2016-07-13 26 views
1

我不知道是否有人能清晰的術語解釋爲什麼這段代碼不工作:爲什麼PHP的simplexml允許addChild在這些例子之一中,但不是其他的例子?

<?php 
$base = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . 
    '<ns:RootNode xmlns:ns="http://www.bogus.com/bogus/">' . 
    '<ns:RequestHeader/>' . 
    '<ns:ContractInfo/>' . 
    '</ns:RootNode>' . "\n"; 
$xml = simplexml_load_string($base); 
$header = $xml->RequestHeader; 

echo get_class($header) . "\n"; 

$header->addChild('SourceID', '123456'); 
echo $xml->asXML() . "\n\n"; 

......造成這種輸出:

SimpleXMLElement 
PHP Warning: SimpleXMLElement::addChild(): Cannot add child. Parent is not 
a permanent member of the XML tree in 
C:\yadayada\test.php on line 12 

Warning: SimpleXMLElement::addChild(): Cannot add child. Parent is not a permanent member of the XML tree in 
C:\yadayada\test.php on line 12 
<?xml version="1.0" encoding="UTF-8"?> 
<ns:RootNode xmlns:ns="http://www.bogus.com/bogus/"><ns:RequestHeader/><ns:ContractInfo/></ns:RootNode> 

...但是這一點代碼的作用:

$base = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . 
    '<ns:RootNode xmlns:ns="http://www.bogus.com/bogus/">' . 
    '<ns:ContractInfo/>' . 
    '</ns:RootNode>' . "\n"; 
$xml = simplexml_load_string($base); 
$header = $xml->addChild('RequestHeader'); 

echo get_class($header) . "\n"; 

$header->addChild('SourceID', '123456'); 
echo $xml->asXML() . "\n\n"; 

......造成這種輸出:

SimpleXMLElement 
<?xml version="1.0" encoding="UTF-8"?> 
<ns:RootNode xmlns:ns="http://www.bogus.com/bogus/"><ns:ContractInfo/><ns:RequestHeader><ns:SourceID>123456</ns:SourceID></ns:RequestHeader></ns:RootNode> 

基本上我能看到的唯一區別是,在第二種情況下,我將節點添加到根元素,並在第一個示例中,我將它們添加到子元素。

我已閱讀了PHP.net上的相關SimpleXML文檔,它使用的例子更像第二個,但我沒有看到明確禁止第一種方法的任何內容。我還發現了一些討論類似問題的SO文章,但沒有一篇真正解釋了爲什麼我不能直接使用SimpleXML將子節點添加到現有節點。

我覺得奇怪的是,在這兩種情況下,代碼試圖修改的對象都是相同的類型SimpleXMLElement,但它們顯然不共享相同的屬性,因爲一個允許addChild,另一個允許不。

在這種情況下,我已經找到了一種方法來使我的代碼有效,但我真的很想理解它爲什麼會這樣工作。


編輯:

由於譁鬼爲指出的命名空間沒有被自動脈動熱管的SimpleXML處理器處理。 Kevin Yank建議對代碼稍作修改,使其正常工作。該生產線

$header = $xml->RequestHeader; 

成爲

$header = $xml->children('http://www.bogus.com/bogus/')->RequestHeader; 

問題解決了,與子節點在正確的命名空間中未添加額外的工作獎金:

SimpleXMLElement 
<?xml version="1.0" encoding="UTF-8"?> 
<ns:RootNode xmlns:ns="http://www.bogus.com/bogus/"><ns:RequestHeader><ns:Source 
ID>123456</ns:SourceID></ns:RequestHeader><ns:ContractInfo/></ns:RootNode> 

回答

2

在你的第一個實例,你重新考慮$xml->RequestHeader是指源中的<ns:RequestHeader/>節點,但它不是。你可以用$xml->asXML()的輸出中沒有任何改變的假名稱;因此,當您嘗試添加一個孩子時,您會收到警告,因爲$header實際上並不是您的$xml樹的成員。

在第二種情況下,你直接將孩子的$xml樹被解析,讓您得到任何警告:

$header = $xml->addChild('RequestHeader'); 

看來,SimpleXML的->運營商的目的不是要理清您的ns:標誌。如果從$base

$base = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . 
    '<RootNode xmlns="http://www.bogus.com/bogus/">' . 
    '<RequestHeader/>' . 
    '<ContractInfo/>' . 
    '</RootNode>' . "\n"; 
$xml = simplexml_load_string($base); 
$header = $xml->RequestHeader; 

$header->addChild('SourceID', '123456'); 
echo $xml->asXML() . "\n\n"; 

這就提出任何警告

+0

謝謝你刪除你的第一個代碼塊的工作,你是絕對正確的。我看了很長一段時間,從來沒有想到名字空間讓我感到困惑。有時你需要第二雙眼睛。 :-)真正令人誤解的部分是,get_class將$ header元素顯示爲SimpleXMLElement,這使我相信它正在查找元素,但無法修改它。再次感謝。 – Gundark

相關問題