2016-07-13 5 views
1

나는이 코드 비트가 작동하지 않는 이유는 누군가가 명확한 용어로 설명 할 수 있는지 궁금 :php simplexml이 addChild를 허용 하나 다른 하나는 허용하지 않는 이유는 무엇입니까?

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> 

...하지만이 비트의 :이 출력 결과

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

... 코드를 수행합니다

$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를 허용하고 다른 객체가 동일한 속성을 공유하지 않는다는 것입니다 아니.

이 경우 이미 코드를 작동시키는 방법을 찾았지만 실제로 작동하는 이유를 이해하고 싶습니다.


편집 : 네임 스페이스가 PHPs 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