【问题标题】:Get low level xpath from XML with Nokogiri使用 Nokogiri 从 XML 获取低级 xpath
【发布时间】:2014-05-20 00:25:59
【问题描述】:

我试图将下面 XML 中低级元素的所有唯一 Xpath 存储在一个数组中,但就像我在数组 a 中所做的那样,正在存储所有 XML,而不仅仅是 Xpath 本身。 XML 具有不同级别的 Xpath。我的意思是,一些子元素只有 2 个祖先,而另一些则不止一个。

这是我的代码。

require 'nokogiri'
doc = Nokogiri::XML(<<EOT)

<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item>
        <name>Cake</name>
        <ppu>0.55</ppu>
        <batters>
            <batter>Regular</batter>
            <batter>Chocolate</batter>
            <batter>Blueberry</batter>
            <batter>Devil's Food</batter>
        </batters>
        <topping>None</topping>
        <topping>Glazed</topping>
        <topping>Sugar</topping>
        <topping>Powdered Sugar</topping>
        <topping>Chocolate with Sprinkles</topping>
        <topping>Chocolate</topping>
        <topping>Maple</topping>
    </item>
    <item>
        <name>Raised</name>
        <ppu>0.55</ppu>
        <batters>
            <batter>Regular</batter>
        </batters>
        <topping>None</topping>
        <topping>Glazed</topping>
        <topping>Sugar</topping>
        <topping>Chocolate</topping>
        <topping>Maple</topping>
    </item>
</items>
EOT

a = []
a = doc.xpath("//*")

puts a

我只想将唯一的 xpath 存储在数组“a”中,如下所示:

/items/item/name
/items/item/ppu
/items/item/batters/batter
/items/item/topping

也许有人可以帮助我如何做到这一点。

感谢您的帮助。

【问题讨论】:

  • 您到底想存储什么? XPath 本身还是元素的内容?

标签: ruby xpath nokogiri


【解决方案1】:

您要选择的是“叶子”节点。你可以这样做:

doc.xpath("//*[not(*)]")

这意味着“选择所有不包含元素的元素”。

如果您需要 XPath,则需要在每个节点上调用 .path。但是 Nokogiri 提供的路径具有明确的位置(例如 /items/item[2]/topping[4]),因此您必须应用正则表达式来删除它们,然后使用 uniq 删除重复项:

doc.xpath("//*[not(*)]").map {|leaf| leaf.path.gsub(/\[.*?\]/, '') }.uniq

输出:

/items/item/name
/items/item/ppu
/items/item/batters/batter
/items/item/topping

【讨论】:

  • 你好,马克。优秀的答案。非常感谢。您的答案中混杂了几个概念(ruby 方法、正则表达式、xpath 等)。我不知道正确的名称是叶节点。谢谢你的澄清。你知道一个很好的链接,我在哪里可以看到 Xpath 的选项?我不知道您使用“[not(*)]”的选项的存在和含义。再次感谢
  • 可爱的 xpath 表达式。
  • @Zurix W3Schools 有一个很好的XPath tutorial。具体来说,[] 是一个进一步约束表达式的 predicatenot() 是一个返回布尔值的 XPath 函数,在这种情况下,如果存在则返回 false是任何子元素 (*)
  • 我不确定它是否有帮助,但您可能想将 XPath //*[not(*)] 视为等同于 Ruby 伪代码 elements.select{|el| el.child_elements.empty?}
  • 非常感谢 Mark 的解释和帮助。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2013-03-21
  • 1970-01-01
  • 2011-07-19
  • 2014-01-14
  • 2012-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多