gpt4 book ai didi

php - 对 XPath 查询使用 XSD 模式验证

转载 作者:行者123 更新时间:2023-12-04 11:18:16 26 4
gpt4 key购买 nike

我正在使用以下代码创建一个 DOMDocument 并针对外部 xsd 文件对其进行验证。

<?php

$xmlPath = "/xml/some/file.xml";
$xsdPath = "/xsd/some/schema.xsd";

$doc = new \DOMDocument();
$doc->loadXML(file_get_contents($xmlPath), LIBXML_NOBLANKS);

if (!$doc>schemaValidate($xsdPath)) {
throw new InvalidXmlFileException();
}
更新 2(重写的问题)
这很好用,这意味着如果 XML 与 XSD 的定义不匹配,它将抛出一个有意义的异常。
现在,我想使用 Xpath 从 DOMDocument 中检索信息。它也可以正常工作,但是,从这一点开始,DOMDocument 与 XSD 完全分离!例如,如果我有一个 DOMNode我不知道它是否属于 simpleType 类型或输入 complexType .我可以检查该节点是否有子节点( hasChild() ),但这不一样。此外,XSD 中还有大量信息(例如,最小和最大出现次数等)。
真正的问题是,我是否必须自己查询 XSD,或者是否有编程方式来询问这类问题。 IE。这是 DOMNode复杂的还是简单的类型?
another post有人建议“使用真正的模式处理器处理模式,然后使用其 API 来询问有关模式内容的问题”。 XPath 是否具有用于检索 XSD 信息的 API,或者是否有与 DOMDocument 不同的便捷方式?
为了记录,原来的问题
现在,我想继续使用 XPath 解析来自 DOMDocument 的信息。为了提高我存储到数据库的数据的完整性并向客户端提供有意义的错误消息,我希望不断使用模式信息来验证查询。 IE。我想根据 xsd 中定义的允许子节点验证获取的子节点。我想通过在 xsd 文档上使用 XPath 来实现。
但是,我偶然发现了 this post .它基本上说这是你自己的一种古怪方式,你应该使用真正的模式处理器并使用它的 API 来进行查询。如果我理解正确,我正在使用带有 schemaValidate 的真实模式处理器。 ,但是使用它的 API 是什么意思呢?
我有点猜到我没有以正确的方式使用模式,但我不知道如何研究正确的用法。
问题
如果我使用 schemaValidate在 DOMDocument 上是一次性验证(真或假)还是与 DOMDocument 绑定(bind)更长时间?准确地说,我是否可以使用验证也以某种方式添加节点,或者我可以使用它来选择我感兴趣的节点,如引用的 SO 帖子所建议的那样?
更新
这个问题被评为不清楚,所以我想再试一次。假设我想添加一个节点或编辑一个节点值。我可以使用 xsd 中提供的模式来验证用户输入吗?最初,为了做到这一点,我想使用另一个 XPath 实例手动查询 xsd 以获取某个节点的规范。但正如链接文章中所建议的,这不是最佳实践。所以问题是,DOM 库是否提供任何 API 来进行此类验证?
也许我想多了。也许我只是添加节点并再次运行验证,看看它在哪里/为什么会中断?在这种情况下,自定义错误处理的答案将是正确的。你确定吗?

最佳答案

您的问题不是很清楚,但听起来您想获得有关任何架构验证失败的详细报告。而DomDocument::validateSchema() only returns a boolean ,您可以使用内部libxml函数以获取更详细的信息。

我们可以从您的原始代码开始,只更改顶部的一件事:

<?php
// without this, errors are echoed directly to screen and/or log
libxml_use_internal_errors(true);
$xmlPath = "file.xml";
$xsdPath = "schema.xsd";

$doc = new \DOMDocument();
$doc->loadXML(file_get_contents($xmlPath), LIBXML_NOBLANKS);

if (!$doc->schemaValidate($xsdPath)) {
throw new InvalidXmlFileException();
}

然后我们可以在异常中发生有趣的事情,这可能(基于您提供的代码)在代码中更高的位置捕获。
<?php

class InvalidXmlFileException extends \Exception
{
private $errors = [];

public function __construct()
{
foreach (libxml_get_errors() as $err) {
$this->errors[] = self::formatXmlError($err);
}
libxml_clear_errors();
}

/**
* Return an array of error messages
*
* @return array
*/
public function getXmlErrors(): array
{
return $this->errors;
}

/**
* Return a human-readable error message from a libxml error object
*
* @return string
*/
private static function formatXmlError(\LibXMLError $error): string
{
$return = "";
switch ($error->level) {
case \LIBXML_ERR_WARNING:
$return .= "Warning $error->code: ";
break;
case \LIBXML_ERR_ERROR:
$return .= "Error $error->code: ";
break;
case \LIBXML_ERR_FATAL:
$return .= "Fatal Error $error->code: ";
break;
}

$return .= trim($error->message) .
"\n Line: $error->line" .
"\n Column: $error->column";

if ($error->file) {
$return .= "\n File: $error->file";
}

return $return;
}
}

所以现在当你捕捉到你的异常时,你可以迭代 $e->getXmlErrors() :
try {
// do stuff
} catch (InvalidXmlFileException $e) {
foreach ($e->getXmlErrors() as $err) {
echo "$err\n";
}
}

对于 formatXmlError函数我刚刚从 the PHP documentation 复制了一个示例它将错误解析为人类可读的内容,但没有理由不能返回一些结构化数据或任何你喜欢的东西。

关于php - 对 XPath 查询使用 XSD 模式验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58079262/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com