浅谈 Java 主流开源类库解析 XML
在大型项目编码推进中,涉及到 XML 解析问题时,大多数程序员都不太会选用底层的解析方式直接编码。
主要存在编码复杂性、难扩展、难复用....,但如果你是 super 程序员或是一个人的项目,也不妨一试。
Jdom/Dom4j/Xstream... 基于底层解析方式重新组织封装的开源类库,简洁明了的 API,稳定高效的运行表现。
Dom4j 基于 JAXP 解析方式,性能优异、功能强大、极易使用的优秀框架。想了解底层解析方式请翻看:浅谈 Java XML 底层解析方式
Jdom 你细看内部代码,本质也是基于 JAXP 但包结构被重新组织, API 大量使用了 Collections 类,在性能上被 dm4j 压了好几个档次。
Xstream 基于 xmlpull 的 OXMapping 技术,更加倾向于将 XML 解析后映射为 Java 世界中的对象,等会在代码中会看的很清楚。
如果你是一名大型项目技术负责人,需求中涉及 XML 解析方面的要求,在程序员编码开始前你需要在充分了解需求的前提下。
来拿捏 XML 解析解决方案所采用的技术,请收藏这篇博客,到时将会给你一些帮助和指导。
实例 demo 地址:https://git.oschina.net/LanboEx/xml-parse-demo.git
需要解析的还是上篇的中 demo.xml,中规中矩不复杂也不简单。
- <?xml version="1.0"?>
- <classGrid>
- <classGridlb>
- <class_id>320170105000009363</class_id>
- <class_number>0301</class_number>
- <adviser>018574</adviser>
- <studentGrid>
- <studentGridlb>
- <stu_id>030101</stu_id>
- <stu_name>齐天</stu_name>
- <stu_age>9</stu_age>
- <stu_birthday>2008-11-07</stu_birthday>
- </studentGridlb>
- <studentGridlb>
- <stu_id>030102</stu_id>
- <stu_name>张惠</stu_name>
- <stu_age>10</stu_age>
- <stu_birthday>2009-04-08</stu_birthday>
- </studentGridlb>
- <studentGridlb>
- <stu_id>030103</stu_id>
- <stu_name>龙五</stu_name>
- <stu_age>9</stu_age>
- <stu_birthday>2008-11-01</stu_birthday>
- </studentGridlb>
- </studentGrid>
- </classGridlb>
- <classGridlb>
- <class_id>420170105000007363</class_id>
- <class_number>0302</class_number>
- <adviser>018577</adviser>
- <studentGrid>
- <studentGridlb>
- <stu_id>030201</stu_id>
- <stu_name>马宝</stu_name>
- <stu_age>10</stu_age>
- <stu_birthday>2009-09-02</stu_birthday>
- </studentGridlb>
- </studentGrid>
- </classGridlb>
- </classGrid>
demo.xml
1. Jdom
Jdom 基于树处理 XML,需要将树加载到内存中,所以你懂的大于内存的 XML 文件,Jdom 其实是拒绝的。
Jdom 具有 SAX 的 java 规则,可以使用推模型分析 XML,所以在一定程度上解析速度可以保证。
Jdom 没有向下兼容的限制,所以比底层 dom 简单,但在表示文档逻辑模型时,不能保证每个字节真正变换。
mvn 依赖:
- <dependency>
- <groupId>jdom</groupId>
- <artifactId>jdom</artifactId>
- <version>1.1</version>
- </dependency>
实例 demo (将 demo.xml studentGridlbb 节点的值解析出来,组成业务实体对象) 。
- String path = Thread.currentThread().getContextClassLoader().getResource("demo.xml").getPath();
- SAXBuilder jdomsaxBuilder = new SAXBuilder(false);
- Document doc = jdomsaxBuilder.build(path);
- Element rootElement = doc.getRootElement();
- List<StudentGridlb> studentGridlbList = new ArrayList<>();
- StudentGridlb studentGridlb;
- for (Object classGridlb : rootElement.getChildren("classGridlb")) {
- Element classGridlbEle = (Element) classGridlb;
- for (Object studentGrid : classGridlbEle.getChild("studentGrid").getChildren("studentGridlb")) {
- Element studentGridEle = (Element) studentGrid;
- studentGridlb = new StudentGridlb();
- studentGridlb.setStu_id(studentGridEle.getChildTextTrim("stu_id"));
- studentGridlb.setStu_age(Integer.parseInt(studentGridEle.getChildTextTrim("stu_age")));
- studentGridlb.setStu_name(studentGridEle.getChildTextTrim("stu_name"));
- DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
- studentGridlb.setStu_birthday(format.parse(studentGridEle.getChildTextTrim("stu_birthday")));
- studentGridlbList.add(studentGridlb);
- }
- }
- XMLOutputter outputter = new XMLOutputter();
- outputter.output(doc, new FileOutputStream(path));
2. Dom4j
Dom4j 为了支持 XPath、XML Schema、基于事件处理大文档或流文档。
Dom4j 为提供构建文档表示的选项,为可通过 Dom4j-API 和标准底层 dom-API 并行访问功能。
为实现上述宏伟目标,Dom4j 使用接口和抽象基本类方法并大量使用 JDK 中 Collections 类。
所以 Dom4j 有丰富的 API,在灵活性上面 Dom4j 更占有优势,性能方面也无可挑剔。
声名在外的 Sun-JAXM,大名鼎鼎的 Hibernate 中XML 配置文件解析都使用的是 Dom4j。
mvn 依赖:
- <!--MetaStuff dom4j-->
- <dependency>
- <groupId>dom4j</groupId>
- <artifactId>dom4j</artifactId>
- <version>1.6.1</version>
- <exclusions>
- <exclusion>
- <groupId>xml-apis</groupId>
- <artifactId>xml-apis</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
剔除 xml-apis 的用意 JDK 中已经有对应的类,如不剔除在部署 weblogic 时会出现 Jar 冲突。
实例 demo (将 demo.xml studentGridlbb 节点的值解析出来,组成业务实体对象) 。
- String path = Thread.currentThread().getContextClassLoader().getResource("demo.xml").getPath();
- SAXReader reader = new SAXReader();
- Document document = reader.read(new File(path));
- List<StudentGridlb> studentGridlbList = new ArrayList<>();
- StudentGridlb studentGridlbVo;
- for (Object classGridlb : document.getRootElement().elements("classGridlb")) {
- Element classGridlbEle = (Element) classGridlb;
- for (Object studentGridlb : classGridlbEle.element("studentGrid").elements("studentGridlb")) {
- Element studentGridlbEle = (Element) studentGridlb;
- studentGridlbVo = new StudentGridlb();
- studentGridlbVo.setStu_id(studentGridlbEle.elementTextTrim("stu_id"));
- studentGridlbVo.setStu_age(Integer.parseInt(studentGridlbEle.elementTextTrim("stu_age")));
- studentGridlbVo.setStu_name(studentGridlbEle.elementTextTrim("stu_name"));
- DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
- studentGridlbVo.setStu_birthday(format.parse(studentGridlbEle.elementTextTrim("stu_birthday")));
- studentGridlbList.add(studentGridlbVo);
- }
- }
3. Xstream
Xstream 为基于注解不需要其它辅助类或映射文件 的OXMapping 技术,如果你用过 hibernate 或 mybatis 之类的 ORM 框架就不难理解这里的 OXM。
Xstream 可以将 JavaBean 序列化为 XML,或将 XML 反序列化为 JavaBean,使得XML序列化不再繁琐。
Xstream 也可以将 JavaBean 序列化成 Json 或反序列化,使用非常方便。
没有映射文件而且底层使用 xmlpull 推模型解析 XML,高性能、低内存占用,结合简洁明了的 API,上手基本是分分钟的事情。
Xstream 同时也可以定制转换类型策略并配有详细的错误诊断,能让你快速定位问题。
使用 Xstream 时,规范和合理的业务对象命名是关键,下面是针对 demo.xml 我抽象的几个业务实体。
- @XStreamAlias("classGrid")
- public class ClassGrid {
- @XStreamImplicit(itemFieldName="classGridlb")
- private List<ClassGridlb> classGridlbList;
- public List<ClassGridlb> getClassGridlbList() {
- return classGridlbList;
- }
- public void setClassGridlbList(List<ClassGridlb> classGridlbList) {
- this.classGridlbList = classGridlbList;
- }
- }
ClassGrid
- @XStreamAlias("classGridlb")
- public class ClassGridlb {
- private String class_id;
- private String class_number;
- private String adviser;
- private StudentGrid studentGrid;
- public String getClass_id() {
- return class_id;
- }
- public void setClass_id(String class_id) {
- this.class_id = class_id;
- }
- public String getClass_number() {
- return class_number;
- }
- public void setClass_number(String class_number) {
- this.class_number = class_number;
- }
- public String getAdviser() {
- return adviser;
- }
- public void setAdviser(String adviser) {
- this.adviser = adviser;
- }
- public StudentGrid getStudentGrid() {
- return studentGrid;
- }
- public void setStudentGrid(StudentGrid studentGrid) {
- this.studentGrid = studentGrid;
- }
- }
ClassGridlb
- @XStreamAlias("studentGrid")
- public class StudentGrid {
- @XStreamImplicit(itemFieldName="studentGridlb")
- private List<StudentGridlb> studentGridlbList;
- public List<StudentGridlb> getStudentGridlbList() {
- return studentGridlbList;
- }
- public void setStudentGridlbList(List<StudentGridlb> studentGridlbList) {
- this.studentGridlbList = studentGridlbList;
- }
- }
StudentGrid
- @XStreamAlias("studentGridlb")
- public class StudentGridlb {
- private String stu_id;
- private String stu_name;
- private Integer stu_age;
- @XStreamConverter(value=DateConverter.class)
- private Date stu_birthday;
- public String getStu_id() {
- return stu_id;
- }
- public void setStu_id(String stu_id) {
- this.stu_id = stu_id;
- }
- public String getStu_name() {
- return stu_name;
- }
- public void setStu_name(String stu_name) {
- this.stu_name = stu_name;
- }
- public Integer getStu_age() {
- return stu_age;
- }
- public void setStu_age(Integer stu_age) {
- this.stu_age = stu_age;
- }
- public Date getStu_birthday() {
- return stu_birthday;
- }
- public void setStu_birthday(Date stu_birthday) {
- this.stu_birthday = stu_birthday;
- }
- @Override
- public String toString() {
- return "StudentGridlb{" + "stu_id='" + stu_id + '\'' + ", stu_name='" + stu_name + '\'' + ", stu_age=" + stu_age + ", stu_birthday=" + stu_birthday + '}';
- }
- }
StudentGridlb
抽象好 XML 业务实体之后,接下来就很简单了,只需要三行代码。
- Xstream Xstream = new Xstream(new DomDriver());
- Xstream.processAnnotations(ClassGrid.class);
- ClassGrid classGrid = (ClassGrid) Xstream.fromXML(new File(Thread.currentThread().getContextClassLoader().getResource("demo.xml").getPath()));
4. 小结
如果你看到过我上篇底层解析方式和这篇的开源类库对比下,封装优秀类库代码编写量会小很多,简洁的 API 使用起来很顺手。
Dom4j/Jdom 都支持对 XML 文档的增删改查动作,毕竟是已树模型加载到内存中进行的操作。
Xstream 专注于 XML 和业务对象之间的序列化和反序列化,删除和修改原 XML 文档实践起来相当困难。
我个人的建议,在项目中同时引入 Dom4j 和 Xstream,在 XMl 复杂情况下,可以考虑使用 Dom4j 获取出感兴趣的部分。
然后抽象出合适的业务实体,使用 Xstream 进行序列化, 进行系统逻辑后续处理。
浅谈 Java 主流开源类库解析 XML的更多相关文章
- Java-XML解析第一篇主流开源类库解析XML
1.流行的XML解析框架 1>底层解析方式:存在编码复杂性.难扩展.难复用.....想了解底层解析方式请参考:浅谈 Java XML 底层解析方式 2>Dom4j:基于 JAXP 解析方式 ...
- !! 浅谈Java学习方法和后期面试技巧
浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...
- 浅谈Java回收对象的标记和对象的二次标记过程_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 一.对象的标记 1.什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的 ...
- Atitit java onvif 开源类库 getProfiles getStreamUri
Atitit java onvif 开源类库 getProfiles getStreamUri 1. ONVIF Java Library by Milgo1 1.1. https://github. ...
- 浅谈Java中set.map.List的区别
就学习经验,浅谈Java中的Set,List,Map的区别,对JAVA的集合的理解是想对于数组: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),JAVA集合可以存储和操 ...
- Java基础学习总结(29)——浅谈Java中的Set、List、Map的区别
就学习经验,浅谈Java中的Set,List,Map的区别,对JAVA的集合的理解是想对于数组: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),JAVA集合可以存储和操 ...
- 浅谈Java语言环境搭建-JDK8
title: 浅谈Java语言环境搭建-JDK8 blog: CSDN data: Java学习路线及视频 1.What's the JDK,JRE JDK(Java Development Kit ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
随机推荐
- net.sz.framework 框架 轻松搭建数据服务中心----读写分离数据一致性,滑动缓存
前言 前文讲述了net.sz.framework 框架的基础实现功能,本文主讲 net.sz.framework.db 和 net.sz.framework.szthread; net.sz.fram ...
- JavaScript 简易版 自动轮播 手动轮播 菜鸟交流
本人刚刚接触前端,许多知识还不了解,以前经常到博客园查询自己需要的东西,现在也终于反客为主了.作为新手,所展示的东西也是浅显易懂,希望同是新手的伙伴们共同交流.共同进步,若是成功捕获一位大大,也请您赐 ...
- 基于MVC和Bootstrap的权限框架解决方案 一.搭建HTML
因为某些原因,因为需要,最新要做一套客户管理系统,但是不满足于仅有的框架. 看了很多大牛写的框架,强大是强大,代码也太TM多了,乱七八糟话不多说,开始吧 随便在网上找到一套好看的HTML,看起来还不错 ...
- Java NIO之Buffers
一.前言 在笔者打算学习Netty框架时,发现很有必要先学习NIO,因此便有了本博文,首先介绍的是NIO中的缓冲. 二.缓冲 2.1 层次结构图 除了布尔类型外,其他基本类型都有相对应的缓冲区类,其继 ...
- jquery-ul-li实现分页功能 转载仅供交流
js文件代码: (function($){ $.fn.Pages = function(options){ var opts = $.extend({},$.fn.Pages.defaults, op ...
- html 压缩工具 html-minifier
https://github.com/kangax/html-minifier#options-quick-reference 1.参数列表 option Description Default re ...
- 记录一个NPE问题
昨天在做公司项目时,我在一处地方加了一个逻辑校验,之后测了下发现在方法调用深处有一处NPE,来源于另一个同事的代码. 其实NPE本应该是个Java编程中老掉牙的问题,但我觉得这一处错误还是比较典型的, ...
- Java程序i学习中各阶段的建议
第一部分:对于尚未做过Java工作的同学,包括一些在校生以及刚准备转行Java的同学. 一.Java基础 首先去找一个Java的基础教程学一下,这里可以推荐一个地址,或者你也可以参照这个地址上去找相应 ...
- SQL SERVER 变量的使用和样例
定义和使用局部变量:说明: 局部变量是用户可自定义的变量. 作用范围仅在程序内部. 局部变量的名称是用户自定义的,命名的局部变量名要符合SQL Server 2000标识符命名规则=>以@开 在 ...
- 蓝桥杯-平方怪圈-java
/* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2016, 广州科技贸易职业学院信息工程系学生 * All rights reserved. * 文件名称: ...