本文详解如何使用 php 的 domdocument + domxpath 高效解析含 cdata 的 xml(如 sitemap),绕过 `#cdata-section` 节点干扰,直接获取纯净文本值,并提供可落地的代码示例与关键注意事项。
在 PHP 中处理 XML 时,DOMDocument 是最常用且可靠的原生方案。但当 XML 中包含 片段(如 Sitemap 中的
根本原因在于:CDATA 并非独立“值容器”,而是 DOM 树中的一个特殊节点类型;它常与前后空白文本节点并存(例如换行与缩进)。手动遍历子节点时,若未过滤空白或未合并相邻文本/CData 内容,就会丢失实际数据。
✅ 推荐方案:弃用通用递归转数组,改用 DOMXPath 精准定位 + string() 函数提取
DOMXPath 的 string() 函数会自动合并目标节点下所有文本类子节点(包括 XML_TEXT_NODE 和 XML_CDATA_SECTION_NODE)的内容,并去除首尾空白,返回纯净字符串——这正是我们所需。
以下为完整、健壮的实现:
XML; $document = new DOMDocument(); $document->loadXML($xml); // 关键:注册命名空间前缀(因 XML 使用默认命名空间) $xpath = new DOMXPath($document); $xpath->registerNamespace('map', 'http://www.sitemaps.org/schemas/sitemap/0.9'); $sitemaps = []; // 使用 XPath 定位所有 sitemap 元素(支持多条目) foreach ($xpath->evaluate('//map:sitemap') as $sitemap) { $sitemaps[] = [ 'loc' => trim($xpath->evaluate('string(map:loc)', $sitemap)), 'lastmod' => trim($xpath->evaluate('string(map:lastmod)', $sitemap)) ]; } var_dump($sitemaps); // 输出: // array(1) { // [0] => array(2) { // ["loc"] => string(39) "https://www.blablal.id/news/sitem https://www.blablal.id/news/sitemap.xml ap.xml" // ["lastmod"] => string(25) "2025-02-02T12:21:02+07:00" // } // }
? 关键要点说明:
? 延伸建议:
此方法简洁、高效、符合 XML 处理最佳实践,彻底规避了手工遍历 DOM 树时对节点类型和空白处理的繁琐逻辑,是解析含 CDATA 的标准 XML(如 Sitemap、RSS、SOAP 响应)的首选方案。