2016-12-26 31 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"] 

注意,請注意前導.將查詢錨定在當前節點。