如何通过PHP与DOMXPath正确分类DOM内容生成对应数组?
问题分析与解决方案
我来帮你搞定这个数组错位的问题!你现在遇到的核心问题是把所有<a>标签和所有<span>标签分别查询出来,然后通过数组下标$key强行关联——但你的HTML里有些<div class="classX">容器没有对应的<span>标签,导致<span>的数量比<a>少,下标自然就对应不上,才会出现后面的span_text乱匹配的情况。
正确思路:以容器为单位遍历
我们应该先获取所有的<div class="classX">容器,然后逐个处理每个容器内部的内容:每个容器里肯定有一个目标<a>标签,然后检查当前容器里是否存在对应的<span>标签,这样就能保证每个link_text和span_text是严格对应的。
修改后的PHP代码
$finder = new DomXPath($dom); // 先获取所有class为classX的div容器,这是关键! $divContainers = $finder->query("//div[contains(@class, normalize-space('classX'))]"); $data = []; foreach ($divContainers as $container) { // 在当前div容器内查找目标a标签,使用.//限定查找范围为当前节点的子元素 $linkNode = $finder->query(".//a[contains(@class, normalize-space('aClass'))]", $container)->item(0); $cleanLinkText = trim(str_replace("\n", " ", $linkNode->textContent)); // 初始化当前项的数组,至少包含link_text $currentItem = [ 'link_text' => $cleanLinkText ]; // 在当前div容器内查找对应的span下的p标签 $spanTextNode = $finder->query(".//span[contains(@class, 'sClass')]/p", $container)->item(0); if ($spanTextNode) { $cleanSpanText = trim(str_replace("\n", " ", $spanTextNode->textContent)); $currentItem['span_text'] = $cleanSpanText; } $data[] = $currentItem; }
代码说明
- 以容器为单位遍历:先拿到所有的
classXdiv,每个div是一个独立的单元,确保内部的a和span属于同一组。 - 限定查找范围:使用
.//的XPath语法,意思是“在当前节点的后代元素中查找”,这样不会跑到其他div里去匹配元素。 - 按需添加span_text:每个div里先获取a标签的文本,再检查是否存在对应的span内容,有就添加
span_text字段,没有就只保留link_text,完全符合你的需求。
验证结果
运行这段代码后,你就能得到期望的数组结构:
[ ['link_text' => 'Link Text 1', 'span_text' => 'Text #1'], ['link_text' => 'Link Text 2'], ['link_text' => 'Link Text 3'], ['link_text' => 'Link Text 4', 'span_text' => 'Text #4'], ['link_text' => 'Link Text 5', 'span_text' => 'Text #5'], ]
内容的提问来源于stack exchange,提问作者Ricardo
相关产品推荐
相关产品推荐

