2016-07-13 22 views
1

コードのこのビットが動作しない理由を誰かが明確な用語で説明できる場合、私は疑問に思う:php simplexmlがこれらの例の1つでは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> 

基本的に違いは、2番目のケースではルート要素にノードを追加していることです。最初の例では、それらを子要素に追加しています。

私はPHP.netの関連するSimpleXMLのドキュメントを読んでおり、2番目の例のような例を使用していますが、最初のメソッドを明示的に禁止するものは見当たりませんでした。同様の問題について話しているSOの記事もいくつか見つかりましたが、SimpleXMLを使用して既存のノードに子ノードを直接追加できない理由を実際に説明するものはありません。

奇妙なことに、どちらの場合でも、コードが変更しようとしているオブジェクトは、同じタイプのSimpleXMLElementですが、addChildを許可するものと同じプロパティを共有しないことは明らかですない。

この場合、私はすでに自分のコードを動作させる方法を見つけましたが、なぜそれが動作するのか理解したいと思います。


編集:名前空間はPHPSのSimpleXMLプロセッサによって自動的に処理されていなかったことを指摘してビートルジュースに

感謝。 Kevin Yankで示唆されているコードを少し修正すると、正しく動作します。あなたは、あなたの最初のインスタンスで

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

:ライン

$header = $xml->RequestHeader; 

は、子ノードが追加作業なしで正しい名前空間に追加されたことをボーナスで、解決

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

問題となります$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

関連する問題