Jsoup代码解读之三-Document的输出

转载自   Jsoup代码解读之三-Document的输出

Jsoup官方说明里,一个重要的功能就是***output tidy HTML***。这里我们看看Jsoup是如何输出HTML的。

HTML相关知识

分析代码前,我们不妨先想想,"tidy HTML"到底包括哪些东西:

  • 换行,块级标签习惯上都会独占一行
  • 缩进,根据HTML标签嵌套层数,行首缩进会不同
  • 严格的标签闭合,如果是可以自闭合的标签并且没有内容,则进行自闭合
  • HTML实体的转义

这里要补充一下HTML标签的知识。HTML Tag可以分为block和inline两类。关于Tag的inline和block的定义可以参考http://www.w3schools.com/html/html_blocks.asp,而Jsoup的Tag类则是对Java开发者非常好的学习资料。

<!-- lang: java -->
// internal static initialisers:
// prepped from http://www.w3.org/TR/REC-html40/sgml/dtd.html and other sources
//block tags,需要换行
private static final String[] blockTags = {"html", "head", "body", "frameset", "script", "noscript", "style", "meta", "link", "title", "frame","noframes", "section", "nav", "aside", "hgroup", "header", "footer", "p", "h1", "h2", "h3", "h4", "h5", "h6","ul", "ol", "pre", "div", "blockquote", "hr", "address", "figure", "figcaption", "form", "fieldset", "ins","del", "s", "dl", "dt", "dd", "li", "table", "caption", "thead", "tfoot", "tbody", "colgroup", "col", "tr", "th","td", "video", "audio", "canvas", "details", "menu", "plaintext"
};
//inline tags,无需换行
private static final String[] inlineTags = {"object", "base", "font", "tt", "i", "b", "u", "big", "small", "em", "strong", "dfn", "code", "samp", "kbd","var", "cite", "abbr", "time", "acronym", "mark", "ruby", "rt", "rp", "a", "img", "br", "wbr", "map", "q","sub", "sup", "bdo", "iframe", "embed", "span", "input", "select", "textarea", "label", "button", "optgroup","option", "legend", "datalist", "keygen", "output", "progress", "meter", "area", "param", "source", "track","summary", "command", "device"
};
//emptyTags是不能有内容的标签,这类标签都是可以自闭合的
private static final String[] emptyTags = {"meta", "link", "base", "frame", "img", "br", "wbr", "embed", "hr", "input", "keygen", "col", "command","device"
};
private static final String[] formatAsInlineTags = {"title", "a", "p", "h1", "h2", "h3", "h4", "h5", "h6", "pre", "address", "li", "th", "td", "script", "style","ins", "del", "s"
};
//在这些标签里,需要保留空格
private static final String[] preserveWhitespaceTags = {"pre", "plaintext", "title", "textarea"
};

另外,Jsoup的Entities类里包含了一些HTML实体转义的东西。这些转义的对应数据保存在entities-full.propertiesentities-base.properties里。

Jsoup的格式化实现

在Jsoup里,直接调用Document.toString()(继承自Element),即可对文档进行输出。另外OutputSettings可以控制输出格式,主要是prettyPrint(是否重新格式化)、outline(是否强制所有标签换行)、indentAmount(缩进长度)等。

里面的继承和互相调用关系略微复杂,大概是这样子:

Document.toString()=>Document.outerHtml()=>Element.html(),最终Element.html()又会循环调用所有子元素的outerHtml(),拼接起来作为输出。

<!-- lang: java -->
private void html(StringBuilder accum) {for (Node node : childNodes)node.outerHtml(accum);
}

outerHtml()会使用一个OuterHtmlVisitor对所以子节点做遍历,并拼装起来作为结果。

<!-- lang: java -->
protected void outerHtml(StringBuilder accum) {new NodeTraversor(new OuterHtmlVisitor(accum, getOutputSettings())).traverse(this);
}

OuterHtmlVisitor会对所有子节点做遍历,并调用node.outerHtmlHead()node.outerHtmlTail两个方法。

<!-- lang: java -->
private static class OuterHtmlVisitor implements NodeVisitor {private StringBuilder accum;private Document.OutputSettings out;public void head(Node node, int depth) {node.outerHtmlHead(accum, depth, out);}public void tail(Node node, int depth) {if (!node.nodeName().equals("#text")) // saves a void hit.node.outerHtmlTail(accum, depth, out);}
}

我们终于找到了真正工作的代码,node.outerHtmlHead()node.outerHtmlTail。Jsoup里每种Node的输出方式都不太一样,这里只讲讲两种主要节点:ElementTextNodeElement是格式化的主要对象,它的两个方法代码如下:

<!-- lang: java -->
void outerHtmlHead(StringBuilder accum, int depth, Document.OutputSettings out) {if (accum.length() > 0 && out.prettyPrint()&& (tag.formatAsBlock() || (parent() != null && parent().tag().formatAsBlock()) || out.outline()) )//换行并调整缩进indent(accum, depth, out);accum.append("<").append(tagName());attributes.html(accum, out);if (childNodes.isEmpty() && tag.isSelfClosing())accum.append(" />");elseaccum.append(">");
}void outerHtmlTail(StringBuilder accum, int depth, Document.OutputSettings out) {if (!(childNodes.isEmpty() && tag.isSelfClosing())) {if (out.prettyPrint() && (!childNodes.isEmpty() && (tag.formatAsBlock() || (out.outline() && (childNodes.size()>1 || (childNodes.size()==1 && !(childNodes.get(0) instanceof TextNode)))))))//换行并调整缩进indent(accum, depth, out);accum.append("</").append(tagName()).append(">");}
}

而ident方法的代码只有一行:

<!-- lang: java -->
protected void indent(StringBuilder accum, int depth, Document.OutputSettings out) {//out.indentAmount()是缩进长度,默认是1accum.append("\n").append(StringUtil.padding(depth * out.indentAmount()));
}

代码简单明了,就没什么好说的了。值得一提的是,StringUtil.padding()方法为了减少字符串生成,把常用的缩进保存到了一个数组中。

好了,水了一篇文章,下一篇将比较有技术含量的parser部分。

另外,通过本节的学习,我们学到了要把StringBuilder命名为accum,而不是sb


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络协议和通信规则,计算机网络协议基本知识

计算机网络协议网络协议为计算机网络中进行数据交换而建立的规则、标准或约定的集合。例如&#xff0c;网络中一个微机用户和一个大型主机的操作员进行通信&#xff0c;由于这两个数据终端所用字符集不同&#xff0c;因此操作员所输入的命令彼此不认识。为了能进行通信&#xf…

微软开源P语言,实现安全的异步事件驱动编程

微软最近开源了P语言&#xff0c;致力于在Linux、macOS和Windows上编写安全的异步事件驱动程序。 微软将P描述为一种领域特定语言&#xff0c;对异步系统的组件间通信进行建模&#xff0c;例如嵌入式、网络或分布式系统。P程序是通过有限状态机&#xff08;finite state machin…

系统架构设计师考试4

架构师考试经验总结 2014年12月14日 11:35:52 langkailen 阅读数 7251 2011年11月中旬参加了系统架构设计师的考试&#xff0c;考试还算比较顺利&#xff0c;顺利通过了国家分数线&#xff0c;获得了资格证书。除去考试不说&#xff0c;在准备考试的这段时间里了解了一下架构设…

a卡 n卡 html5性能,a卡n卡天梯图_a卡n卡显卡性能对照表2020年5月

相信许多自己购买过显卡的用户都知道a卡和n卡&#xff0c;决定一款显卡的性能好坏主要是架构、流处理器、核心频率、显存带宽、显存位宽、显存容量等多种因素决定。但是从参数来看新手比较难看出一个显卡的好坏&#xff0c;最简单的就是看天梯图&#xff0c;下面我们就一起来看…

Jsoup代码解读之二-DOM相关对象

转载自 Jsoup代码解读之二-DOM相关对象之前在文章中说到&#xff0c;Jsoup使用了一套自己的DOM对象体系&#xff0c;和Java XML API互不兼容。这样做的好处是从XML的API里解脱出来&#xff0c;使得代码精炼了很多。这篇文章会说明Jsoup的DOM结构&#xff0c;DOM的遍历方式。在…

sql server 2012远程链接的方法及步骤

首先说下什么是sql server:(以下是应用某度某科的内容) SQL Server 是Microsoft 公司推出的关系型数据库管理系统。具有使用方便可伸缩性好与相关软件集成程度高等优点&#xff0c;可跨越从运行Microsoft Windows 98 的膝上型电脑到运行Microsoft Windows 2012 的大型多处理器的…

系统架构师考试5

https://download.csdn.net/download/u014484863/10041079 https://download.csdn.net/download/u014484863/10041079 下载首页 精品专辑 我的资源 上传资源赚积分 已下载 我的收藏 参与活动送会员hot 下载帮助 下载 > 考试认证 > 软考等考 > 系统架构师复习资料…

ASP.NET Core 性能对比评测(ASP.NET,Python,Java,NodeJS)

前言 性能是我们日常生活中经常接触到的一个词语&#xff0c;更好的性能意味着能给我们带来更好的用户体检。比如我们在购买手机、显卡、CPU等的时候&#xff0c;可能会更加的关注于这样指标&#xff0c;所以本篇就来做一个性能评测。 性能也一直是我们开发人员一直追求的一个目…

计算机三级网络技术题库第15套,第15套 上机操作题

一、基本操作题*********本题型共有5小题*********1. 将考生文件夹下的RDEV文件夹中的文件KING.MAP删除。2. 在考生文件夹下BEF文件夹中建立一个名为SEOG的新文件夹。3. 将考生文件夹下RM文件夹中的文件PALY.PRG复制到考生文件夹下BMP文件夹中。4. 将考生文件夹下TEED文件夹中的…

Jsoup代码解读之一-概述

转载自 Jsoup代码解读之一-概述今天看到一个用python写的抽取正文的东东&#xff0c;美滋滋的用Java实现了一番&#xff0c;放到了webmagic里&#xff0c;然后发现Jsoup里已经有了…觉得自己各种不靠谱啊&#xff01;算了&#xff0c;静下心来学学好东西吧&#xff01; Jsoup…

法在计算机课程中的应用,尝试教学法在中职《计算机应用基础》课程中的应用(原稿)...

《尝试教学法在中职《计算机应用基础》课程中的应用(原稿).doc》由会员分享&#xff0c;可免费在线阅读全文&#xff0c;更多与《尝试教学法在中职《计算机应用基础》课程中的应用(原稿)》相关文档资源请在帮帮文库(www.woc88.com)数亿文档库存里搜索。1、尝试练习,安排学生进行…

Visual Studio“15”进一步改善性能和易用性

随着Visual Studio“15”开发工作的继续&#xff0c;微软也在不断介绍着为了改善该产品执行速度和安装后体积所做的诸多努力。第5个技术预览版近日已发布&#xff0c;在这些方面也有了进一步提高。 在微软公司John Montgomery发布的新闻稿中&#xff0c;他通过一个视频对比了Ro…

JAVA缓存的实现

转载自 JAVA缓存的实现 缓存可分为二大类: 一、通过文件缓存,顾名思义文件缓存是指把数据存储在磁盘上&#xff0c;不管你是以XML格式&#xff0c;序列化文件DAT格式还是其它文件格式&#xff1b; 二、内存缓存&#xff0c;也就是实现一个类中静态Map,对这个Map进行常规的增删…

myeclipse 2016 ci3破解教程(含软件下载)

一、myeclipse简介&#xff1a; MyEclipse企业级工作平台&#xff08;MyEclipseEnterprise Workbench &#xff0c;简称MyEclipse&#xff09;是对EclipseIDE的扩 展&#xff0c;利用它我们可以在数据库和JavaEE的开发、发布以及应用程序服务器的整合方面极大的提高工作效 率。…

系统架构师考试6

系统架构设计师考试经验 2018年01月29日 15:23:46 大宝大宝吃饱睡好 阅读数 346 原文链接 1. 考试准备流程 考试报名地址 网站比较奇葩&#xff0c;需要IE或者360&#xff0c;chrome不行 1.1 报名 网站注册【大概9月份】填写报名信息上传照片【需要注意照片大小&#xff0c;…

计算机主机组成实验,计算机组成原理实验-运算器组成实验报告

计算机组成原理实验-运算器组成实验报告 曾国江—计算机组成原理实验报告 - 0 - 计算机组成原理课程实验报告9.3 运算器组成实验姓 名&#xff1a; 曾国江 学 号&#xff1a; 系 别&#xff1a; 计算机工程学院 班 级&#xff1a; 网络工程1班 指导老师&#xff1a; 完成时间&a…

Jsoup解析HTML实例及文档方法详解

转载自 Jsoup解析HTML实例及文档方法详解这篇文章主要介绍了Jsoup如何解析一个HTML文档、从文件加载文档、从URL加载Document等方法&#xff0c;对Jsoup常用方法做了详细讲解&#xff0c;最近提供了一个示例供大家参考 使用DOM方法来遍历一个文档 从元素抽取属性&#xff0c;文…

系统架构师考试9

系统架构师复习经验及资料共享 [复制链接] 发表于 2018-2-5 11:25 | 来自 51CTO网页 [只看他] 楼主 在入职第一天。。 人力&#xff1a;有没有证书 我&#xff1a;。。没有&#xff0c;目前都有哪些证书 人力回了一张图&#xff0c;上面大概有PMP、项目管理师、系统架构师…

java通过commons-fileupload实现多张图片的上传(servlet)

//添加食品信息private void addProduct(HttpServletRequest request, HttpServletResponse response) throws IOException{PrintWriter out response.getWriter();/*Date datenew Date();SimpleDateFormat formatnew SimpleDateFormat("yyyy-MM-dd hh:mm:ss");Stri…

javaweb项目搭建ehcache缓存系统

转载自 javaweb项目搭建ehcache缓存系统EhCache 是一个纯Java的进程内缓存框架&#xff0c;具有快速、精干等特点&#xff0c;是Hibernate中默认的CacheProvider&#xff0c;同时在项目开发中也被广泛使用到。接下来就以用户缓存为例&#xff0c;基于javaweb项目来搭建ehcache…