基于Go结构体的XPath多匹配元素首项定位问题
解决XPath定位首个匹配元素并兼容Go嵌套结构体反序列化的问题
需求
需定位满足条件的首个元素,且必须保留现有XPath查询的部分内容,原因是后续要反序列化Go语言中的嵌套结构体。
现有Go结构体定义
type offersDto struct { PinnedOffer *offerDto `xpath:"(.//div[@id='aod-pinned-offer'])[1]" xpath_required:"false"` } type offerDto struct { PriceBlock *struct { Price string `xpath:".//span[contains(concat(' ', normalize-space(@class), ' '), ' a-offscreen ')]/text()"` } `xpath:".//span[contains(concat(' ', normalize-space(@class), ' '), ' a-price ')]"` }
当前问题
当xpath:".//span[contains(concat(' ', normalize-space(@class), ' '), ' a-price ')]"匹配到多个结果时,查询无法正常工作。不需要数组形式,希望定位到多个(或单个)匹配结果中的首个元素。
问题场景对应的HTML结构
<div id="aod-pinned-offer" class="a-section a-spacing-none aod-pinned-offer-block"> <table><tbody><tr><td> <span> <div class="some-class"> <span class="some-class">-35%</span> <span class="a-price some-class"> <span class="a-offscreen"> AED354.00 </span> <span> <span>AED</span><span>354<span>.</span></span><span>00</span> </span> </span> </div> <div class="some-class"> <span> <span> <span> List Price: <span class="a-price some-class"> <span class="a-offscreen"> AED541.00 </span> <span> AED541.00 </span> </span> </span> </span> </span> </div> </span> </td></tr></tbody></table> </div>
尝试过的方法
希望保留查询的第一部分(.//div[@id='aod-pinned-offer'])[1],并定位到首个class为a-offscreen的span元素,尝试了类似(.//div[@id='aod-pinned-offer'])[1](.//span[contains(concat(' ', normalize-space(@class), ' '), ' a-price ')]//span[contains(concat(' ', normalize-space(@class), ' '), ' a-offscreen ')]/text())[0]的多种括号变体,但发现不支持这种连续的集合查询写法。
解决方案
1. XPath语法层面解决
将原XPath中的()[1]替换为[position()=1],即可正确定位到首个匹配元素。比如针对PriceBlock的XPath可修改为:
.//span[contains(concat(' ', normalize-space(@class), ' '), ' a-price ')][position()=1]
2. Go反序列化层面说明
后续发现encoding/json反序列化器默认会取多个元素中的首个,因此从Go语言角度,该问题无需额外处理。
内容的提问来源于stack exchange,提问作者nazzrrg
相关产品推荐
相关产品推荐

