【问题标题】:Get parent node where child = x获取child = x的父节点
【发布时间】:2023-03-30 14:59:01
【问题描述】:

当我找到匹配的子节点时,我想从 XML 源返回一个“父”节点。

如果我搜索“ddd”:

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

我想返回“第 2 节”

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

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

【问题讨论】:

    标签: ruby arrays nokogiri


    【解决方案1】:

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

    所以这应该有效:

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

    【讨论】:

      【解决方案2】:

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

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

      这是使用您的第二个样本。它首先查找具有child/item 后代的match 元素,其中item 包含ddd,然后查找foo 元素的孙子match

      【讨论】:

        【解决方案3】:

        有一个名为#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
        

        Section 2 不是 parent 根据您给出的 XML,它是 &lt;child&gt; 节点的 sibling 节点。

        久经考验:

        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"
        

        【讨论】:

        • 太棒了..!我的问题是我需要的内容的简化版本,但这让我走上了正确的道路……这在哪里记录?另外...有没有办法按名称调用父节点,因为我在现实世界中想要的是从我的子节点开始的新节点。
        • @Beertastic 我给了链接。
        • Sweet...正在阅读...出于某种原因,我认为这都是 Nokogiri 文档,而不是纯 Ruby.. 谢谢..
        • 我已经更新了我的问题...但是,我在本地遇到了这个错误:未定义的方法 `previous_element' .. 所有这些都只是使用标准 nokogiri 对吗?
        • @Beertastic 好吧,我不知道你的 XML 结构。在你的情况下,在你搜索的 node 之前,没有兄弟元素。这就是你的原因得到nil.. 并且您正在调用该方法.. 这就是错误的原因。您需要很好地阅读您的 XML,并且 XPATH 也需要正确。 nokogiri 没什么问题.. :)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多