获取 parent 节点,其中 child = x

Get parent node where child = x

当我找到匹配的 child.

时,我想 return 来自 XML 源的 'parent' 节点

如果我搜索 'ddd':

@doc.xpath('//item[contains(., "ddd")]')

我要return'Section 2'

我找不到关于 'where' Nokogiri 类型代码的文档。 这可能吗??

<entry>
  <match>
    <field>Section 1</field>
    <child>
      <item>aaa</item>
      <item>bbb</item>
      <item>ccc</item>
     </child>
  </match>
  <match>
    <field>Section 2</field>
    <child>
      <item>ddd</item>
      <item>eee</item>
      <item>fff</item>
     </child>
  </match>
  <match>
    <field>Section 3</field>
    <child>
      <item>hhh</item>
      <item>iii</item>
      <item>jjj</item>
     </child>
  </match>
</entry>

这是更准确的 XML 格式。 我需要在节点树上上下移动才能获得第 2 节。 这可能吗?

<entry>
  <match>
    <field>
      <foo>Section 1</foo>
    </field>
    <child>
      <item>aaa</item>
      <item>bbb</item>
      <item>ccc</item>
     </child>
  </match>
  <match>
    <field>
      <foo>Section 2</foo>
    </field>
    <child>
      <item>ddd</item>
      <item>eee</item>
      <item>fff</item>
     </child>
  </match>
  <match>
    <field>
      <foo>Section 3</foo>
    </field>
    <child>
      <item>hhh</item>
      <item>iii</item>
      <item>jjj</item>
     </child>
  </match>
</entry>

有一个名为 #previous_element 的方法:

# #xpath gives all the matched nodes as a collection.
@doc.xpath('//child[./item[contains(., "ddd")]]').map do |child|
  child.previous_element.text
end
# #at_xpath gives first matched node
@doc.at_xpath('//child[./item[contains(., "ddd")]]').previous_element.text
# => Section 2
根据您提供的 XML,

Section 2 不是 parent,它是 sibling <child> 节点的节点。

久经考验:

require 'nokogiri'

@doc = Nokogiri::XML.parse <<-XML
<entry>
  <match>
    <field>Section 1</field>
    <child>
      <item>aaa</item>
      <item>bbb</item>
      <item>ccc</item>
     </child>
  </match>
  <match>
    <field>Section 2</field>
    <child>
      <item>ddd</item>
      <item>eee</item>
      <item>fff</item>
     </child>
  </match>
  <match>
    <field>Section 3</field>
    <child>
      <item>hhh</item>
      <item>iii</item>
      <item>jjj</item>
     </child>
  </match>
</entry>
XML

@doc.at_xpath('//child[./item[contains(., "ddd")]]').previous_element.text # => "Section 2"

您可以在 XPath 中执行此操作:

@doc.xpath("/entry/match[child/item[contains(., 'ddd')]]/field/foo")

这是使用您的第二个示例。它首先找到具有 child/item 个后代的 match 元素,其中 item 包含 ddd,然后找到该 matchfoo 元素孙子.

您可以使用“..”语法轻松遍历树(类似于目录文件夹)。

所以这应该有效:

@doc.xpath('//item[contains(., "ddd")]/..')

or

@doc.xpath('//item[contains(., "ddd")]/../field')