我想在某个模式的html doc中搜索div id。 我想在正则表达式中匹配这个模式:
foo_([[:digit:]]{1.8})
使用xpath。上述模式的xpath等价物是什么?
我被//div[@id="foo_
困住了然后呢?如果有人可以继续为其表达法律意见。
修改
抱歉,我想我必须详细说明。实际上它不是foo_
,而是post_message_
以下是片段:
html_doc = Nokogiri::HTML(open(myfile))
message_div = html_doc.xpath('//div[substring(@id,13) = "post_message_" and substring-after(@id, "post_message_") => 0 and substring-after(@id, "post_message_") <= 99999999]')
仍然失败。错误讯息:
无法计算表达式'
//div[substring(@id,13) = "post_message_" and substring-after(@id, "post_message_") => 0 and substring-after(@id, "post_message_") <= 99999999]
'(Nokogiri :: XML :: XPath :: SyntaxError)
答案 0 :(得分:15)
这个(更新):
XPath 1.0:
"//div[substring-before(@id, '_') = 'foo'
and substring-after(@id, '_') >= 0
and substring-after(@id, '_') <= 99999999]"
编辑#2:OP对问题进行了更改。以下,更加简化的XPath 1.0表达式对我有用:
"//div[substring(@id, 1, 13) = 'post_message_'
and substring(@id, 14) >= 0
and substring(@id, 14) <= 99999999]"
XPath 2.0有一个方便的matches()
function:
"//div[matches(@id, '^foo_\d{1,8}$')]"
除了更好的可移植性之外,我希望数值表达式(XPath 1.0样式)的性能优于正则表达式测试,尽管这只会在处理大型数据集时变得明显。
答案的原始版本:
"//div[substring-before(@id, '_') = 'foo'
and number(substring-after(@id, '_')) = substring-after(@id, '_')
and number(substring-after(@id, '_')) >= 0
and number(substring-after(@id, '_')) <= 99999999]"
使用number()
函数是不必要的,因为数学比较运算符隐式地将它们的参数强制转换为数字,任何非数字将变为NaN
并且大于/小于测试将失败。
我还删除了尖括号的编码,因为这是XML要求,而不是XPath要求。
答案 1 :(得分:5)
正如已经指出的那样,在XPath 2.0中使用标准的正则表达式功能和matches()
函数这样的函数会很好。
一种可能的XPath 1.0解决方案:
//div[starts-with(@id, 'post_message_')
and
string-length(@id) = 21
and
translate(substring-after(@id, 'post_message_'),
'0123456789',
''
)
=
''
]
请注意以下:
使用标准XPath函数starts-with()
。
使用标准XPath函数string-length()
。
使用标准XPath函数substring-after()
。
使用标准XPath函数 translate()
。
答案 2 :(得分:2)
或者使用xpath函数匹配(字符串,模式)。
<xsl:if test="matches(name(.),'foo_')">
不幸的是它不是正则表达式,但它可能已经足够了,除非你有其他不需要的foo_标签,那么我猜你可以添加一些“if”检查来剔除它们。
答案 3 :(得分:0)
Nikkou使这非常容易阅读:
doc.search('div').attr_matches('id', /post_message_\d{1,8}/)