PHP xmllib XSD 验证命名空间错误:没想到 X,预期 X

我一直在尝试让 xmllib 通过 合作并验证 xmldsig<Signature>元素DOMDocument,但无论我如何将元素扔给它,它都会不断产生虚假错误。显然,由于而无法<Signature>成为 root 。我无法正确设置根上的属性:尝试验证结果:DOMDocumentxmlns


Element 'Signature': No matching global declaration available for the validation root. 

我认为这可能是因为模式旨在“包含”,您毕竟想要签署“某些东西”,而不仅仅是本身签名。因此,通过创建这个:


<?xml version="1.0"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

    xmlns:ds="http://www.w3.org/2000/09/xmldsig#"

    version="1.0"

    elementFormDefault="qualified">

<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd" />

<xs:element name="root">

    <xs:complexType>

        <xs:sequence>

            <xs:element ref="ds:Signature" />

        </xs:sequence>

    </xs:complexType>

</xs:element>

</xs:schema>

我现在可以拥有虚拟元素的包含签名。


我意识到 PHP XML 处理相当糟糕,没有一个工具真正工作得那么好。然而,一旦它实际上正确地将事情交给 xmllint,这样做应该没有问题。其他答案建议也添加 XPath,但我想保持 KISS;尽可能少地使用 PHP 库。


通过几百行代码的欺骗,我让它配合并将<Signature>xml 文件的一部分包装到一个<root>元素内的普通测试文件中。


我认为它正在做一些事情来破坏文档中的名称空间。$myDocument->saveXML();失败后调用$myDocument->schemaValidate();会返回一个特殊的结果:


Element 'Signature': This element is not expected. Expected is ( {http://www.w3.org/2000/09/xmldsig#}Signature ).

当 xml 看起来像这样时(我已经添加了格式;实际情况是未格式化的;尽管空格不应该很重要):


<?xml version="1.0"?>

<root>

    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">

         (... omitted crypto ...)

    </Signature>

</root>

从我对它所做的阅读来看,该错误应该意味着<Signature> 元素上的命名空间是错误的。但在这里,它明确地明确指定为xmlns错误消息所期望的内容。那么,这里出了什么问题呢?


附录:准备签名进行验证的代码(在任意文档中)看起来像这样。这是一个复杂的版本,我添加了一个“根”元素,而不是直接使用模式,请参阅下面的我的答案,结果证明这是不必要的,尽管这是一个很好的测试,就像在您想要的更复杂的场景中一样要在对 libxml 的一次调用中验证签名的内容,这是一件有效的事情:


慕沐林林
浏览 107回答 1
1回答

MM们

PHP 就是问题所在。它存在微妙的错误,并且不会/不能正确理解以编程方式创建的文档中的 XML 名称空间。添加/编辑 DOMDocument 元素的方法有多种,其中一些/大部分可能会导致元素E位于某个名称空间X中,当您仅查看 XML 输出时,但 DOMDocument 对象认为它位于名称空间Y中。即使您只使用提供的函数而不访问对象的内部,也可能使它们处于不一致的状态。在某些情况下,如果您想要特定格式的命名空间(由于规范化问题)甚至是不可避免的。替换该行代码$myDocument->schemaValidate();和$myDocument->loadXML($myDocument->saveXML()); $myDocument->schemaValidate();并且验证错误应该消失。无论哪种方式(使用xsd包含的自定义或直接使用 xmldsig 验证文件)都应该有效。虽然该错误被视为“不是错误”,但它确实是一个问题,因为DOMDOcument实际上不会使用xmlns属性输出确切的语法,而是使用前缀表示法(如果您使用createElementNS(). (虽然语法上可能是相同的,但没有人理解 xml 命名空间,因此接受您的 XML 的人可能希望它与示例完全相同,即:使用 ,而xmlns不是使用元素ds:Signature)。相反, usingDOMElement::setAttributeNS($currentNS, 'xmlns', $subElementNS) 会输出默认命名空间标记,但不会使用新命名空间正确递归地标记元素下的编程实体。
打开App,查看更多内容
随时随地看视频慕课网APP