2015-04-28 18 views
3

當試圖通過使用schemaValidate方法以驗證針對模式的PHP DOMDocument對象,正在生成下一個警告:元素'foo':該元素不是預期的。預期是({http://www.example.com}富)

警告:DOM文檔:: schemaValidate():元素'foo':該元素不爲 。預期是({foo})。在X上 行Y

它只發生在已附加到DOMDocument的元素上。我準備了下面的代碼片段和模式,使任何人都可以立即測試:

段:

$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方法的bar。

驗證返回false(這意味着驗證錯誤)。當使用loadXML方法加載foo時,錯誤停止發生,但這肯定不是解決方案,因爲在很多情況下需要動態創建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

相關問題