2016-12-26 6 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

노코 기리가 시작 만 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')

나는 노코 기리가 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() 함수가 발견되었습니다.

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

(CONCAT를 얻을 가능성은) 인수 작업 : 그것은 어떻게 든 작동 할 수 있다는 또 하나의 힌트

xml.xpath("concat()")               

... 예상되는 오류 메시지를 반환 ...인가?

P.S. : xml.xpath("/root/a/text()")과 같은 기본 xpath 표현식이 정상적으로 작동합니다.

+1

문제의 전체 예제를 제공 할 수 있습니까? 'concat'이있는 XPath는 괜찮습니다. Nokogiri가 다른 것을 기대하는 곳에서 결과를 사용하고있는 것 같습니다. – matt

답변

2

XPath 쿼리는 일반적으로 노드 집합 (문서의 노드 모음)을 반환합니다. Nokogiri에서는 Nokogiri::XML::NodeSet 개체로 표시됩니다.

Nokogiri에서는 을 xpath 방법으로 사용할 수도 있습니다. 이 경우 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"] 

NB, 현재 노드에서 쿼리를 고정하는 최고의 .을 알 수 있습니다.