Ruby/Nokogiri/Xpath浅层搜索
下面应用于简化xml的代码使我获得了myanim1.swf的节点,正如预期的那样。实际上,我想要一个带有myanim3.swf的节点。我想说的是,获取第一个带有属性名=animationUrl的属性标记的节点,但不要深入到一个子节点。我目前有一个解决方案,但我正在寻找一个更优雅的解决方案 这是ruby,对象是Nokogiri对象。我相信这是XPath搜索,但我有点不清楚这是否是Nokogiri的XPath风格。无论如何,谢谢你的帮助 XML:Ruby/Nokogiri/Xpath浅层搜索,ruby,search,xpath,nokogiri,Ruby,Search,Xpath,Nokogiri,下面应用于简化xml的代码使我获得了myanim1.swf的节点,正如预期的那样。实际上,我想要一个带有myanim3.swf的节点。我想说的是,获取第一个带有属性名=animationUrl的属性标记的节点,但不要深入到一个子节点。我目前有一个解决方案,但我正在寻找一个更优雅的解决方案 这是ruby,对象是Nokogiri对象。我相信这是XPath搜索,但我有点不清楚这是否是Nokogiri的XPath风格。无论如何,谢谢你的帮助 XML: 我想你需要这样的东西: t.xpath("/blah
我想你需要这样的东西:
t.xpath("/blah/property[@name='animationUrl']")
我想你需要这样的东西:
t.xpath("/blah/property[@name='animationUrl']")
您需要使用at_xpath以及对节点的绝对引用,这将指定您只希望在以下深度检索节点:
在行动中:
require 'nokogiri'
thisNode = <<XML
<blah>
<property name="overlays">
<array>
<object type="myType">
<property name="animationUrl" value="myanim1.swf"/>
</object>
<object type="myType">
<property name="animationUrl" value="myanim2.swf"/>
</object>
</array>
</property>
<property name="animationUrl" value="myanim3"/>
</property>
</blah>
XML
xml=Nokogiri::XML(thisNode)
my_node = xml.at_xpath("/blah/property[@name='animationUrl']")
puts my_node #=> <property name="animationUrl" value="myanim3"/>
您需要使用at_xpath以及对节点的绝对引用,这将指定您只希望在以下深度检索节点:
在行动中:
require 'nokogiri'
thisNode = <<XML
<blah>
<property name="overlays">
<array>
<object type="myType">
<property name="animationUrl" value="myanim1.swf"/>
</object>
<object type="myType">
<property name="animationUrl" value="myanim2.swf"/>
</object>
</array>
</property>
<property name="animationUrl" value="myanim3"/>
</property>
</blah>
XML
xml=Nokogiri::XML(thisNode)
my_node = xml.at_xpath("/blah/property[@name='animationUrl']")
puts my_node #=> <property name="animationUrl" value="myanim3"/>
如果您知道所需物品的深度,可以执行以下操作:
p d.at_xpath('//property[@name="animationUrl"][count(ancestor::*) = 1]')
但是,如果您知道深度,那么当然更容易做到:
p d.at_xpath('/*/property[@name="animationUrl"]')
如果您希望进行实际的广度优先搜索,在任何深度都能找到最浅的项目:
虽然XPath允许您如上所示确定项目的深度,但它不允许您在返回的节点集中对项目进行排序,而这正是纯XPath中需要做的。因此,我们必须在一般情况下使用Ruby:
class Nokogiri::XML::Node
def at_shallowest_xpath( path )
xpath(path).sort_by{ |n| n.xpath 'count(ancestor::*)' }.first
end
end
d = Nokogiri::XML xml_source
puts d.at_shallowest_xpath('//property[@name="animationUrl"]')
#=> <property name="animationUrl" value="myanim3"/>
如果您知道所需物品的深度,可以执行以下操作:
p d.at_xpath('//property[@name="animationUrl"][count(ancestor::*) = 1]')
但是,如果您知道深度,那么当然更容易做到:
p d.at_xpath('/*/property[@name="animationUrl"]')
如果您希望进行实际的广度优先搜索,在任何深度都能找到最浅的项目:
虽然XPath允许您如上所示确定项目的深度,但它不允许您在返回的节点集中对项目进行排序,而这正是纯XPath中需要做的。因此,我们必须在一般情况下使用Ruby:
class Nokogiri::XML::Node
def at_shallowest_xpath( path )
xpath(path).sort_by{ |n| n.xpath 'count(ancestor::*)' }.first
end
end
d = Nokogiri::XML xml_source
puts d.at_shallowest_xpath('//property[@name="animationUrl"]')
#=> <property name="animationUrl" value="myanim3"/>
获取带有属性标记的第一个节点
属性名称=animationUrl,但
不要超过一个孩子
相对XPath表达式:
*[property/@name='animationUrl'][1]
这意味着:上下文节点的第一个子元素至少有一个@name属性等于“animationUrl”的属性子元素
绝对XPath表达式:
/*[property/@name='animationUrl']
这意味着:根元素至少有一个@name属性等于'animationUrl'的属性子元素
这意味着:文档根的第一个子元素至少有一个属性子元素@name属性等于“animationUrl”
获取带有属性标记的第一个节点
属性名称=animationUrl,但
不要超过一个孩子
相对XPath表达式:
*[property/@name='animationUrl'][1]
这意味着:上下文节点的第一个子元素至少有一个@name属性等于“animationUrl”的属性子元素
绝对XPath表达式:
/*[property/@name='animationUrl']
这意味着:根元素至少有一个@name属性等于'animationUrl'的属性子元素
这意味着:documentroot的第一个子元素至少有一个property子元素,其@name属性等于'animationUrl'我认为您误解了OP的意图。他只想在根的子级提取一个节点。他不需要计算深度。@MarkThomas Ack,你说得对。我完全没听懂这些话,但不要说得比一个孩子更深。我把浅层搜索误解为广度优先,先找到最浅的。哦,答案的上半部分仍然有效,至少:我认为你误读了OP的意图。他只想在根的子级提取一个节点。他不需要计算深度。@MarkThomas Ack,你说得对。我完全没听懂这些话,但不要说得比一个孩子更深。我把浅层搜索误解为广度优先,先找到最浅的。哦,答案的上半部分仍然有效,至少:Nokogiri的XPath风格?Nokogiri使用libxml2,这是一个标准的XML解析器?Nokogiri使用libxml2,这是一个标准的XML解析器。你可以用在。Nokogiri将做正确的事情。使用at将返回指定级别上所有出现的具有animationUrl的对象。at_xpath将只返回op所查找的第一个实例。您不必使用at_xpath。你可以用在。Nokogiri将做正确的事情。使用at将返回指定级别上所有出现的具有animationUrl的对象。at_xpath将只返回op所寻找的第一个实例。