HTML (特别是MathML)可以被大量嵌套。使用,我想在父节点中搜索最上层的节点,这些节点是任意的。下面是一个HTML/MathML示例。
<math><semantics>…(任意深度) <mrow> (称为(1)) <mrow> (1-1)1. `<mrow>` (2)
1. `<mrow>` (2-1)
2. `<mrow>` (2-2)对于Nokogiri::HTML对象,page,page.css("math mrow")返回<mrow>所有节点的数组,在本例中数组大小为5,最后一个节点为"<mrow> (2-2)“。
我的目标是在最上层识别最后一个<mrow>节点,即上面示例中的"<mrow> (2)“(以便我可以在它之后添加另一个节点)。
换句话说,我想得到“这类节点中最浅的深度上的最后一个节点”。节点类型的最上层的深度是未知的,因此我不能限制搜索的深度。
发布于 2022-08-23 12:19:17
如果您希望在深度方面使用最高级的mrow节点,则可以在所有:first-of-type中选择ancestors数量最少的节点。
first_mrow = page.css('mrow:first-of-type').min_by.with_index { |node, index| [node.ancestors.size, index] }添加with_index可以确保对于祖先数量相同的节点,第一个节点将被选择。
要从文档的开头获取第一个mrow节点(不管深度如何),只需使用:
first_mrow = page.at_css('mrow')对于第一个mrow节点,您可以选择其parent节点:
parent = first_mrow.parent最后,从父节点(立即)的last节点中检索mrow元素:
last_mrow = parent.css('> mrow').last后者也可以通过:last-of-type CSS伪类表示:
last_mrow = parent.at_css('> mrow:last-of-type')发布于 2022-08-23 12:58:04
听起来像是第一眼就看到的广度优先搜索问题:向队列中添加一个节点,如果它不是期望的类型,删除它并以相反的顺序将它的子节点添加到队列中,重复直到找到所需的节点(由于BFS属性,它将是最浅的节点,而最后一个节点是因为我们反向添加子节点)。
快速而肮脏的例子:
require "nokogiri"
def find_last_shallowest(root)
queue = [root]
while queue.any?
element = queue.shift
break element if matching?(element)
queue += element.children.reverse
end
end
def matching?(element)
# Put your matching logic here
element.name == "m"
end
doc = <<~XML
<foo>
<bar>
<m>
<x></x>
</m>
</bar>
<baz>
</baz>
<m>
<y></y>
</m>
<m>
<z></z>
</m>
</foo>
XML
xml = Nokogiri::XML(doc)
find_last_shallowest(xml.root) # => #(Element:0xf744 { name = "m", children = [ #(Text "\n "), #(Element:0xf758 { name = "z" }), #(Text "\n ")] })它发现m的东西,其中有z作为一个孩子-这是最后和最浅的一个.
https://stackoverflow.com/questions/73457783
复制相似问题