我正在尝试解析包含有序列表和DL / DD标记的html。目标是创建一个xml结构,用于逐项列出添加某些属性的EACH标记的内容。在最终效果中展平结构(所需的输出将显示在问题的最后)。
以下是存储在文件中的html示例(在我的代码中包含在test.html中):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test Structure</title>
</head>
<body>
<ol><li>Item 1 - Level 1
<dl><dd>Item 1.1 - Level 2
</dd><dd>Item 1.2 - Level 2
</dd></dl>
</li><li>Item 2 - Level 1
<dl><dd>Item 2.1 - Level 2
<dl><dd>Item 2.1.1 - Level 3
</dd><dd>Item 2.1.2 - Level 3
<dl><dd>Item 2.1.2.1 - Level 4
</dd><dd>Item 2.1.2.2 - Level 4
</dd></dl>
</dd></dl>
</dd><dd>Item 2.2 - Level 2
<dl><dd>Item 2.2.1 - Level 3
</dd><dd>Item 2.2.2 - Level 3
<dl><dd>Item 2.2.2.1 - Level 4
</dd><dd>Item 2.2.2.2 - Level 4
</dd></dl>
</dd><dd>Item 2.2.3 - Level 3
<dl><dd>Item 2.2.3.1 - Level 4
</dd><dd>Item 2.2.3.2 - Level 4
</dd></dl>
</dd><dd>Item 2.2.4 - Level 3
</dd></dl>
</dd></dl>
</li><li>Item 3 - Level 1
<dl><dd>Item 3.1 - Level 2
</dd><dd>Item 3.2 - Level 2
</dd></dl>
</li></ol>
</body>
</html>
HTML输出(此处显示您没有看到在浏览器中看到的缩进):
- Item 1 - Level 1
- Item 1.1 - Level 2
- Item 1.2 - Level 2
- Item 2 - Level 1
- Item 2.1 - Level 2
- Item 2.1.1 - Level 3
- Item 2.1.2 - Level 3
- Item 2.1.2.1 - Level 4
- Item 2.1.2.2 - Level 4
- Item 2.2 - Level 2
- Item 2.2.1 - Level 3
- Item 2.2.2 - Level 3
- Item 2.2.2.1 - Level 4
- Item 2.2.2.2 - Level 4
- Item 2.2.3 - Level 3
- Item 2.2.3.1 - Level 4
- Item 2.2.3.2 - Level 4
- Item 2.2.4 - Level 3
- Item 3 - Level 1
- Item 3.1 - Level 2
- Item 3.2 - Level 2
期望的输出:
<job>
<req level='1'>Item 1 - Level 1</req>
<req level='1.1'>Item 1.1 - Level 2</req>
<req level='1.2'>Item 1.2 - Level 2</req>
<req level='2'>Item 2 - Level 1</req>
<req level='2.1'>Item 2.1 - Level 2</req>
<req level='2.1.1'>Item 2.1.1 - Level 3</req>
<req level='2.1.2'>Item 2.1.2 - Level 3</req>
<req level='2.1.2.1'>Item 2.1.2.1 - Level 4</req>
<req level='2.1.2.2'>Item 2.1.2.2 - Level 4</req>
<req level='2.2'>Item 2.2 - Level 2</req>
<req level='2.2.1'>Item 2.2.1 - Level 3</req>
<req level='2.2.2'>Item 2.2.2 - Level 3</req>
<req level='2.2.2.1'>Item 2.2.2.1 - Level 4</req>
<req level='2.2.2.2'>Item 2.2.2.2 - Level 4</req>
<req level='2.2.3'>Item 2.2.3 - Level 3</req>
<req level='2.2.3.1'>Item 2.2.3.1 - Level 4</req>
<req level='2.2.3.2'>Item 2.2.3.2 - Level 4</req>
<req level='2.2.4'>Item 2.2.4 - Level 3</req>
<req level='3'>Item 3 - Level 1</req>
<req level='3.1'>Item 3.1 - Level 2</req>
<req level='3.2'>Item 3.2 - Level 2</req>
</job>
请注意,我们希望从遍历结构而不是从每个LI和DD属性的实际内容派生层次结构...我的示例的内容列出了层次结构(1,1.1,1.2 ......)但是在实际数据中我们不会看到。 “level”属性应该反映结构的遍历。
我是Ruby和Nokogiri的新手,但这是我尝试阅读HTML(没有创建XML)。我被困在分离LI节点和内容。我尝试过使用.each
,children.each
等等:
require 'rubygems'
require 'open-uri'
require 'nokogiri'
url = "test.html"
doc = Nokogiri::HTML(open(url))
line = "1"
doc.css("ol[1]").children.each do |n|
puts line + n.content.to_s
line.succ!
n.children do |c|
puts line + c.content.to_s
line.succ!
end
end
答案 0 :(得分:1)
您可以使用node_name
方法确定什么是文本以及什么是子项,这是一个示例函数,它会在ol下显示html标记的名称:
def traverse(node, indent = 0)
node.children.each do |child|
next if child.node_name == "text"
puts " "*indent + child.node_name
traverse(child, indent+1)
end
end
traverse doc.css("ol[1]")
(我正在跳过的文本节点是标签的文本内容)