PHP 5.3.3 无法针对嵌套的 XSD 验证 XML
Posted
技术标签:
【中文标题】PHP 5.3.3 无法针对嵌套的 XSD 验证 XML【英文标题】:PHP 5.3.3 fails to validate XML against nested XSD's 【发布时间】:2010-10-20 18:44:24 【问题描述】:从 php 5.2.8 升级到 5.3.3 后,新的 libxml_disable_entity_loader(false)
函数似乎无法在 Windows 上通过命令行访问网络共享上的 PHP 文件。更具体地说,DOMDocument::schemaValidate()
失败,XSD 文件包含网络共享上其他 XSD 文件的多级嵌套 include()。
下面的示例让我相信,在 PHP 中,对于包含多层嵌套 XSD include() 的 XSD 文件,对 libxml_disable_entity_loader(false)
的函数调用没有得到认可。
我在这里遗漏了什么还是您认为这是 PHP 或可能是 libxml 的错误?
复制:
测试 1(成功):
"C:\PHP\5.3.3\php.exe" -c "C:\PHP\5.3.3\php.ini" "C:\Temp\validate.php"
上面的 Windows 命令行示例使用硬编码路径,而不是 Windows 共享文件夹。
它将在 PHP 5.2.8 和 PHP 5.3.3 中成功回显“通过”。
测试 2(失败):
"C:\PHP\5.3.3\php.exe" -c "C:\PHP\5.3.3\php.ini" "\\192.168.82.99\Deployment\Temp\validate.php"
右键单击您的 C: 驱动器 > 属性 > 共享 > 新共享 > 共享名称:“部署”
在上面的命令行示例中编辑 IP 地址以匹配您的本地计算机。
上面的 Windows 命令行示例使用相同的文件,但通过 Windows 共享文件夹。
在 PHP 5.2.8 中,它将回显“通过”。
在 PHP 5.3.3 中,它将回显“失败”并产生以下关于“加载外部实体失败”和“加载文档失败”的 PHP 警告:
在 PHP 5.3.3 中运行上述命令行示例会产生:
Warning: DOMDocument::schemaValidate(): I/O warning : failed to load external entity "/192.168.82.99/DEPLOYMENT/Temp/grandparent.xsd" in \\192.168.82.99\DEPLOYMENT\Temp\validate.php on line 8
Warning: DOMDocument::schemaValidate(): Element 'http://www.w3.org/2001/XMLSchemainclude': Failed to load the document '/192.168.82.99/DEPLOYMENT/Temp/grandparent.xsd' for inclusion. in \\192.168.82.99\DEPLOYMENT\Temp\validate.php on line 8
Warning: DOMDocument::schemaValidate(): Invalid Schema in \\192.168.82.99\DEPLOYMENT\Temp\validate.php on line 8
failed
需要复制的文件:
将所有这些文件放在“C:\Temp\”(或在命令行示例中更改路径)
validate.php
<?php
chdir(dirname(__FILE__));
libxml_disable_entity_loader(false);
$xmlDoc = new DomDocument();
$xmlDoc->load('sample.xml');
echo $xmlDoc->schemaValidate('child.xsd') ? 'passed' : 'failed';
?>
sample.xml
<?xml version="1.0"?>
<team mascot="cowboys" />
child.xsd
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified" >
<!-- The include below works -->
<xsd:include schemaLocation="parent.xsd" />
<xsd:element name="team" type="baseTeam" />
</xsd:schema>
parent.xsd
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified" >
<!-- The include below fails in PHP 5.3.3 even though libxml_disable_entity_loader(false) is called! -->
<xsd:include schemaLocation="grandparent.xsd" />
<xsd:complexType name="baseTeam">
<xsd:attribute name="mascot" type="mascotNames" use="required" />
</xsd:complexType>
</xsd:schema>
grandparent.xsd
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified" >
<xsd:simpleType name="mascotNames">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="bengals" />
<xsd:enumeration value="cowboys" />
<xsd:enumeration value="patriots" />
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
【问题讨论】:
这可能是libxml2相关的,不是PHP本身的问题。尝试在 PHP 5.2 和 5.3 中使用相同的 libxml 版本。如果问题仍然存在,submit a bug report。 使用 php 5.3.3/winxp/php.net-build 对我来说很好。 【参考方案1】:$dir = dirname(__FILE__) . '/sources/';
$file = $dir . 'data.xml';
$xml = file_get_contents($file);
$doc = new DOMDocument;
$doc->documentURI = $file;
$doc->loadXML($xml);
$doc->xinclude();
echo $doc->schemaValidate($dir . 'child.xsd') ? 'passed' : 'failed';
【讨论】:
以上是关于PHP 5.3.3 无法针对嵌套的 XSD 验证 XML的主要内容,如果未能解决你的问题,请参考以下文章
无法针对xsd架构验证xml doc(无法找到元素'replyMessage'的声明)