如何用Nokogiri只选择叶子节点?

时间:2013-07-26 20:00:13

标签: ruby xpath nokogiri

我正在寻找有关如何完成的建议。我正在尝试使用xpath的解决方案:

一个html示例:

<div>
  <div>
    <div>text div (leaf)</div>
    <p>text paragraph (leaf)</p>
  </div>
</div>
<p>text paragraph 2 (leaf)</p>

代码:

doc = Nokogiri::HTML.fragment("- the html above -")
result = doc.xpath("*[not(child::*)]")


[#<Nokogiri::XML::Element:0x3febf50f9328 name="p" children=[#<Nokogiri::XML::Text:0x3febf519b718 "text paragraph 2 (leaf)">]>] 

但是这个xpath只给了我最后一个“p”。我想要的就像一个扁平的行为,只返回叶子节点。

以下是stackoverflow中的一些参考答案:

How to select all leaf nodes using XPath expression?

XPath - Get node with no child of specific type

由于

3 个答案:

答案 0 :(得分:4)

您可以使用以下命令找到所有没有子元素的元素节点:

//*[not(*)]

示例:

require 'nokogiri'

doc = Nokogiri::HTML.parse <<-end
<div>
  <div>
    <div>text div (leaf)</div>
    <p>text paragraph (leaf)</p>
  </div>
</div>
<p>text paragraph 2 (leaf)</p>
end

puts doc.xpath('//*[not(*)]').length
#=> 3

doc.xpath('//*[not(*)]').each do |e|
    puts e.text
end
#=> "text div (leaf)"
#=> "text paragraph (leaf)"
#=> "text paragraph 2 (leaf)"

答案 1 :(得分:2)

您的代码存在问题:

doc = Nokogiri::HTML.fragment("- the html above -")

见这里:

require 'nokogiri'

html = <<END_OF_HTML
<div>
  <div>
    <div>text div (leaf)</div>
    <p>text paragraph (leaf)</p>
  </div>
</div>
<p>text paragraph 2 (leaf)</p>
END_OF_HTML


doc = Nokogiri::HTML(html)
#doc = Nokogiri::HTML.fragment(html)
results = doc.xpath("//*[not(child::*)]")
results.each {|result| puts result}

--output:--
<div>text div (leaf)</div>
<p>text paragraph (leaf)</p>
<p>text paragraph 2 (leaf)</p>

如果我这样做:

doc = Nokogiri::HTML.fragment(html)
results = doc.xpath("//*[not(child::*)]")
results.each {|result| puts result}

我没有输出。

答案 2 :(得分:2)

在XPath中,文本本身就是一个节点 - 所以给定你的评论你只想选择标签内容,而不是包含内容的标签 - 但是你会捕获<br/>(如果有的话)

我猜你正在寻找所有不包含其他元素的元素(标签)(这不是完全你所要求的) - 然后你' @Justin Ko的答案很好,并使用XPath表达式

//*[not(*)]

如果您确实想要查找所有叶节点,则无法使用*选择器,但需要使用node()

//node()[not(node())]

节点可以是元素,也可以是文本节点,注释,处理指令,属性甚至XML文档(但不能在其他元素中出现)。

如果你真的只想要文本节点,那就去找@Priti提出的//text(),这确实有点选择了你所要求的节点(通过突出显示它们,而不是通过定义哪些叶节点)。