为什么 php simplexml 在其中一个示例中允许 addChild 而在另一个示例中不允许?
Why php simplexml allow addChild in one of these examples but not the other?
我想知道是否有人可以清楚地解释为什么这段代码不起作用:
<?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 文章,但是 none 真正解释了为什么我不能使用 SimpleXML 直接将子节点添加到现有节点。
我觉得奇怪的是,在这两种情况下,代码试图修改的对象都是同一类型,SimpleXMLElement,但它们显然不共享相同的属性,因为一个允许 addChild,另一个允许没有。
在这种情况下,我已经找到了让我的代码正常工作的方法,但我真的很想了解它为什么会这样工作。
编辑:
感谢 BeetleJuice 指出命名空间未由 PHP 的 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>
在您的第一个实例中,您认为 $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";
这不会引发警告
我想知道是否有人可以清楚地解释为什么这段代码不起作用:
<?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 文章,但是 none 真正解释了为什么我不能使用 SimpleXML 直接将子节点添加到现有节点。
我觉得奇怪的是,在这两种情况下,代码试图修改的对象都是同一类型,SimpleXMLElement,但它们显然不共享相同的属性,因为一个允许 addChild,另一个允许没有。
在这种情况下,我已经找到了让我的代码正常工作的方法,但我真的很想了解它为什么会这样工作。
编辑:
感谢 BeetleJuice 指出命名空间未由 PHP 的 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>
在您的第一个实例中,您认为 $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";
这不会引发警告