取消设置子节点使方法消失

时间:2013-04-30 06:27:37

标签: xml simplexml php

我用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中不再存在节点

好吧,我不想取消该方法。

2 个答案:

答案 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();