簡體   English   中英

Ruby / Nokogiri / Xpath淺層搜索

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM