[英]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
方法以僅選擇那些具有名為Links
且target
屬性值為"one"
的節點的節點。 如果有任何鏈接,則FirstLink
或SecondLink
的target
屬性值為"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>
元素,其中FirstLink
的target
屬性值為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.