如何在Nokogiri xpath表达式中使用concat()?我试过了:
xml.xpath("concat(/root/a/text(), /root/b/text())")
但是失败了:
ArgumentError:node_set必须是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:表达式无效:/ concat('foo', '酒吧')
我知道Nokogiri基于libxml2,因此它只实现了XPath 1.0。但是concat()是XPath 1.0的一部分。但是,XPath 2.0中的类似函数是string-join(),我给了它一个机会:
xml.xpath("string-join('foo', 'bar')")
错误讯息:
RuntimeError:xmlXPathCompOpEval:找不到函数字符串连接
请参阅,它与concat()的错误消息不同。所以至少找到了函数concat()。还有一点暗示它可能以某种方式起作用......
xml.xpath("concat()")
...返回预期的错误消息:
Nokogiri :: XML :: XPath :: SyntaxError:参数数量无效: 的concat()
有机会让concat()使用参数吗?
P.S。:像xml.xpath("/root/a/text()")
这样的基本xpath表达式可以正常工作。
答案 0 :(得分:2)
XPath查询通常会返回 node-set ,即文档中的节点集合。在Nokogiri中,这由Nokogiri::XML::NodeSet
对象表示。
Nokogiri还允许您使用NodeSet
方法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 :(得分: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"]
注意,请注意前导.
将查询锚定在当前节点。