<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>
- 与<Item>
“目标”-Attribute中的某个值匹配的每个<FirstLink>
的内容。
我已经尝试了几种方法但是我不知道如何通过它的孙子的属性来识别元素,然后提取这个孙子的父母的兄弟的内容,X(。
答案 0 :(得分:1)
我完全不明白你的目标是什么。但是使用猜测,我试图告诉你,在这种情况下如何进行:
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
的{{1}}节点的节点。 。如果"one"
或FirstLink
的任何链接具有SecondLink
属性值target
,则对于该节点,将选择祖父节点"one"
。
Item
会为您提供字符串node.at("//Links/FirstLink")['target']
,该字符串是节点目标属性的值,第一个的 FirstLink 项目节点,然后是第二个项节点中的"one"
。 "two"
中的['any vaue']
部分是对String#[]
方法的调用。
请记住以下方法也会为您提供使用正则表达式的灵活性。
node.at("//Links/FirstLink")['target']['any vaue']
现在nodeset = doc.xpath("//Item").reject do |node|
node.at("//Links/FirstLink")['target']['any vaue']
end
仅包含所需的nodeset
个节点。现在我使用#map,在其中传递每个 item 节点以收集Item
节点的内容。然后使用表达式String
的{{3}}方法将选择//Data/String
节点。然后#at
将为您提供每个字符串节点的内容。
String
答案 1 :(得分:1)
我们可以构建一个XPath表达式来执行此操作。假设我们从整个XML文档开始,而不是你已经拥有的节点集,比如
//Item
将选择所有<Item>
个元素(我猜你已经有类似的东西来获得这个节点集。)
接下来,要仅选择那些<Item>
个<Links><FirstLink>
元素FirstLink
target
属性值为one
的<{1}}
//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")