2016-12-26 62 views
1

如何在Nokogiri xpath表达式中使用concat()?我已经试过:Nokogiri和concat()

xml.xpath("concat(/root/a/text(), /root/b/text())") 

但是失败: “”

ArgumentError: node_set must be a Nokogiri::XML::NodeSet

其实好像引入nokogiri接受与只启动XPath表达式或“/”,所以我尝试了这些:

xml.xpath(".concat(/root/a/text(), /root/b/text())") 
xml.xpath("/concat(/root/a/text(), /root/b/text())") 
xml.xpath("/concat('foo', 'bar')") 

但他们都失败,此错误:

Nokogiri::XML::XPath::SyntaxError: Invalid expression: /concat('foo', 'bar')

我知道引入nokogiri是基于libxml2的,因此它仅实现的XPath 1.0。但是concat()是XPath 1.0的一部分。但是,XPath 2.0中的类似功能是字符串连接(),我给它一个机会:

xml.xpath("string-join('foo', 'bar')")  

错误消息:

RuntimeError: xmlXPathCompOpEval: function string-join not found

见,它比一个CONCAT不同的错误信息()。所以至少找到函数concat()。还有一个暗示,它可能以某种方式工作是...

xml.xpath("concat()")               

...返回预期的错误消息:

Nokogiri::XML::XPath::SyntaxError: Invalid number of arguments: concat()

任何机会得到CONCAT()带参数的工作?

P.S .:像xml.xpath("/root/a/text()")一样的基本xpath表达式正常工作。

+1

你能提供一个完整的问题例子吗?带'co​​ncat'的XPath对我来说工作正常,我怀疑你正在使用Nokogiri期望的其他地方的结果。 – matt

回答

2

XPath查询通常会返回节点集,该文档中的节点集合。在Nokogiri中,这是由Nokogiri::XML::NodeSet对象表示的。

Nokogiri还允许您使用NodeSetxpath方法。在这种情况下,Nokogiri executes the query individually against each of the nodes in the NodeSet in turn, and combines them all into a new NodeSet which it returns as the result

正常情况下,您可以像预期的那样工作,其结果是所有匹配查询的节点的组合。但是,在使用返回非节点集的XPath查询时,这不起作用,因为在这种情况下。

执行查询后,Nokogiri会尝试将结果(它预计为NodeSet)添加到新创建的NodeSet。当结果实际上是一个字符串this fails with the error you are getting

这已经在Nokogiri bug,并添加到他们的roadmap,但目前还没有解决方案。

变通方法/解决方案是让所有非节点集在单个节点而不是节点集上返回XPath查询。 at_xpath将返回查询的第一个匹配节点,并且该节点可用于进一步调用xpath而不存在此问题。

1

似乎为我

body = "<root><a>aaa</a><b>bbb</b></root>" 
xml = Nokogiri::XML(body) 
xml.xpath("concat(/root/a/text(), /root/b/text())") # => "aaabbb" 

鉴于你的更新工作,也许尝试呢?

body = "<wrapper><root><a>aaa</a><b>bbb</b></root></wrapper>" 
xml = Nokogiri::XML(body) 
xml = xml.xpath("wrapper") # returns a node set 
xml.map { |each| each.xpath("concat(./root/a/text(), ./root/b/text())") } # => ["aaabbb"] 

注意,请注意前导.将查询锚定在当前节点。