XPath在处理XML或HTML文档时,其核心能力之一就是能够轻松地匹配和返回多个节点。它并不是一个“是否能”的问题,而更多是“如何更精确、更高效地”选择你所需的一组节点。无论是寻找页面上所有链接、所有特定类型的段落,还是那些满足复杂条件的数据项,XPath都提供了丰富的语法和操作符来达成这个目标。
要匹配多个节点,XPath提供了多种策略,具体选择哪种取决于你的目标和文档结构。最直接的方式是选择所有同名元素,比如
//a会选中文档中所有的
<a>标签。但我们往往需要更细致的筛选。
-
基于标签名和位置: 如果想选前三个
<li>
元素,可以尝试//ul/li[position() <= 3]
。 -
基于属性: 比如,我们经常需要抓取所有带有特定class的元素,如
//div[@class='product-item']
,这会返回所有class为product-item
的div
。 -
使用通配符:
//*
会匹配文档中的所有元素,而//div/*
则会匹配所有div
元素下的直接子元素。这在探索文档结构时很有用,但通常不建议用于精确数据提取,因为它会带来大量无关节点。 -
联合操作符
|
: 当你需要同时匹配几种不同类型的节点时,|
操作符非常强大。比如,//h1 | //h2 | //h3
可以一次性获取所有一级、二级、三级标题。 -
文本内容匹配:
//p[contains(text(), '关键词')]
可以找到所有包含特定关键词的段落。
这些只是冰山一角,XPath的强大之处在于其组合能力,通过将这些基本选择器与谓词、轴(axes)结合,几乎可以定位任何你想要的节点集合。
XPath中如何精确选择具有特定属性的多个元素?这个需求在实际工作中太常见了,简直是XPath的“基本功”之一。我们经常会遇到这样的场景:页面上有很多
div,但只有那些
class属性是
product-card的才是我想要的商品信息;或者,我想找到所有
href属性包含
category字样的链接。
要精确选择,关键在于使用谓词(Predicates)。谓词用方括号
[]包裹,紧跟在节点测试(node test)之后。
最直接的是完全匹配属性值:
//div[@class='product-card']
这会返回文档中所有
class属性值恰好是
product-card的
div元素。注意,如果一个
div有多个
class,例如
<div class="product-card featured">,这种写法是匹配不到的。这时就需要
contains()函数。
使用
contains()函数进行模糊匹配:
//div[contains(@class, 'product-card')]
这样就能匹配到所有
class属性值中包含
product-card子串的
div元素,比如
product-card featured或
featured product-card都能被选中。这在处理动态生成的class名时尤其有用。
类似的,还有
starts-with()和
ends-with()(后者在XPath 1.0中不直接支持,但XPath 2.0+有):
//a[starts-with(@href, '/products/')] // 匹配所有href以/products/开头的链接
当然,我们还可以组合多个条件,使用
and或
or:
//a[@target='_blank' and contains(@href, 'external')] // 匹配所有在新窗口打开且链接包含'external'的a标签 //input[@type='text' or @type='email'] // 匹配所有type是text或email的input标签
通过这些组合,你可以构建出非常精细的筛选逻辑,从一大堆节点中精准地“捞”出你真正需要的那一部分。这就像在图书馆里,你不只是找“书”,而是找“作者是XX,出版年份在YY之后,并且书名包含ZZ关键词”的书。

全面的AI聚合平台,一站式访问所有顶级AI模型


有时候,我们的需求不是“所有
div里的
p”,而是“所有标题和所有列表项”,或者“所有错误信息和所有警告信息”。这些节点可能在文档结构中相距甚远,标签名也各不相同,但它们在逻辑上属于同一类信息,需要一起处理。这时,XPath的联合操作符
|就显得尤为重要,它允许你将多个独立的XPath表达式的结果合并成一个节点集。
想象一下,你正在解析一个新闻页面,想抓取所有标题(可能是
h1,
h2,
h3)和所有主要内容段落(
p标签,但可能只有
class='article-body'的)。如果一个一个去取,那代码会显得重复且效率不高。
使用
|操作符可以这样写:
//h1 | //h2 | //h3 | //p[@class='article-body']
这个表达式会返回一个节点集,其中包含了所有匹配到的
h1、
h2、
h3元素,以及所有
class属性为
article-body的
p元素。这些节点在返回时通常会按照它们在原始文档中的顺序排列,这对于后续处理来说非常方便。
我个人在做一些内容聚合时,经常会用到这个技巧。比如,要从一个复杂的HTML页面中提取所有“显眼”的文本内容,我可能会这样组合:
//h1 | //h2 | //h3 | //h4 | //p[string-length(normalize-space(.)) > 50] | //li[string-length(normalize-space(.)) > 30]
这里我甚至加入了
string-length()和
normalize-space()函数,来过滤掉那些过短或只有空白的段落和列表项,确保抓取到的内容有实际意义。这种灵活性是
|操作符的魅力所在。
需要注意的是,
|操作符连接的每个部分本身都必须是一个有效的XPath表达式,并且它们的结果会简单地合并。它不会像SQL的
UNION ALL那样去重,但对于节点集来说,通常每个节点都是唯一的,所以去重不是主要考虑。性能上,虽然理论上会执行多个表达式,但在大多数现代XPath引擎中,这种开销通常可以忽略不计,尤其是在处理合理大小的文档时。 除了直接选择,XPath还有哪些高级技巧可以帮助批量定位元素?
当简单的标签名、属性或联合选择不足以满足需求时,我们就需要深入挖掘XPath的“高级武器”了。这些技巧往往涉及到轴(Axes)、函数(Functions)以及对上下文(Context)的巧妙利用。它们能让你在复杂的、非结构化的或嵌套很深的文档中,像侦探一样精准地找出目标。
-
利用轴(Axes)进行关系定位: XPath的轴允许你根据节点之间的关系来选择节点,而不仅仅是它们的层级。这对于批量选择那些没有独特属性,但与某个已知节点有特定关系的元素非常有用。
following-sibling::*
:选择当前节点之后的所有同级元素。preceding-sibling::*
:选择当前节点之前的所有同级元素。descendant::*
:选择当前节点的所有后代元素。ancestor::*
:选择当前节点的所有祖先元素。parent::*
:选择当前节点的直接父元素。child::*
:选择当前节点的直接子元素(这是默认轴,通常省略)。
举个例子,如果你找到一个
div
,它的标题是<h2>产品列表</h2>
,然后你想抓取这个div
后面所有ul
里的li
元素://h2[text()='产品列表']/following-sibling::ul/li
这个表达式首先定位到文本为“产品列表”的
h2
标签,然后从它的所有同级兄弟元素中找到ul
标签,再从这些ul
标签中选择所有的li
子元素。这种“先找到参照物,再定位目标”的思路,在
以上就是XPath如何匹配多个节点?的详细内容,更多请关注知识资源分享宝库其它相关文章!
相关标签: html node go ai win 排列 a标签 yy red sql html String xml union 堆 class Length href 选择器 position input ul li 大家都在看: XML与HTML混合使用时注意什么? XSLT如何输出HTML? XML转换到HTML的方法? 如何使用XSLT将XML转换为HTML? xml文件怎么转换成html网页 将xml转换为html网页的详细步骤
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。