我有一个充满嵌套item
节点的xml文档。在大多数情况下,每个item
都有一个name
元素。我想检查item
是否有name
元素,如果不存在,则返回默认名称。
<item>
<name>Item 1</name>
</item>
<item>
<items>
<item>
<name>Child Item 1</name>
</item>
<item>
<name>Child Item 2</name>
</item>
</items>
</item>
当我向node.at('name')
询问没有name
元素的节点时,它会从树下面的子节点中选择下一个节点。在上述情况下,如果我在第二个at('name')
上询问item
,我会"Child Item 1"
。
答案 0 :(得分:0)
问题是你正在使用at()
,它可以接受CSS选择器或XPath表达式,并试图猜测你给了它。在这种情况下,它认为name
是一个CSS选择器,它是一个后代选择器,在当前节点下面的任何位置选择name
元素。
相反,您希望使用XPath表达式仅查找子 <name>
元素。您可以通过明确表达XPath表达式来实现此目的:
node.at('./name')
或者您可以使用at_xpath
方法清除:
node.at_xpath('name')
这是一个简单的工作示例:
require 'nokogiri'
doc = Nokogiri.XML '<r>
<item id="a">
<name>Item 1</name>
</item>
<item id="b">
<items>
<item id="c">
<name>Child Item 1</name>
</item>
<item id="d">
<name>Child Item 2</name>
</item>
</items>
</item>
</r>'
doc.css('item').each do |item|
name = item.at_xpath('name')
name = name ? name.text : "DEFAULT"
puts "#{item['id']} -- #{name}"
end
#=> a -- Item 1
#=> b -- DEFAULT
#=> c -- Child Item 1
#=> d -- Child Item 2