PHP实现删除XML文件中指定item父节点的问题
问题:删除XML文件中的item节点
我尝试从现有XML文件中删除所有<item>节点,保留<channel>下的基础节点。
原XMLfile1.xml
<?xml version="1.0"?> <rss> <channel> <title>Main Website</title> <link>siteurl</link> <item> <item_type>Product</item_type> <title>abcd</title> <sku>TESTsku</sku> <id>919031</id> <short_description><![CDATA[]]></short_description> <description><![CDATA[]]></description> <link>siteurl</link> <availability>Out of Stock</availability> <price>21.81 CAD</price> <sale_price>21.81 CAD</sale_price> <categories> <category/> </categories> <attributes> </item> </channel> </rss>
期望得到的XMLfile1.xml
<?xml version="1.0"?> <rss> <channel> <title>Main Website</title> <link>siteurl</link> </channel> </rss>
已尝试的代码
$xmlBase = <<<XML <?xml version="1.0"?> <rss> <channel> <title>Main Website</title> <link>siteurl</link> </channel> </rss> XML; $status = 1; if ($status == 1) { $entitiesXML = new \SimpleXMLElement('XMLfile1.xml'); } else { $entitiesXML = new \SimpleXMLElement($xmlBase); } $fileExist = 'XMLfile1.xml'; if (file_exists($fileExist)) { $doc1 = new \DOMDocument('1.0'); $doc1->loadXML($entitiesXML->asXML()); $elements = $doc1->getElementsByTagName('channel'); // $root = $doc1->firstChild; $nodes_to_insert = array(); $nodes_to_remove = array(); foreach($elements->childNodes as $item) { if($item->nodeName != "item") { continue; } $nodes_to_remove[] = $item; } foreach($nodes_to_remove as $node) { $elements->removeChild($node); } $doc1->saveXML(); }
我还尝试了基于DOMXpath的多种解决方案,但都无法成功删除<item>元素。
解决方案
你的代码存在几个关键问题,修正后即可实现需求:
getElementsByTagName('channel')返回的是DOMNodeList节点集合,不能直接遍历其childNodes,需先获取单个<channel>节点;- 遍历子节点时需注意过滤文本节点(如换行、空格),准确识别
<item>节点; saveXML()仅生成XML字符串,需用save()方法将修改后的内容写入原文件。
修正后的DOMDocument实现
$filePath = 'XMLfile1.xml'; if (file_exists($filePath)) { // 直接加载XML文件,无需通过SimpleXMLElement转换 $doc = new \DOMDocument('1.0'); $doc->preserveWhiteSpace = false; // 可选:清理冗余空白 $doc->formatOutput = true; // 可选:格式化输出XML结构 $doc->load($filePath); // 获取所有channel节点(假设XML中只有一个channel) $channels = $doc->getElementsByTagName('channel'); foreach ($channels as $channel) { // 反向遍历子节点,避免正向遍历因节点删除导致索引错乱 for ($i = $channel->childNodes->length - 1; $i >= 0; $i--) { $node = $channel->childNodes->item($i); if ($node->nodeName === 'item') { $channel->removeChild($node); } } } // 将修改后的内容保存回原文件 $doc->save($filePath); }
更简洁的DOMXPath实现
$filePath = 'XMLfile1.xml'; if (file_exists($filePath)) { $doc = new \DOMDocument('1.0'); $doc->preserveWhiteSpace = false; $doc->formatOutput = true; $doc->load($filePath); $xpath = new \DOMXPath($doc); // 精准选中所有channel下的item节点 $items = $xpath->query('//channel/item'); foreach ($items as $item) { // 通过父节点删除当前item $item->parentNode->removeChild($item); } $doc->save($filePath); }
内容的提问来源于stack exchange,提问作者Mohit Rane
相关产品推荐
相关产品推荐

