【问题标题】:Jsoup parse and nested tagsJsoup解析和嵌套标签
【发布时间】:2012-03-24 17:31:10
【问题描述】:

我正在学习 Jsoup 并拥有这个 HTML:

 [...]
 <p style="..."> <!-- div 1 -->
   Content
 </p>
 <p style="..."> <!-- div 2 -->
   Content
 </p>
 <p style="..."> <!-- div 3 -->
   Content
 </p>
 [...]

我使用 Jsoup.parse() 和 document select("p") 来捕获“内容”(效果很好)。但是……

 [...]
 <p style="..."> <!-- div 1 -->
   Content
 </p>
 <p style="..."> <!-- div 2 -->
   Content
 </p>
 <p style="..."> <!-- div 3 -->
   Content
   <p style="..."></p>
   <p style="..."></p>
 </p>
 [...]

在这个场景中,我看到 Jsoup.parse() 将这段代码转换为:

 [...]
 <p style="..."> <!-- div 1 -->
   Content
 </p>
 <p style="..."> <!-- div 2 -->
   Content
 </p>
 <p style="..."> <!-- div 3 -->
   Content
 </p>
 <p style="..."> <!-- div 4 -->
 </p>
 <p style="..."> <!-- div 5 -->
 </p>
 [...]

如何使用 Jsoup 保持嵌套段落的顺序(div 3 内的 div 4 和 5)?


添加示例:

HTML 文件

 <html>
 <head>
    <title>Title</title>
 </head>
 <body>
    <p style="margin-left:2em">
            <span class="one">Text</span>
            <span class="two"><span class="nest">Text</span></span>
            <span class="three"></span>
    </p>
    <p style="margin-left:2em">
            <span class="one">Text</span>
            <span class="two"><span class="nest">Text</span></span>
            <span class="three"></span>
    </p>
    <p style="margin-left:2em">
            <span class="one">Text</span>
            <span class="two"><span class="nest">Text</span></span>
            <span class="three"></span>
            <p style="margin-left:2em"></p>
            <p style="margin-left:2em"></p>
    </p>

 </body>
 </html>

Java 代码

Document doc = null;
doc = Jsoup.connect(URL_with_HTML).get();
System.out.println(doc.outerHtml());

返回

<html>
<head> 
 <title>Title</title> 
</head> 
<body> 
 <p style="margin-left:2em"> <span class="one">Text</span> <span class="two"><span class="nest">Text</span></span> <span class="three"></span> </p> 
 <p style="margin-left:2em"> <span class="one">Text</span> <span class="two"><span class="nest">Text</span></span> <span class="three"></span> </p> 
 <p style="margin-left:2em"> <span class="one">Text</span> <span class="two"><span class="nest">Text</span></span> <span class="three"></span> </p>
 <p style="margin-left:2em"></p> 
 <p style="margin-left:2em"></p> 
 <p></p>   
</body>
</html>

这是正确的吗?我使用 Jsoup 1.6.1。我知道 Jsoup 应该返回嵌套段落而不是以前的返回。

【问题讨论】:

  • 这似乎是一个错误。如果可以,请归档。
  • 我添加了带有文件/代码的示例以进行澄清。

标签: java jsoup


【解决方案1】:

HTML 中不存在嵌套段落。上一段自Jsoup implements the WHATWG HTML5 specification起自动关闭:

  1. p 标记会被以下任一自动关闭:addressarticleasideblockquotedivdlfieldsetfooter、 987654331 @,h1h2h3h4h5h6headerhgrouphrmainmenunavolppresectiontableul。因此&lt;p&gt;&lt;div&gt;&lt;/div&gt; becomes &lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;
  2. 名称为p(即&lt;/p&gt;)但没有相应的开始标签的结束标签是一个解析错误,并被&lt;p&gt; 替换。因此&lt;span&gt;&lt;/span&gt;&lt;/p&gt; 变为&lt;span&gt;&lt;/span&gt;&lt;p&gt;

所以 jsoup 是正确的,而你的 HTML 是无效的。

请务必理解您的 HTML 无效,因为您有太多 &lt;/p&gt;,而不是因为“嵌套”段落。嵌套不会发生,因为它们会自动关闭。但是后来的&lt;/p&gt; 已经过时了,因为“对应的”&lt;p&gt; 之前已经自动关闭了。

【讨论】:

  • 非常感谢! HTML 代码是第三方的(不是我的),我没有修改它。现在,我该如何解决这个问题? (将嵌套段落替换为 span class="p",例如,如果问题出在 parse() 方法中?)
  • @FabianBarney,Jsoup 不关心有效的 HTML 标签。请使用Jsoup.parse("&lt;html&gt;&lt;body&gt;&lt;xxx&gt;&lt;/xxx&gt;&lt;/body&gt;&lt;/html&gt;")进行测试。
  • 但是 jsoup 关心的是“真实世界”解析 HTML。自动关闭&lt;p&gt;&lt;p&gt; 内嵌套块元素的未定义行为是真实世界的解析。否则,对于像 ...&lt;p&gt;First paragraph&lt;p&gt;Second paragraph... 这样的绝对合法 HTML,您会遇到很多麻烦。不关闭&lt;p&gt; 是合法的!
  • @Manz jsoup 非常像浏览器那样进行解析。使用 Firebug 之类的工具检查您的页面,您会发现您的 HTML 得到了相同的解释。 (自动关闭的 p-tags 等)我们无法告诉您如何修复它,因为不清楚您想要的输出应该是什么样子。如果您需要嵌套块元素,则不能使用 &lt;p&gt; 作为外部标签。改用&lt;div&gt; ...
  • @FabianBarney,谢谢,我直到现在才知道。
【解决方案2】:

Hj,我明白原来的问题。但我认为这是 Jsoup 的一个错误(不是你的)。因为这是一个简单的例子:

<html>
    <head></head>
    <body>
        <p></p>
        <p>
            <div></div>
        </p>
    </body>
</html>

但是 Jsoup 会解析这个:

<html>
    <head></head>
    <body>
        <p></p>
        <p></p>
        <div></div>
        <p></p>
    </body>
</html>

如果可以,请提交此错误,以便作者修复它:-)

P.S:就一个“嗨”字,stackoverflow不允许吗?

【讨论】:

  • 我怀疑这不是错误。如果将“可疑”

    替换为 可以正常工作。也许,

    中的

    是 HTML 不正确的,Jsoup 明白尝试修复它吗?

  • 根据我的经验,Jsoup 并不关心 HTML 关键字。我一直在使用 Jsoup 来解析 XML,效果很好。您可以使用Jsoup.parse("&lt;html&gt;&lt;body&gt;&lt;xxx&gt;&lt;/xxx&gt;&lt;/body&gt;&lt;/html&gt;") 进行测试。
  • 一个&lt;p&gt;不允许包含任何块元素!所以“简单”的例子是无效的 (X)HTML。
  • @FabianBarney,谢谢,我明白了。
  • 单独使用 p 标签也有类似的问题。当我解析这个 HTML &lt;p&gt;&lt;p class="a"&gt;Sample Text &lt;/p&gt;Sample 1&lt;br&gt; Sample 2 &lt;/p&gt; 时,我得到的输出为 &lt;html&gt; &lt;head&gt;&lt;/head&gt; &lt;body&gt; &lt;p&gt;&lt;/p&gt; &lt;p class="a"&gt;Sample Text &lt;/p&gt;Sample 1 &lt;br&gt; Sample 2 &lt;p&gt;&lt;/p&gt; &lt;/body&gt; &lt;/html&gt;
猜你喜欢
  • 1970-01-01
  • 2015-02-09
  • 2012-02-18
  • 1970-01-01
  • 2011-09-24
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多