XPath查询与正则表达式

4
很简单,有一个HTML文件,其中有一个带有变量id的div元素,如下所示。
<div id="abc_1"><div>

id的整数部分是可变的,因此它可以是abc_892、abc_553等等。

什么是获取该值的最佳查询方法?


参考文献:使用PHP中的正则表达式过滤XPath属性(2011年7月) - hakre
2个回答

6
//div[starts-with(@id, "abc_")]

2

目前被接受的答案选择了这些不需要的元素:

<div id="abc_xyz"/>

但只有那些div元素必须被接受,其id不仅以"abc_"开头,而且下划线后面的子字符串是整数的表示形式。

使用此XPath表达式

//div
   [@id[starts-with(., 'abc_') 
      and 
        floor(substring-after(.,'_')) 
       = 
        number(substring-after(.,'_')) 
       ]
   ]

这个选择器会选中任何带有id属性的div元素,其字符串值以"abc_"开头,并且-后面的子字符串是一个整数。

解释:

在XPath 1.0中,我们利用了这个XPath表达式:

floor($x) = number($x)

$x为整数时,表达式的值为true()

这可以很容易地证明:

  1. 如果$x是整数,则根据定义,上述表达式的值为true()

  2. 如果上述表达式的值为true(),则意味着等式两边都不是NaN,因为根据定义,NaN不等于任何值(包括它自己)。但这意味着$x是一个数字(number($x)不是NaN),并且根据定义,一个等于整数floor($x)的数字$x是整数。

另一种解决方案:

//div
   [@id[starts-with(., 'abc_') 
      and 
        'abc_' = translate(., '0123456789', '')
       ]
   ]

你能解释一下为什么这个有效吗?我对xpath不是很熟悉,所以我猜floor()会返回一个永远不等于自己的值,就像sql的三元逻辑(例如,在sql中null = null总是false)一样?谢谢。 - goat
@chris:已完成。顺便提一下,表达式中有一点不准确,现在已经修正了。 - Dimitre Novatchev
@chris:不客气。是的,XPath(即使是1.0版本)是一种非常强大的语言和工具,可以提供优雅的解决方案。 - Dimitre Novatchev
好的,就像我说的,我认为额外的检查可能是不必要的,但我相信它可能对某些人有用。只是出于好奇,//div[@id[translate(.,'0123456789','') = 'abc_']] 不会更快吗? - Flynn1179
@Flynn1179:两种方法都是O(N) -- 如果其中一种更快,这将取决于实现。XPath引擎优化器可能会或可能不会识别和优化特定的表达式。我更喜欢使用floor($x) = $x,因为这更易读、易懂,并且可以很好地转化为“类型检查”。 - Dimitre Novatchev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接