PHP中使用XPath查询class为box的div及其子div的正确方法
关联提取嵌套div内容的正确XPath写法
问题说明
现有多组<div class="box">父容器,需要从每个容器内关联提取两个字段,原有分开全局查询节点、靠手动计数对齐索引的写法容易出现错位,执行效率低。
提取规则:
- 每个box内,id以
adx_开头、class为shorttext的div文本(示例值:test text) - 同一个box内,class为
pBox的div文本(示例值:$230)
示例HTML结构:
<div class="box"> <div id="adx_113_x_shorttext" class="shorttext">test text</div> <div class="btnLst"><span id="vs_table_IRZ_x_MI52_x_c010_MI52" class="info"> <flag class="tooltip-show-condition"></flag></span></div> <div class="pBox"> <div>$230</div> </div> </div>
原有错误写法示例:
$acc_count = 0; $accessories = $xpath->query("//div[contains(@class,'shorttext')]"); $price = $xpath->query("//div[contains(@class,'pBox')]"); foreach ($accessories as $node) { echo $node->nodeValue . " | " . $price[$acc_count]->nodeValue; . "\n"; $acc_count++; }
该写法核心问题:全局查询所有shorttext、pBox节点后靠计数器索引匹配,一旦某个容器缺节点、节点顺序变动就会出现错位。
实现方案
核心逻辑:先遍历所有父级box容器,再在每个容器的上下文范围内做相对XPath查询,从根源保证两个字段属于同一个容器,完全避免索引错位问题。
PHP实现代码:
// 第一步:查询所有box父容器 $boxList = $xpath->query("//div[contains(@class, 'box')]"); foreach ($boxList as $boxItem) { // 在当前box上下文内,匹配符合规则的shorttext节点:class含shorttext、id以adx_开头 // 注意XPath开头的.代表从当前节点往下查找,不能省略 $textNode = $xpath->query(".//div[contains(@class, 'shorttext') and starts-with(@id, 'adx_')]", $boxItem)->item(0); // 在当前box上下文内查询pBox节点 $priceNode = $xpath->query(".//div[contains(@class, 'pBox')]", $boxItem)->item(0); // 非空校验,避免节点缺失时报错 $extractText = $textNode ? trim($textNode->nodeValue) : ''; $extractPrice = $priceNode ? trim($priceNode->nodeValue) : ''; echo $extractText . " | " . $extractPrice . "\n"; }
注意事项
- 相对查询的XPath必须以
.开头,否则会默认从整个文档根节点全局查询,失去关联匹配的作用 - 用
starts-with(@id, 'adx_')匹配固定前缀的随机id,匹配精度比仅靠class匹配更高 - 增加节点非空判断,兼容个别box结构不完整的场景,避免运行报错
- 该写法不需要手动维护索引计数器,不会出现跨块匹配错位的问题,查询效率也高于多次全局查询。
内容的提问来源于stack exchange,提问作者K997
相关产品推荐
相关产品推荐

