[英]Ruby / Nokogiri / Xpath shallow search
如下所示,應用於以下(簡化)xml的代碼使我得到了myanim1.swf節點。 我實際上想要的節點是myanim3.swf。 我想說“用屬性名= animationUrl獲得帶有屬性標簽的第一個節點,但不要比一個孩子更深入”。 我目前有一個解決方法,但是我正在尋找一種更優雅的解決方案。
這是紅寶石,該對象是Nokogiri對象。 我相信這是XPath搜索,但是對於Nokogiri是否具有XPath風格我還不清楚。 無論如何,幫助表示贊賞,謝謝。
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>
碼:
myNode = thisNode.search("property[name=animationUrl]").first.andand["value"]
獲取帶有屬性標簽的第一個節點,該標簽的屬性名稱為animationUrl,但深度不超過一個孩子
相對XPath表達式:
*[property/@name='animationUrl'][1]
這意味着: 上下文節點的第一個子元素,至少具有一個property
子元素,其@name
屬性等於'animationUrl'
絕對XPath表達式:
/*[property/@name='animationUrl']
這意味着: 根元素具有至少一個property
子元素,其@name
屬性等於'animationUrl'
/descendant::*[property/@name='animationUrl'][1]
這意味着: 文檔根的第一個后代元素具有至少一個property
子元素,其@name
屬性等於'animationUrl'
我認為您需要以下內容:
t.xpath("/blah/property[@name='animationUrl']")
您需要使用at_xpath
以及對該節點的絕對引用,這將指定您只想檢索<blah><property>
深度的節點:
my_node = xml.at_xpath("/blah/property[@name='animationUrl']")
並采取行動:
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可以確定項目的深度(如上所示),但它不允許您對返回的NodeSet中的項目進行排序(這是在純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"/>
編輯 :使用XPath查找深度雖然有些棘手,但大約是讓Nokogiri為您查找元素深度的兩倍(在我的機器上,具有此測試數據) 。 而是使用以下命令:
class Nokogiri::XML::Node
def at_shallowest_xpath( path )
xpath(path).sort_by{ |n| n.ancestors.length }.first
end
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.