我正在寻找有关如何完成的建议。我正在尝试使用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
由于
答案 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()
,这确实有点选择了你所要求的节点(通过突出显示它们,而不是通过定义哪些叶节点)。