【问题标题】:How to make an xpath expression read through a part of the document only (Ruby/Nokogiri/xpath)如何使 xpath 表达式仅读取文档的一部分(Ruby/Nokogiri/xpath)
【发布时间】:2013-03-21 16:53:01
【问题描述】:

我使用 Ruby 1.9.3p385、Nokogiri 和 xpath v.1。

在 Stackoverflow 上很棒的人的帮助下,我想出了这个 xpath 表达式:

products = xml_file.xpath("(/root_tag/middle_tag/item_tag")

拆分此 XML 文件:

<root_tag>
  <middle_tag>
    <item_tag>
      <headline_1>
        <tag_1>Product title 1</tag_1>
      </headline_1>
      <headline_2>
        <tag_2>Product attribute 1</tag_2>
      </headline_2>
    </item_tag>
    <item_tag>
      <headline_1>
        <tag_1>Product title 2</tag_1>
      </headline_1>
      <headline_2>
        <tag_2>Product attribute 2</tag_2>
      </headline_2>
    </item_tag>
  </middle_tag>
</root_tag>

分成 2 个产品。

我现在希望遍历每个产品并提取所有产品信息(通过提取其叶节点)。为此,我正在使用此代码:

products.each do |product|
  puts product #=> <item_tag><headline_1><tag_1>Product title 1</tag_1></headline_1><headline_2><tag_2>Product attribute 1</tag_2></headline_2></item_tag>
  product_data = product.xpath("//*[not(*)]")
  puts product_data #=> <tag_1>Product title 1</tag_1><tag_2>Product attribute 1</tag_2><tag_1>Product title 2</tag_1><tag_2>Product attribute 2</tag_2>
end

如您所见,这正是我想要的,除了一件事:它读取的是产品而不是产品。

如何将我的搜索限制在产品范围内?回答时,请注意示例已简化。我希望该解决方案“擦除”产品知识(如果可能的话),因为它可能适用于所有情况。

【问题讨论】:

  • //*[not(*)] 中的 // 选择器将 xpath 的范围更改回文档根元素(root_tag)。您需要使用本地选择器编写此代码,例如 headline_1headine_1/tag_1,而不是使用 //
  • 好的,但是您对可以处理此问题的表达式有什么建议吗?我在代码中有这样的:paths = ["/root_tag/middle_tag/item_tag/headline_1", "/root_tag/middle_tag/item_tag/headline_2"]。也许我们可以提取 "headline_1""headline_2"(两者都没有出现的部分),然后在本地搜索它们...
  • 我是一个专业的刮刀,所以如果你放一些$$,我可以为你做,就像你requested。如果您有兴趣,请按照我的个人资料中的说明给我发电子邮件。
  • 谢谢,但我只是在寻找一个常规的 SO 代码答案,所以我可以将代码放入我的应用程序并用它做很多事情。

标签: ruby xml xpath xml-parsing nokogiri


【解决方案1】:

答案是在//*[not(*)] 之前简单地添加一个.

product_data = product.xpath(".//*[not(*)]")

这告诉 XPath 表达式从当前节点而不是根开始。

先生。 Novatchev 的回答虽然在技术上是正确的,但不会导致解析代码成为惯用的 Ruby。

【讨论】:

    【解决方案2】:

    代替

    //*[not(*)] 
    

    使用

    (//product)[1]//*[not(*)] 
    

    这只会选择 XML 文档中第一个 product 元素下的“叶节点”。

    对文档中的所有 product 元素重复此操作。您可以通过以下方式获得他们的数量:

    count(//product)
    

    【讨论】:

    • 完美,正是我想要的。
    【解决方案3】:

    你可能只想:

    product_data = product.xpath("*")
    

    它们都会找到产品的子元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-24
      • 2018-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多