XPath多字符串比较优化:能否用数组类型简化多OR条件写法?
好问题!这确实是很多XPath使用者会碰到的可读性优化痛点,我会分不同XPath版本给你梳理最适合的方案:
XPath 1.0(无原生序列/数组支持)
XPath 1.0没有原生的数组或序列类型,所以没法直接用你设想的contains(arraytype("a", "b"), node/text())这种写法。不过我们可以用字符串拼接的技巧来简化重复代码,提升可读性:
contains('|a|b|', concat('|', node/text(), '|'))
原理是把目标值用一个不会出现在文本中的分隔符(比如|、#)包裹成一个字符串,再把节点文本也用同样的分隔符包裹后,检查是否包含在这个大字符串里。这样就不用重复写多次node/text(),比一堆or要清爽不少。
注意:如果节点内有子元素,node/text()可能返回多个文本节点,这时候建议用string(node)来获取整个节点的完整字符串值,避免匹配异常。
XPath 2.0及以上(支持序列/数组)
从XPath 2.0开始,原生支持**序列(Sequence)**类型(可以理解为轻量版的数组),这时候写法就非常简洁了:
最常用的简洁写法
node/text() = ("a", "b")
在XPath 2.0+中,当单个值和序列做相等比较时,会自动检查该值是否等于序列中的任意一项,效果完全等价于node/text()="a" or node/text()="b",但可读性提升很多。
更显式的写法(适合复杂场景)
如果想要更明确地表达“存在匹配项”的逻辑,可以用some...satisfies语法:
some $val in ("a", "b") satisfies $val = node/text()
关于数组类型的使用
XPath 3.0+还引入了正式的数组类型,如果想用数组来实现,需要用到数组函数(注意要绑定数组命名空间):
array:contains(array{"a", "b"}, node/text())
不过一般来说,用序列的node/text() = ("a", "b")已经足够简洁直观,除非你有特定的数组操作需求,否则没必要特意用数组。
总结
- 老环境(XPath 1.0):用分隔符包裹的
contains技巧简化代码; - 新环境(XPath 2.0+):直接用序列比较
node/text() = ("a", "b"),既简洁又易读; - 数组类型在XPath 3.0+支持,但不是多字符串比较的最优选择,序列写法更常用。
内容的提问来源于stack exchange,提问作者Mega-X

