我用SimpleXML解析了一个XML并希望截断它。这是方法:
public function truncate(SimpleXMLElement $xml)
{
foreach ($xml->children() as $key => $value)
{
if ( !empty($key) && isset($xml->$key))
{
echo "unset $key";
unset($xml->$key);
}
}
echo $xml->asXML();
exit;
}
在第一次未设置之后,它抛出了这个:
警告:pat \ Persistence \ File \ Text \ XML :: truncate():第36行的pat / Persistence / File / Text / XML.php中不再存在节点
好吧,我不想取消该方法。
答案 0 :(得分:2)
simplexml中的错误消息“节点不再存在”表示您正在尝试删除不再存在的节点。
正如您已经注意到,这在第一次迭代中未发生,但在后续迭代中不会发生。如果您现在想象 SimpleXMLElement::children()
返回一个数组,其中子项的从零开始的索引作为键,子元素节点作为值,请考虑以下内容以便更好地理解:
你有一个有两个孩子的元素。因此children()
函数返回一个包含两个数组的数组。
$children = [ 0 => <child1>, 1 => <child2> ]
^ unset($xml->{0});
`-----------------^
$xml->children() = [ 0 => <child1>, 1 => <child2> ]
现在删除第一个子元素,索引为0.
第二个孩子还在那里:
$xml->children() = [ 0 => <child2> ]
但是因为你按照他们的号码访问了孩子,并且第一个孩子被删除了,所以第二个孩子获得了一个新的索引:从之前的1开始现在为0.但是你在索引1取消了孩子:
$children = [ 0 => <child1>, 1 => <child2> ]
^ unset($xml->{1});
`-----------------^
$xml->children() = [ 0 => <child2> ]
不再存在:
节点不再存在
查看错误消息?那怎么解决呢? SimpleXML中的一种常见方法是在该问题中使用hakre概述的simplexml self-reference:
unset($value[0]);
如您所见,它不需要使用任何密钥。另一种选择是你反向子数组并从结尾处取消设置,而不是从头开始。这样你就不会把索引拉到脚下了:
$children = array_reverse($xml->children());
foreach ($children as $key => $value) {
...
unset($xml->$key);
}
}
但是自引用可能更容易使用,因为它也适用于你想在simplexml中取消设置某些内容的其他情况,因此值得你接受well-explained read over there。
完整的例子一目了然:
public function truncate()
{
$xml = $this->_xml;
$children = $xml->children();
foreach ($children as $index => $child)
{
if ($index) {
unset($child[0]);
}
}
$xml->asXML('php://output');
exit;
}
我还会说exit
不属于那个方法,但是我把它留在了,所以你可以更好地定位。相反,该方法应该只是输出截断的XML而不关心结束脚本。在调用方法之后将其移出并放置,因为这是两种不同的任务:一种是XML处理和输出,另一种是程序流。
答案 1 :(得分:0)
您是前辈的孩子,但如果您想删除空的孩子,请从父母那里删除 尝试这样的事情:
foreach ($xml->children() as $child)
{
if (empty($child)) {
unset($child[0]);
}
}
echo $xml->asXML();