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

php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










