Java Jsoup Html 特殊字符转义

背景:

最近工作中有涉及到新老API返回内容的比较,有时为了方便看Diff,需要干预一下API返回的Response,忽略一些期望的Diff,更好的发现一些期望之外的Diff,来发现Bug。

更改Response Body实现:

下面这个函数就是把API返回的结果做一些替换,减少Diff的干扰。因为Response返回的Html格式,为了方便操作把Body先转换成String,做正则匹配替换操作,为了方便Python脚本比较内容不同(具体内容可以参考这篇文章《Python DiffLib–比较文本内容》),再把Body解析成Html格式输出到Log文件里。

这里用到了JsoupJsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

import org.jsoup.Jsoup;
import org.jsoup.select.Elements;

 private Document getDocumentBody(String body)
 {
        
        String headingAlign = "";
        body = body.replaceAll(headingAlign, "");

        String docMetadata = "[\\s\\S]*";
        body = body.replaceAll(docMetadata, "");

        String docChangeMC = "";
        body = body.replaceAll(docChangeMC, "");

        String refAnchor = "";
        body = body.replaceAll(refAnchor, "");

        Document doc = Jsoup.parseBodyFragment(body);
        return doc;
 }       

从处理过的Body中提取需要比较的部分,

 if (response.body() != null && !(response.body().asString().equals(""))) 
 {
       Elemnets seclaw = getDocumentBody(response.body().asString()).getElementsByTag("seclaw:seclaw");
       stream.println(seclaw);
}

遇到转义问题

API返回的Response原样输出时,字符都是正常的,但是经过Jsoup处理后,发现有些转义字符原样输出了,这将影响内空比较结果。
  代表空格
< 代表 <
> 代表 >

parseBodyFragment 方法创建一个空壳的文档,并插入解析过的HTML到body元素中。假如使用正常的 Jsoup.parse(String html) 方法,通常也可以得到相同的结果,但是明确将用户输入作为 body片段处理,以确保用户所提供的任何糟糕的HTML都将被解析成body元素。经过Jsoup的解析,将API原Response Body中的一些空格和<>符号以转义符的形式出现了。

 <heading>
     <title>Chapter 21&nbsp;&nbsp;&nbsp;&nbsp;Bonds and Guarantees</title>
 </heading>
<seclaw:level leveltype="unclassified">
     <heading>
      <title>&lt;emph typestyle="caps"&gt;Introduction to Bonds and Guarantees&lt;/emph&gt;</title>
     </heading>
     <seclaw:bodytext />
</seclaw:level>

关于转义字符串:

为什么要用转义字符串?

这就要说到HTML转义字符串
转义字符串(Escape Sequence)也称字符实体(Character Entity)。在HTML中,定义转义字符串的原因有两个:
第一个原因是像“<”和“>”这类符号已经用来表示HTML标签,因此就不能直接当作文本中的符号来使用。为了在HTML文档中使用这些符号,就需要定义它的转义字符串。当解释程序遇到这类字符串时就把它解释为真实的字符。在输入转义字符串时,要严格遵守字母大小写的规则。

第二个原因是,有些字符在ASCII字符集中没有定义,因此需要使用转义字符串来表示。

转义字符串的组成

转义字符串(Escape Sequence),即字符实体(Character Entity)分成三部分:第一部分是一个&符号,英文叫ampersand;第二部分是实体(Entity)名字或者是#加上实体(Entity)编号;第三部分是一个分号。

比如,要显示小于号(<),就可以写 < 或者 < 。

用实体(Entity)名字的好处是比较好理解,一看lt,大概就猜出是less than的意思,但是其劣势在于并不是所有的浏览器都支持最新的Entity名字。而实体(Entity)编号,各种浏览器都能处理。

提示:实体名称(Entity)是区分大小写的。

备注:同一个符号,可以用“实体名称”和“实体编号”两种方式引用,“实体名称”的优势在于便于记忆,但不能保证所有的浏览器都能顺利识别它,而“实体编号”则没有这种担忧,但它实在不方便记忆。

转义和反转义:

Java 中StringEscapeUtils 类进行转义和反转义,例如:

转义:

System.out.println(StringEscapeUtils.escapeHtml4("
"
));

输出:

&lt;div&gt;&lt;/div&gt;

反转义:

System.out.println(StringEscapeUtils.unescapeHtml4("<div></div>"));

输出:

<div></div>

所以有关转义的问题就可以得到解决了:

import org.apache.commons.lang3.StringEscapeUtils;
import org.jsoup.select.Elements;

  if (response.body() != null && !(response.body().asString().equals(""))) 
  {
       Elements elements = getDocumentBody(response.body().asString()).getElementsByTag("seclaw:seclaw");
       stream.println(StringEscapeUtils.unescapeHtml4(elements.toString()));
  }

这样反转义一下,前面输出有转义符的问题就解决了。

<heading>
    <title>Chapter 21    Bonds and Guarantees</title>
</heading>
<seclaw:level leveltype="unclassified">
    <heading>
        <title><emph typestyle="caps">Introduction to Bonds and Guarantees</emph></title>
    </heading>
    <seclaw:bodytext />
</seclaw:level>

你可能感兴趣的:(Tool,Utility,Jsoup,Escape,Sequence,字符串转义,html解析)