使用 JSoup 解析 HTML 列表以创建树结构
Parse HTML list using JSoup to create Tree structure
我有 HTML 个列表,其结构与我需要使用 JSoup 解析的结构完全相同(我的语言是 Java)。这是一个例子:
<div class="ulist">
<ul>
<li><p>Healthy Food</p></li>
<div class="ulist">
<ul>
<li><p>Vegetables</p></li>
<div class="ulist">
<ul>
<li> <p>Carrots</p> </li>
<li> <p>Lettuce</p> </li>
<li> <p>Cucumbers</p> </li>
</ul>
</div> </li>
<li> <p>Fruits</p>
<div class="ulist">
<ul>
<li> <p>Apples</p> </li>
<li> <p>Bananas</p> </li>
<li> <p>Canned Fruits</p></li>
<div class="ulist">
<ul>
<li> <p>Peaches</p> </li>
<li> <p>Pears</p> </li>
</ul>
</div>
</ul>
</div>
</li>
</ul>
</div>
</ul>
</div>
因为这个数据基本上只是一个树数据结构,我希望能够解析它并从数据中创建一个树。我在使用 JSoup 时遇到困难,因为看起来您无法真正按预期遍历 DOM。
例如,代码如下:
Elements elList = doc.select("ul");
for (Element el: elList){
Elements subList = el.select("ul");
for (Element subEl : subList){
//do whatever you need to do
}
}
产生以下结果,它似乎不是 "walking" 或 "traversing",而是不断从文档中选择相同的内容:
遍历此列表并将其放入树结构的代码是什么?
JSoup 将 DOM 构建为内存中的数据结构,您可以通过非常强大的 "random access" 方式访问它,例如使用出色的 css 选择器实现。要使用 JSoup 解决您的问题,您可以像这样循环处理结果:
Elements elList = doc.select("ul");
for (Element el: elList){
Elements subList = el.select("ul");
for (Element subEl : subList){
//do whatever you need to do
}
}
但是,如果您需要遍历非常大的 html 文件并且文件结构良好,您可能需要使用像 SAX 这样的库。这避免了将整个 DOM 保存在内存中。
在 JSoup 中,select()
和 getElementByTag()
return 当前元素作为结果的一部分,如果它匹配标签。
因此,当您执行 doc.select("ul")
并对结果执行 select()
时,您会得到相同的结果,正如您已经注意到的那样。
正确执行此操作的关键是获取第一个元素,然后搜索它的子元素。
大致如下:
public static Node processTree( Element elem ) {
Node result;
Elements elList = elem.getElementsByTag("ul");
if ( elList == null || elList.size() == 0 ) {
return null;
};
result = new Node();
Element current = elList.first();
elList = current.children();
// Process LI elements and add them as content to the
// result Node
...
// Now go down the tree
if ( elList != null && elList.size() != 0 ) {
for ( Element el : elList ) {
Node elTree = processTree( el );
if ( elTree != null ) {
result.addChild( elTree );
}
}
}
return result;
}
(当然,这只是一个草图。Node
将是你的树结构节点。这样做的目的是告诉你,你必须遍历 children。如果你愿意,你可以在同一个循环中处理 li
个元素)
我有 HTML 个列表,其结构与我需要使用 JSoup 解析的结构完全相同(我的语言是 Java)。这是一个例子:
<div class="ulist">
<ul>
<li><p>Healthy Food</p></li>
<div class="ulist">
<ul>
<li><p>Vegetables</p></li>
<div class="ulist">
<ul>
<li> <p>Carrots</p> </li>
<li> <p>Lettuce</p> </li>
<li> <p>Cucumbers</p> </li>
</ul>
</div> </li>
<li> <p>Fruits</p>
<div class="ulist">
<ul>
<li> <p>Apples</p> </li>
<li> <p>Bananas</p> </li>
<li> <p>Canned Fruits</p></li>
<div class="ulist">
<ul>
<li> <p>Peaches</p> </li>
<li> <p>Pears</p> </li>
</ul>
</div>
</ul>
</div>
</li>
</ul>
</div>
</ul>
</div>
因为这个数据基本上只是一个树数据结构,我希望能够解析它并从数据中创建一个树。我在使用 JSoup 时遇到困难,因为看起来您无法真正按预期遍历 DOM。
例如,代码如下:
Elements elList = doc.select("ul");
for (Element el: elList){
Elements subList = el.select("ul");
for (Element subEl : subList){
//do whatever you need to do
}
}
产生以下结果,它似乎不是 "walking" 或 "traversing",而是不断从文档中选择相同的内容:
遍历此列表并将其放入树结构的代码是什么?
JSoup 将 DOM 构建为内存中的数据结构,您可以通过非常强大的 "random access" 方式访问它,例如使用出色的 css 选择器实现。要使用 JSoup 解决您的问题,您可以像这样循环处理结果:
Elements elList = doc.select("ul");
for (Element el: elList){
Elements subList = el.select("ul");
for (Element subEl : subList){
//do whatever you need to do
}
}
但是,如果您需要遍历非常大的 html 文件并且文件结构良好,您可能需要使用像 SAX 这样的库。这避免了将整个 DOM 保存在内存中。
在 JSoup 中,select()
和 getElementByTag()
return 当前元素作为结果的一部分,如果它匹配标签。
因此,当您执行 doc.select("ul")
并对结果执行 select()
时,您会得到相同的结果,正如您已经注意到的那样。
正确执行此操作的关键是获取第一个元素,然后搜索它的子元素。
大致如下:
public static Node processTree( Element elem ) {
Node result;
Elements elList = elem.getElementsByTag("ul");
if ( elList == null || elList.size() == 0 ) {
return null;
};
result = new Node();
Element current = elList.first();
elList = current.children();
// Process LI elements and add them as content to the
// result Node
...
// Now go down the tree
if ( elList != null && elList.size() != 0 ) {
for ( Element el : elList ) {
Node elTree = processTree( el );
if ( elTree != null ) {
result.addChild( elTree );
}
}
}
return result;
}
(当然,这只是一个草图。Node
将是你的树结构节点。这样做的目的是告诉你,你必须遍历 children。如果你愿意,你可以在同一个循环中处理 li
个元素)