Element 'foo': This element is not expected. Expected ({http://www.example.com} foo)
When trying to validate a PHP DOMDocument object for a schema using the schemaValidate method, the following warning is generated:
Warning: DOMDocument :: schemaValidate (): Element 'foo': This element is unexpected. Expected ({ http://www.example.com } foo). in X by row Y
This only happens with elements added to the DOMDocument. I have prepared the following code snippet and diagram for anyone to test instantly:
Excerpt:
$template = '
<root
xmlns="http://www.example.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.com schema.xsd"
>
<bar/>
</root>
';
$DD = new DOMDocument();
$DD -> loadXML($template);
$foo = $DD -> createElement('foo');
$DD -> getElementsByTagName('root') -> item(0) -> appendChild($foo);
var_dump(htmlentities($DD -> saveXML()));
var_dump($DD -> schemaValidate(__DIR__ . '/schema.xsd'));
Scheme:
<?xml version="1.0"?>
<xs:schema
targetNamespace="http://www.example.com"
xmlns:SiiDte="http://www.example.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
>
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="bar"/>
<xs:element name="foo"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I don't see any difference between foo and bar, apart from foo, the appendChild method was added and bar was added using the loadXML method.
Validation returns false (which means validation failed). Loading foo with the loadXML method stops the error, but this is definitely not a solution because XML needs to be generated dynamically in many cases.
¿Why is the add-on element generating this validation error and how to resolve it?
source to share
The element <foo>
you are creating is a "missing" namespace and therefore in a null namespace.
The namespace is also the part you see in the curly (or angle) brackets in the error message:
{http://www.example.com}foo
`----------------------´`-´
namespace name
Instead, createElement
use createElementNS
and include a namespace next to the element name.
When you save the generated document in XML format (to validate it manually, for example by looking at it), you are absolutely correct that this element looks like <bar>
:
<?xml version="1.0"?>
<root xmlns="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com schema.xsd">
<bar/>
<foo/></root>
But it's just added there with zero namspace (hence inserted with few namespaces) and in memory the element still has no namespace - and the check is done in memory.
Here's a complete example with validation in action:
<?php
/**
* Element 'foo': This element is not expected. Expected is ( {http://www.example.com}foo )
*
* @link http://stackoverflow.com/a/29925747/367456
*/
$template = <<<XML
<root
xmlns="http://www.example.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.com schema.xsd">
<bar/>
</root>
XML;
$schema = <<<XML
<?xml version="1.0"?>
<xs:schema
targetNamespace="http://www.example.com"
xmlns:SiiDte="http://www.example.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="bar"/>
<xs:element name="foo"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
XML;
$schema = 'data://text/xml;base64,' . base64_encode($schema);
$namespace = 'http://www.example.com';
$doc = new DOMDocument();
$doc->loadXML($template);
$foo = $doc->createElementNS($namespace, 'foo');
$doc->documentElement->appendChild($foo);
echo $doc->saveXML();
var_dump($doc->schemaValidate($schema));
Output:
<?xml version="1.0"?>
<root xmlns="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com schema.xsd">
<bar/>
<foo/></root>
bool(true)
source to share