簡體   English   中英

Ruby + Nokogiri + Xpath導航Node_Set

[英]Ruby + Nokogiri + Xpath navigate Node_Set

<Item id="item0">
  <Links>
    <FirstLink id="link1" target="one"/>
    <SecondLink id="link2" target="two"/>
  </Links>
  <Data>
    <String>content</String>
  </Data>
</Item>
<Item id="item1">
  <Links>
    <FirstLink id="link1" target="two"/>
    <SecondLink id="link2" target="two"/>
  </Links>
  <Data>
    <String>content</String>
  </Data>
</Item>

我用這種結構創建了一個Nokogiri-NodeSet,即帶有鏈接和數據子項的項目列表。 如何過濾<FirstLink>的'target'-屬性中與某個值不匹配的所有項目?

實際上,最后我想要提取的是<Data><String> -每個與<FirstLink> “ Target” -Attribute中的某個值匹配的<Item>

我已經嘗試了幾種方法,但是對於如何通過其孫子的屬性來標識元素,然后提取該孫子的父級兄弟姐妹X()的內容,我一無所知。

我完全不明白你的目標是什么。 但是,我想通過一個猜測向您展示在這種情況下如何進行:

require 'nokogiri'

doc = Nokogiri::XML <<-xml
<Item id="item0">
  <Links>
    <FirstLink id="link1" target="one"/>
    <SecondLink id="link2" target="two"/>
  </Links>
  <Data>
    <String>content1</String>
  </Data>
</Item>
<Item id="item1">
  <Links>
    <FirstLink id="link1" target="two"/>
    <SecondLink id="link2" target="two"/>
  </Links>
  <Data>
    <String>content2</String>
  </Data>
</Item>
xml

表達式為"//Item" #xpath方法將選擇所有Item節點。 然后,將那些Item節點傳遞到#reject方法以僅選擇那些具有名為Linkstarget屬性值為"one"的節點的節點。 如果有任何鏈接,則FirstLinkSecondLinktarget屬性值為"one" ,將為該節點選擇祖父母節點Item

node.at("//Links/FirstLink")['target']將為您提供字符串"one" ,該字符串是節點的target屬性的值,第一個Item節點為FirstLink ,第二個為"two" 項目節點。 部分['any vaue']node.at("//Links/FirstLink")['target']['any vaue']是對一個呼叫String#[]方法。

請記住,以下方法也將為您提供使用正則表達式靈活性

nodeset = doc.xpath("//Item").reject do |node|
  node.at("//Links/FirstLink")['target']['any vaue']
end

現在, nodeset僅包含必需的Item節點。 現在,我使用#map ,傳遞其中的每個項目節點以收集String節點的內容。 然后,帶有表達式//Data/String #at方法將選擇String節點。 然后#text ,將為您提供每個String節點的內容

nodeset.map { |n| n.at('//Data/String').text } # => ["content1"]

我們可以建立一個XPath表達式來做到這一點。 假設我們從整個XML文檔開始,而不是從現有的節點集開始,例如

//Item

將選擇所有<Item>元素(我想您已經有了類似的東西來獲取此節點集)。

接下來,僅選擇具有<Links><FirstLink>那些<Item>元素,其中FirstLinktarget屬性值為one

//Item[Links/FirstLink[@target='one']]

最后選擇這些節點的Data/String子代:

//Item[Links/FirstLink[@target='one']]/Data/String

因此,使用Nokogiri,您可以使用以下方式(其中doc是您解析的文檔):

doc.xpath("//Item[Links/FirstLink[@target='one']]/Data/String")

或者,如果要使用已經擁有的節點集,則可以使用相對表達式:

nodeset.xpath("self::Item[Links/FirstLink[@target='one']]/Data/String")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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