简体   繁体   English

为什么\\ DomDocument#schemaValidate()对有效的XML发出警告?

[英]Why does \DomDocument#schemaValidate() give warning for valid XML?

I have built a \\DomDocument in PHP which I'd like to validate against an XSD file. 我在PHP中建立了一个\\ DomDocument,我想针对一个XSD文件进行验证。 I've checked in more online XML-XSD validator and my XML passed validation on all of them. 我已经签入了更多的在线XML-XSD验证器,并且我的XML通过了所有验证器。 What am I doing wrong? 我究竟做错了什么? Why my XML passes other validators but not when calling schemaValidate on the DomDocument itself? 为什么在DomDocument本身上调用schemaValidate时,我的XML为什么不通过其他验证器?

This is the piece of PHP code that generates the XML: 这是一段生成XML的PHP​​代码:

    $xmlDoc = new \DOMDocument('1.0', 'UTF-8');
    $rootElem = $xmlDoc->createElementNS('http://fip.loginet.hu', 'allatok');

    /** @var RearingAnimal $animal */
    foreach($this->animals as $animal){
        $animalElem = $xmlDoc->createElement('allat');
        $animalElem->appendChild($xmlDoc->createElement('fulszam', $animal->getEarNumber()));
        $animalElem->appendChild($xmlDoc->createElement('tenyeszet', $animal->getRearingCode()));
        $animalElem->appendChild($xmlDoc->createElement('szuletesi_ido', $animal->getBirthDate()));
        $animalElem->appendChild($xmlDoc->createElement('fajta', $animal->getBreed()));
        $animalElem->appendChild($xmlDoc->createElement('ivar', $animal->getSex()));

        $rootElem->appendChild($animalElem);
    }

    $xmlDoc->appendChild($rootElem);

    if(!$xmlDoc->schemaValidate($this->getXsdFileName())){
        throw new \Exception("XML Socument validation failed!");
    }

XSD: XSD:

<schema 
     attributeFormDefault="unqualified" 
     elementFormDefault="qualified" 
     targetNamespace="http://fip.loginet.hu"                   
     xmlns="http://www.w3.org/2001/XMLSchema" 
     xmlns:tns="http://fip.loginet.hu">
<element name="allatok">
    <complexType>
        <sequence>
            <element name="allat" minOccurs="0" maxOccurs="unbounded" type="tns:Allat"/>
        </sequence>
    </complexType>
</element>
<complexType name="Allat">
    <sequence>
        <element name="fulszam" type="string"/>
        <element name="tenyeszet" type="integer"/>
        <element name="szuletesi_ido" type="date"/>
        <element name="fajta" type="integer"/>
        <element name="ivar" type="tns:Ivar"/>
    </sequence>
</complexType>
<simpleType name="Ivar">
    <restriction base="string">
        <enumeration value="m"/>
        <enumeration value="f"/>
    </restriction>
</simpleType>

And the XML i'd like to validate against: 我想针对的XML进行验证:

<?xml version="1.0" encoding="UTF-8"?>
<allatok xmlns="http://fip.loginet.hu">
    <allat>
        <fulszam>HU 30966 0259 0</fulszam>
        <tenyeszet>4737016</tenyeszet>
        <szuletesi_ido>2016-09-03</szuletesi_ido>
        <fajta>1</fajta>
        <ivar>m</ivar>
    </allat>
    <allat>
        <fulszam>HU 31342 0375 1</fulszam>
        <tenyeszet>4737016</tenyeszet>
        <szuletesi_ido>2016-03-21</szuletesi_ido>
        <fajta>2</fajta>
        <ivar>m</ivar>
    </allat>
    <allat>
        <fulszam>HU 31342 4595 1</fulszam>
        <tenyeszet>4737016</tenyeszet>
        <szuletesi_ido>2016-03-21</szuletesi_ido>
        <fajta>2</fajta>
        <ivar>m</ivar>
    </allat>
</allatok>

The error I get: 我得到的错误:

Warning: DOMDocument::schemaValidate(): Element 'allat': This element is not expected. Expected is ( {http://fip.loginet.hu}allat )

UPDATE: 更新:

I figured out, that the warning can be fixed if I use $xmlDoc->createElementNS and pass the namespace individually everywhere, instead of using $xmlDoc->createElement . 我发现,如果我使用$xmlDoc->createElementNS并分别将命名空间传递到任何地方,而不是使用$xmlDoc->createElement ,则可以修复警告。 However the output of the both is the same XML string. 但是,两者的输出都是相同的XML字符串。 However the xmlns definition of the 'allatok' element should apply to all descendant elements until stated else... so I solved it, but I'm still curious if someon could explain this behavior? 但是, 'allatok'元素的xmlns定义应适用于所有后代元素,除非另有说明...所以我解决了它,但是我仍然好奇有人能解释这种行为吗?

The namespace aware methods (like DOMDocument::createElementNS() ) create an node in the provided namespace. 支持名称空间的方法(如DOMDocument::createElementNS() )在提供的名称空间中创建一个节点。 They set the namespaceURI property, the other methods do not. 他们设置了namespaceURI属性,而其他方法则没有。

So the node is not in the expected namespace and the XML does not match the schema. 因此,该节点不在预期的名称空间中,并且XML与架构不匹配。 Here is a small demo: 这是一个小演示:

$document = new \DOMDocument();
$foo = $document->appendChild($document->createElementNS('urn:foo', 'f:foo'));
$foo->appendChild($document->createElementNS('urn:foo', 'f:bar'));
$foo->appendChild($document->createElement('f:bar'));

echo "after create\n";
foreach ($document->documentElement->childNodes as $bar) {
    echo '{'.$bar->namespaceURI.'}'.$bar->localName, "\n";
}

Output: 输出:

after create 
{urn:foo}bar 
{}f:bar 

Using the non namespace aware methods you can create an DOM that will serialize to the same XML string - even if the node was created without namespaces. 使用不了解名称空间的方法,您可以创建一个将序列化为相同XML字符串的DOM-即使该节点是在没有名称空间的情况下创建的。

echo $xml = $document->saveXML();

Output: 输出:

<?xml version="1.0"?> 
<f:foo xmlns:f="urn:foo"><f:bar/><f:bar/></f:foo>

Now if that document is loaded the parser will resolve the namespaces and both bar nodes are in the expected namespace. 现在,如果该文档已加载,则解析器将解析名称空间,并且两个bar节点都位于预期的名称空间中。

$document->loadXML($xml);

echo "after load\n";
foreach ($document->documentElement->childNodes as $bar) {
    echo '{'.$bar->namespaceURI.'}'.$bar->localName, "\n";
}

Output: 输出:

after load 
{urn:foo}bar 
{urn:foo}bar

I suggest using the namespace aware methods if you create an XML with namespaces. 如果创建带有名称空间的XML,建议使用名称空间感知方法。 As for why the node can not inherit the namespace of the parent. 至于为什么节点不能继承父级的命名空间。 It exists before that (after the create) and only gets a parent if you append/insert it. 它在此之前(在创建之后)存在,并且只有在您追加/插入它时才获得父项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 DOMDocument :: schemaValidate()抛出警告错误 - DOMDocument::schemaValidate() throwing warning errors 为什么相同XML和XSD文件上的DOMDocument :: schemaValidate()有时执行时间比平时高得多? - Why DOMDocument::schemaValidate() over the same XML and XSD files have sometimes a execution time dramatically higher than usual? 当架构无效时,如何禁用DOMDocument :: schemaValidate()生成的警告? - How to disable warning produced by DOMDocument::schemaValidate() when the schema is invalid? DOM文档不加载一个较大的有效xml文件 - DOMDocument does not load a larger valid xml file 如何在PHP中使用schemaValidate()验证XML时将警告消息作为字符串获取? - How to get the warning message as a string when validating XML with schemaValidate() in PHP? PHP DOMDocument schemaValidate但获取类型 - PHP DOMDocument schemaValidate but get type DOMDocument :: schemaValidate()超出允许的最大长度&#39;255&#39; - DOMDocument::schemaValidate() exceeds the allowed maximum length of '255' CakePHP Xml实用程序库触发DOMDocument警告 - CakePHP Xml utility library triggers DOMDocument warning 使用 DOMDocument 加载 xml 时出现警告 - Warning while load xml using the DOMDocument 为什么DomDocument getElementsByTagName会返回一半NodeList? - Why DomDocument getElementsByTagName give back an half NodeList?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM