2015-04-28 1 views
3

При попытке проверки объекта PHP DOMDocument против схемы с использованием метода schemaValidate, следующее предупреждение генерируется:Элемент 'foo': этот элемент не ожидается. Ожидаемый есть ({http://www.example.com} Foo)

Предупреждения: DOMDocument :: schemaValidate(): Element '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, был добавлен с помощью метода appendChild, тогда как панель добавлена ​​с помощью метода loadXML.

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

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

ответ

1

Элемент <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> 

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

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

<?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) 
+0

я не заметил, потому что только с помощью пространства имен по умолчанию. Но спасибо, не знал, что необходимо указать пространство имен в этом случае. – mikl

+1

Да, о части, которая * не * очевидна из взгляда на XML (у меня было это короткое и неправильное в моей первой ревизии ответа) Я добавил лучшее объяснение (надеюсь!).Я также разместил код-пример, демонстрирующий его в действии. – hakre