日期:2014-05-17  浏览次数:20739 次

jsoup 处理HTML 坑记录

? ? jsoup 是一款非常优秀的处理HTML的java工具,最大的特点就是拥有类似jquery的select操作。使用非常简单,但是最近本人在使用过程中,由于不熟悉踩了一个坑,记录已备忘。

?

代码如下: ? ?

public static void main(String[] args) {
        String content = "<a href=\"test.html\" title=\"men tshirt\" >men tshirt</a>";
        try {

            Document document = Jsoup.parse(content);
            Elements links = document.select("a");
            for (Element link : links) {
                link.attr("clickdata", "adfafgadsfaf");
                if (!link.hasClass("click-target-with-quot")) {
                    link.addClass("click-target-with-quot");
                }
            }
            System.out.println(document.html());// 错误代码
            System.out.println(document.body().html());//正确代码
        } catch (Exception e) {
        }
    }

?

需求也很简单,将一个HTML片段中的所有的<a>标签,增加一个class,和一个自定义属性。

代码中红色标注了错误和正确的代码,区别在于错误的代码会返回添加了<html>等头尾的标签。

?

<html>
 <head></head>
 <body>
  <a href="test.html" title="men tshirt" clickdata="adfafgadsfaf" class=" click-target-with-quot">men tshirt</a>
 </body>
</html>

?

正确的如下:

<a href="test.html" title="men tshirt" clickdata="adfafgadsfaf" class=" click-target-with-quot">men tshirt</a>

?

原因在于:在 Jsoup.parse解析的时候在类HtmlTreeBuilderState类中会判断是否属于BeforeHtml,BeforeHead等等状态,如果满足的话会被强制添加<html>标签。

具体代码如下:

BeforeHtml {
        boolean process(Token t, HtmlTreeBuilder tb) {
            if (t.isDoctype()) {
                tb.error(this);
                return false;
            } else if (t.isComment()) {
                tb.insert(t.asComment());
            } else if (isWhitespace(t)) {
                return true; // ignore whitespace
            } else if (t.isStartTag() && t.asStartTag().name().equals("html")) {
                tb.insert(t.asStartTag());
                tb.transition(BeforeHead);
            } else if (t.isEndTag() && (StringUtil.in(t.asEndTag().name(), "head", "body", "html", "br"))) {
                return anythingElse(t, tb);
            } else if (t.isEndTag()) {
                tb.error(this);
                return false;
            } else {
                return anythingElse(t, tb);
            }
            return true;
        }

        private boolean anythingElse(Token t, HtmlTreeBuilder tb) {
            tb.insert("html");
            tb.transition(BeforeHead);
            return tb.process(t);
        }
    }

?

?

?

?

本站支持?pay for your wishes