开发者

PHP SimpleXML: Remove items with for

开发者 https://www.devze.com 2023-02-05 15:22 出处:网络
I just can remove an item from a simpleXML element with: unset($this->simpleXML->channel->item[0]);

I just can remove an item from a simpleXML element with:

unset($this->simpleXML->channel->item[0]);

but I can't with the a for:

    $items = $this->simpleXML->xpath('/rss/channel/item');
    for($i = count($items); $i > $itemsNumber; $i--) {
        unset($items[$i - 1]);
    }

some items are removed from $items (Netbeans Debug can confirm that) but when I get 开发者_Go百科the path again (/rss/channel/item) nothing was deleted.

What's wrong?


SimpleXML does not handle node deletion, you need to use DOMNode for this. Happily, when you import your nodes into DOMNode, the instances point to the same tree.

So, you can do that :

<?php

$items = $this->simpleXML->xpath('/rss/channel/item');
foreach ($items as $item) {
    $node = dom_import_simplexml($item);
    $node->parentNode->removeChild($node);
}


You're currently only, as you know, unsetting the item from the array.

To get the magical unsetting to work on the SimpleXMLElement, you have to either do as Xavier Barbosa suggested or give PHP a little nudge into firing off the correct unsetting behaviour.

The only change in the code snippet below is the additions of [0]. Heavy emphasis on the word magical.

$items = $this->simpleXML->xpath('/rss/channel/item');
for($i = count($items); $i > $itemsNumber; $i--) {
    unset($items[$i - 1][0]);
}

With that said, I would recommend (as Xavier and Josh have) moving into DOM-land for manipulating the document.


Well I was racking my brain trying to figure out how to delete the last child from an xml document. Then I insert a new element at the top. This way there is always a set amount of items in my rss feed. I could not get the xpath stuff to work. That could be because of the free server I am using but anyways. This is what I did. My xml document is an rss feed so I have 6 elements before the items start. ie. title,description under the channel. $file = 'newrss.xml';//get file

$fp = fopen($file, "rb") or die("cannot open file");//open the file
$str = fread($fp, filesize($file));//read the file

$xml = new DOMDocument();//new xml DOMDocument
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$xml->loadXML($str) or die("Error");//Load Document
// get document element
$root   = $xml->documentElement;
$fnode  = $root->firstChild;
$ori    = $fnode->childNodes->item(6);//The 6th item starts the item nodes
//Get the number of items in my xml.
$nodeLength = $fnode->getElementsByTagName('item')->length;//count nodes
$itemNum=$nodeLength+5;//I added 5 so it starts from the first item
$lNode  = $fnode->childNodes->item($itemNum);//Get the last child node
$fnode->removeChild($lNode);//finally remove that node.

I know this is not pretty but it works good. It took me forever to figure this out so I hope it will help someone else since I see this question a lot. If you are not interested in adding your new item to the top of the rss list then you could skip the $ori variable. Furthermore if you do leave out the $ori variable you will have to adjust the $itemNum so you remove the correct item.

0

精彩评论

暂无评论...
验证码 换一张
取 消