Ruby + Nokogiri + Xpath导航Node_Set

时间:2014-02-03 16:45:43

标签: ruby xpath nokogiri

<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(。

2 个答案:

答案 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")