PHP删除XML指定属性节点 保存后文件无改动问题
问题根因
- 核心问题是你处理的XML根节点声明了默认命名空间
xmlns="http://www.w3.org/2005/Atom",使用DOMXPath查询带默认命名空间的节点时,必须先注册命名空间别名,否则写的XPath路径匹配不到任何节点,删除逻辑自然不会执行,最终输出的文件就和原文件完全一致。 - 你的逻辑匹配规则有疏漏:用
contains(text(), 'NotDelete')是模糊匹配,只要文本里包含这个字符串就会被判定为保留,容易出现误判;同时没处理标签和内容之间的换行、缩进空格,精确匹配时容易因为排版问题匹配失败。 - 你当前提供的测试XML里,唯一的
<brand>节点内容就是NotDelete,本身就符合保留条件,就算XPath写对,跑这个测试用例也不会产生删除操作。 - 需求描述和代码逻辑不匹配:你提到要判断「brand属性值」,但实际XML里
NotDelete是<brand>子节点的文本内容,不是节点属性。
修正代码
场景1:删除不符合保留规则的<brand>节点本身
<?php $resp = file_get_contents('EXAMPLE.COM'); $doc = new DomDocument('1.0'); $doc->formatOutput = true; $doc->loadxml($resp); $xpath = new DOMXPath($doc); // 注册XML默认命名空间,前缀名可自定义,这里用atom $xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom'); // 用normalize-space忽略文本前后的换行、空格,做精确匹配 $toDeleteBrandNodes = $xpath->evaluate("/atom:feed/atom:entry/atom:brand[not(normalize-space(.)='NotDelete')]"); foreach ($toDeleteBrandNodes as $node) { $node->parentNode->removeChild($node); } $doc->save('test1.xml');
场景2:删除brand值不符合规则的整个<entry>节点
如果你的需求是删掉整条不符合要求的商品entry,而不是只删brand节点,直接调整XPath匹配entry即可:
<?php $resp = file_get_contents('EXAMPLE.COM'); $doc = new DomDocument('1.0'); $doc->formatOutput = true; $doc->loadxml($resp); $xpath = new DOMXPath($doc); $xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom'); // 直接筛选brand不符合保留规则的entry节点 $toDeleteEntryNodes = $xpath->evaluate("/atom:feed/atom:entry[not(normalize-space(atom:brand)='NotDelete')]"); foreach ($toDeleteEntryNodes as $entry) { $entry->parentNode->removeChild($entry); } $doc->save('test1.xml');
测试时可以在原XML里加一个brand值不是
NotDelete的entry节点,就能看到删除效果。
内容的提问来源于stack exchange,提问作者Jacob
相关产品推荐
相关产品推荐

