Элемент ‘foo’: этот элемент не ожидается. Ожидается ({http://www.example.com} foo)

При попытке проверить объект PHP DOMDocument по схеме, используя метод schemaValidate, генерируется следующее предупреждение:

Предупреждение: DOMDocument :: schemaValidate (): Элемент ‘foo’: Этот элемент
неожиданно. Ожидается ({http://www.example.com} foo). в X на
линия Y

Это происходит только с элементами, которые были добавлены в DOMDocument. Я подготовил следующий фрагмент кода и схему, чтобы каждый мог мгновенно протестировать:

Snippet:

$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'));

Схема:

<?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>

Я не вижу разницы между foo и bar, кроме того, что foo был добавлен методом appendChild, а bar добавлен методом loadXML.

Проверка возвращает ложь (что означает ошибку проверки). При загрузке foo с помощью метода loadXML ошибка прекращается, но это определенно не является решением, поскольку во многих случаях XML-файл необходимо создавать динамически.

Appe Почему добавление элемента вызывает эту ошибку проверки и как ее решить?

3

Решение

Элемент <foo> то, что вы создаете, «отсутствует» в пространстве имен и, следовательно, в пространстве пустых имен.

Пространство имен также является частью, которую вы видите в фигурных (или угловых) скобках в сообщении об ошибке:

  {http://www.example.com}foo
`----------------------´`-´
namespace      name

Вместо createElement использование createElementNS и предоставьте пространство имен рядом с именем элемента.

Сохраняя созданный документ в формате XML (чтобы проверить его вручную, например, посмотрев на него), вы совершенно правы в том, что элемент кажется быть как <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>

Но он был просто добавлен туда с его пустым пространством имен (следовательно, вставлен с небольшим количеством пространств имен вокруг), и в памяти элемент все еще не имеет пространства имен — и проверка находится в памяти.

Вот полный пример с проверкой в ​​действии:

<?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));

Выход:

<?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)
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]