
本文介绍如何通过 XPath 表达式 *|text() 同时获取 HTML 元素内所有子元素节点和直接子文本节点,从而完整还原 等容器中“标签间文本”的原始顺序与结构。
本文介绍如何通过 xpath 表达式 `*|text()` 同时获取 html 元素内所有子元素节点和直接子文本节点,从而完整还原 `
` 等容器中“标签间文本”的原始顺序与结构。
在 PHP 的 DOMDocument + DOMXPath 开发中,一个常见需求是:遍历某个父元素(如 <p></p>)的所有直接子内容,不仅包括 <span></span>、<img alt="如何使用 PHP DOMXPath 提取标签内外的纯文本节点(包括相邻文本)" > 等标签节点,也包括夹在标签之间的纯文本(如 "Example Text 1" 和 "Example Text 2")。默认调用 $xpath->evaluate("*", $object) 仅返回元素节点(Element Nodes),而忽略文本节点(Text Nodes),导致内容丢失或顺序错乱。
正确做法是扩展 XPath 表达式,显式包含文本节点。使用联合表达式 *|text() 即可同时匹配:
-
*:所有子元素节点(如<span></span>、<img alt="如何使用 PHP DOMXPath 提取标签内外的纯文本节点(包括相邻文本)" >) -
text():所有直接子文本节点(即父元素下一级的纯文本,不含嵌套文本)
✅ 示例代码如下:
$dom = new DOMDocument();
libxml_use_internal_errors(true); // 忽略 HTML 解析警告
$dom->loadHTML('<p> Example Text 1 <span> Text </span> Example Text 2 <img src="example.png" alt="如何使用 PHP DOMXPath 提取标签内外的纯文本节点(包括相邻文本)" ></p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill5233" title="btpanel phpsite 宝塔面板PHP网站"><img
src="https://img.php.cn/upload/skill/000/000/081/179040786932301.jpg" alt="btpanel phpsite 宝塔面板PHP网站" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill5233" title="btpanel phpsite 宝塔面板PHP网站">btpanel phpsite 宝塔面板PHP网站</a>
<p>宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理</p>
</div>
<a href="/xiazai/skill5233" title="btpanel phpsite 宝塔面板PHP网站" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/7fc7563c4182" style="max-width:90%" rel="nofollow" target="_blank">PHP免费学习笔记(深入)</a>”;</p>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);
// 定位到 <p> 元素
$pNode = $dom->getElementsByTagName('p')->item(0);
// 获取所有直接子节点:元素 + 相邻文本
$subObjects = $xpath->evaluate("*|text()", $pNode);
// 遍历并区分类型,保持原始顺序
foreach ($subObjects as $node) {
if ($node instanceof DOMText) {
echo "TEXT: '" . trim($node->textContent) . "'\n";
} elseif ($node instanceof DOMElement) {
echo "ELEMENT: <" . $node->tagName . "> (content: '" . trim($node->textContent) . "')\n";
}
}输出结果(按 DOM 树中实际顺序):
TEXT: 'Example Text 1' ELEMENT: <span> (content: 'Text') TEXT: 'Example Text 2' ELEMENT: <img alt="如何使用 PHP DOMXPath 提取标签内外的纯文本节点(包括相邻文本)" > (content: '')
⚠️ 注意事项:
-
text()仅匹配直接子文本节点,不会递归抓取深层嵌套文本(如<span><em>inner</em></span>中的"inner"不会被text()在<p></p>层级捕获); - 文本节点可能包含空白符(换行、缩进),建议用
trim($node->textContent)清理; - 若需排除空白文本节点,可改用更精确的
text()[normalize-space()]; -
DOMXPath::evaluate()返回的是DOMNodeList,其遍历顺序严格遵循 HTML 源码中节点出现的物理顺序,天然支持混合内容的线性处理。
总结:*|text() 是 DOMXPath 处理混合内容(Mixed Content)的标准模式,它让开发者能以统一方式遍历“标签+文本”序列,是构建 HTML 解析器、富文本提取器或模板预处理器的关键技巧。


















