阅读目录

  • 0 Dom4j XStream 简单介绍

    • Dom4j
    • XStream
  • 1 新建 Spring Boot Maven 示例工程项目
  • 2 引入依赖 Pom
  • 3 Dom4j 代码实例
    • 3.1 打开一个远程 xml
    • 3.2 创建一个 xml 文档
    • 3.3 遍历
    • 3.4 使用 xpath 获取节点
    • 3.5 保存到 文件
    • 3.6 XML 文件转文本
    • 3.7 文本转 XML 文档对象
    • 3.8 使用 XSLT 转换 XML
  • 4 XStream 代码实例
    • 4.1 不使用别名直接输出 xml
    • 4.2 使用别名直接输出 xml
    • 4.3 替换节点名称
    • 4.4 实体对象属性作为节点的属性
    • 4.5 使用注解 @XStreamAlias
    • 4.6 使用注解 @XStreamImplicit
    • 4.9 属性转换器
    • 4.10 反序列化

Xml 现在仍然占据着比较重要的地位,比如微信接口中使用了 Xml 进行消息的定义。本章重点讨论 Xml 的新建、编辑、查找、转化,可以这么理解,本章是使用了 dom4j、xstream 也是在开发者中使用最为广泛的 。 本章主要是位大家提供一个操作 Xml 的类库。

回到顶部

0 Dom4j XStream 简单介绍

一句话 Dom4j 专注于 Xml 操作的高性能库,Xstream 则专注于 对象之间的转换。

Dom4j

Dom4j 为了支持 XPath、XML Schema、基于事件处理大文档或流文档。

Dom4j 为提供构建文档表示的选项,为可通过 Dom4j-API 和标准底层 dom-API 并行访问功能。

为实现上述宏伟目标,Dom4j 使用接口和抽象基本类方法并大量使用 JDK 中 Collections 类。

所以 Dom4j 有丰富的 API,在灵活性上面 Dom4j 更占有优势,性能方面也无可挑剔。

声名在外的 Sun-JAXM,大名鼎鼎的 Hibernate 中XML 配置文件解析都使用的是 Dom4j。

XStream

XStream 为基于注解不需要其它辅助类或映射文件 的OXMapping 技术,如果你用过 hibernate 或 mybatis 之类的 ORM 框架就不难理解这里的 OXM。

XStream 可以将 JavaBean 序列化为 XML,或将 XML 反序列化为 JavaBean,使得XML序列化不再繁琐。

XStream 也可以将 JavaBean 序列化成 Json 或反序列化,使用非常方便。

没有映射文件而且底层使用 xmlpull 推模型解析 XML,高性能、低内存占用,结合简洁明了的 API,上手基本是分分钟的事情。

XStream 同时也可以定制转换类型策略并配有详细的错误诊断,能让你快速定位问题。

回到顶部

1 新建 Spring Boot Maven 示例工程项目

注意:是用来 IDEA 开发工具

  1. File > New > Project,如下图选择 Spring Initializr 然后点击 【Next】下一步
  2. 填写 GroupId(包名)、Artifact(项目名) 即可。点击 下一步
    groupId=com.fishpro
    artifactId=xmldom4j
  3. 选择依赖 Spring Web Starter 前面打钩。
  4. 项目名设置为 spring-boot-study-xmldom4j.

回到顶部

2 引入依赖 Pom

  • dom4j-1.6.1 支持 Java 1.4+
  • dom4j-2.0.2 支持 Java 5+
  • dom4j-2.1.1 支持 Java 8+

mvnrepository 只有 1.6.1 那就用1.6.1

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- https://mvnrepository.com/artifact/dom4j/dom4j --><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><!-- https://mvnrepository.com/artifact/jaxen/jaxen xpath解析的时候需要引入 jaxen包 否则会报错 java.lang.NoClassDefFoundError: org/jaxen/JaxenException--><dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version></dependency><!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream 支持xml转bean --><dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.11.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

回到顶部

3 Dom4j 代码实例

3.1 打开一个远程 xml

 /*** 解析远程 XML 文件* @return Document xml 文档* */public static Document parse(URL url) throws DocumentException{SAXReader reader = new SAXReader();Document document =reader.read(url);return document;}

3.2 创建一个 xml 文档

/*** 创建一个 xml 文档* */public static Document createDocument() {Document document = DocumentHelper.createDocument();Element root = document.addElement("root");Element author1 = root.addElement("author").addAttribute("name", "James").addAttribute("location", "UK").addText("James Strachan");Element author2 = root.addElement("author").addAttribute("name", "Bob").addAttribute("location", "US").addText("Bob McWhirter");return document;}

3.3 遍历

 System.out.println("====遍历================================");//获取根节点Element root = document.getRootElement();// 遍历根节点下的子节点for (Iterator<Element> it = root.elementIterator(); it.hasNext();) {Element element = it.next();// do somethingSystem.out.println("根节下子节点名称:"+element.getName());}// 遍历子节点 author 下的子节点for (Iterator<Element> it = root.elementIterator("feed"); it.hasNext();) {Element foo = it.next();// do somethingSystem.out.println("author节点下节点名称:"+foo.getName());}// 后去根节点的属性for (Iterator<Attribute> it = root.attributeIterator(); it.hasNext();) {Attribute attribute = it.next();// do somethingSystem.out.println("根节下子节点属性:"+attribute.getName());}

3.4 使用 xpath 获取节点

System.out.println("================================================");//使用 XPath 获取节点 获取多个节点List<Node> list = document.selectNodes("//feed/entry");for (Node node :list) {System.out.println("list node:"+node.getName());}Node node = document.selectSingleNode("//feed");System.out.println("node:"+node.getName());

3.5 保存到 文件

//写到文件里面Document document1=Dom4jUtils.createDocument();FileWriter out = new FileWriter("foo.xml");document1.write(out);out.close();

3.6 XML 文件转文本

 Document xd=DocumentHelper.parseText(text);

3.7 文本转 XML 文档对象

 String text = "<person> <name>James</name> </person>";
Document document = DocumentHelper.parseText(text);

3.8 使用 XSLT 转换 XML

/*** 使用XSLT转换XML* */public static Document styleDocument(Document document, String stylesheet) throws Exception {TransformerFactory factory = TransformerFactory.newInstance();//实例化转换器工厂 TransformerFactoryTransformer transformer = factory.newTransformer(new StreamSource(stylesheet));// 创建一个转化格式对象DocumentSource source = new DocumentSource(document); // XML 源对象DocumentResult result = new DocumentResult(); //转换结果对象transformer.transform(source, result);//转换操作Document transformedDoc = result.getDocument();//获取转换后的文档return transformedDoc;}

回到顶部

4 XStream 代码实例

4.1 不使用别名直接输出 xml

Blog.java (路径 src/main/java/com/fishpro/xmldom4j/domain/Blog.java)

public class Blog {private Author writer;private List entries = new ArrayList();public Blog(Author writer) {this.writer = writer;}public void add(Entry entry) {entries.add(entry);}public List getContent() {return entries;}
}

部分代码

Blog teamBlog = new Blog(new Author("Guilherme Silveira"));teamBlog.add(new Entry("first","My first blog entry."));teamBlog.add(new Entry("tutorial","Today we have developed a nice alias tutorial. Tell your friends! NOW!"));//1.如果不设置别名呢System.out.println(xstream.toXML(teamBlog));/** 1.不设置别名输出* <com.fishpro.xmldom4j.domain.Blog>*   <writer>*     <name>Guilherme Silveira</name>*   </writer>*   <entries>*     <com.fishpro.xmldom4j.domain.Entry>*       <title>first</title>*       <description>My first blog entry.</description>*     </com.fishpro.xmldom4j.domain.Entry>*     <com.fishpro.xmldom4j.domain.Entry>*       <title>tutorial</title>*       <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>*     </com.fishpro.xmldom4j.domain.Entry>*   </entries>* </com.fishpro.xmldom4j.domain.Blog>* */

4.2 使用别名直接输出 xml

注意使用了上面代码的 Blog teamBlog 的定义。注释部分为输出效果

 //2.设置别名xstream.alias("blog", Blog.class);xstream.alias("entry", Entry.class);System.out.println(xstream.toXML(teamBlog));/** 2.设置别名* <blog>*   <writer>*     <name>Guilherme Silveira</name>*   </writer>*   <entries>*     <entry>*       <title>first</title>*       <description>My first blog entry.</description>*     </entry>*     <entry>*       <title>tutorial</title>*       <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>*     </entry>*   </entries>* </blog>* */

4.3 替换节点名称

注意使用了上面代码的 Blog teamBlog 的定义。注释部分为输出效果

 //3.writer 节点 转为 author节点System.out.println("2.writer 节点 转为 author节点");xstream.useAttributeFor(Blog.class, "writer");xstream.aliasField("author", Blog.class, "writer");System.out.println(xstream.toXML(teamBlog));xstream.addImplicitCollection(Blog.class, "entries");System.out.println(xstream.toXML(teamBlog));/** 3. author 替代了 write* <blog>*   <author>*     <name>Guilherme Silveira</name>*   </author>*   <entry>*     <title>first</title>*     <description>My first blog entry.</description>*   </entry>*   <entry>*     <title>tutorial</title>*     <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>*   </entry>* </blog>* */

4.4 实体对象属性作为节点的属性

注意使用了上面代码的 Blog teamBlog 的定义。注释部分为输出效果

//4.writer 作为 blog 的属性System.out.println("4.作为blog的属性");xstream.useAttributeFor(Blog.class, "writer");xstream.registerConverter(new AuthorConverter());//作为blog的属性System.out.println(xstream.toXML(teamBlog));/** 4.writer 作为 blog 的属性* <blog author="Guilherme Silveira">*   <entry>*     <title>first</title>*     <description>My first blog entry.</description>*   </entry>*   <entry>*     <title>tutorial</title>*     <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>*   </entry>* </blog>* */

4.5 使用注解 @XStreamAlias

@XStreamAlias 可以应用到类似,也可以应用到实体对象 Bean 的属性名上

本示例中使用了 User 和 Address 实体,他们的关系是 User 可以拥有多个 Address

User (路径 src/main/java/com/fishpro/xmldom4j/domain/User.java)

@XStreamAlias("user")
public class User {@XStreamAlias("id")private Integer userId;@XStreamAlias("username")private String username;@XStreamImplicitprivate List<Address> addresses;public User(Integer userId,String username){this.userId=userId;this.username=username;}public User(Integer userId,String username,List<Address> addresses){this.userId=userId;this.username=username;this.addresses=addresses;}public Integer getUserId() {return userId;}public void setUserId(Integer userId) {this.userId = userId;}
}

Address (路径 src/main/java/com/fishpro/xmldom4j/domain/Address.java)

@XStreamAlias("address")
public class Address {private String street;private String zipcode;private String mobile;public Address(String street,String zipcode,String mobile){this.street=street;this.zipcode=zipcode;this.mobile=mobile;}public String getStreet() {return street;}public void setStreet(String street) {this.street = street;}public String getZipcode() {return zipcode;}public void setZipcode(String zipcode) {this.zipcode = zipcode;}public String getMobile() {return mobile;}public void setMobile(String mobile) {this.mobile = mobile;}
}
System.out.println("5.使用注解");//5.使用注解xstream.processAnnotations(User.class);User msg = new User(1, "fishpro");System.out.println(xstream.toXML(msg));/** 使用注解 @XStreamAlias("user")* <user>*   <id>1</id>*   <username>fishpro</username>* </user>* */

4.6 使用注解 @XStreamImplicit

注意使用了上面代码的 Blog teamBlog 的定义。注释部分为输出效果

//6.使用注解 子节点是列表List<Address> addressList=new ArrayList<>();addressList.add(new Address("江苏省南京市玄武大道1000号","201001","1801989098"));addressList.add(new Address("江苏省南京市玄武大道1001号","201001","1811989098"));msg = new User(1, "fishpro",addressList);System.out.println(xstream.toXML(msg));/** 6.使用注解 子节点是列表* <user>*   <id>1</id>*   <username>fishpro</username>*   <address>*     <street>江苏省南京市玄武大道1000号</street>*     <zipcode>201001</zipcode>*     <mobile>1801989098</mobile>*   </address>*   <address>*     <street>江苏省南京市玄武大道1001号</street>*     <zipcode>201001</zipcode>*     <mobile>1811989098</mobile>*   </address>* </user>* */

4.9 属性转换器

当我们遇到日期的是,可能需要转换成想要的格式,我们给 User 对象增加 created 属性

    private Calendar created = new GregorianCalendar();

那么上面的示例就会输出,注意以下多出了created节点

<user><id>1</id><username>fishpro</username><address><street>江苏省南京市玄武大道1000号</street><zipcode>201001</zipcode><mobile>1801989098</mobile></address><address><street>江苏省南京市玄武大道1001号</street><zipcode>201001</zipcode><mobile>1811989098</mobile></address><created><time>1565691626712</time><timezone>Asia/Shanghai</timezone></created>
</user>

接下来我们新建一个转换器类
SingleValueCalendarConverter (路径 src/main/java/com/fishpro/xmldom4j/util/SingleValueCalendarConverter.java)

/*** 日期转换器* */
public class SingleValueCalendarConverter implements Converter {public void marshal(Object source, HierarchicalStreamWriter writer,MarshallingContext context) {Calendar calendar = (Calendar) source;writer.setValue(String.valueOf(calendar.getTime().getTime()));}public Object unmarshal(HierarchicalStreamReader reader,UnmarshallingContext context) {GregorianCalendar calendar = new GregorianCalendar();calendar.setTime(new Date(Long.parseLong(reader.getValue())));return calendar;}public boolean canConvert(Class type) {return type.equals(GregorianCalendar.class);}
}

在运行 main 示例,如下 created 节点变化了

<user><id>1</id><username>fishpro</username><address><street>江苏省南京市玄武大道1000号</street><zipcode>201001</zipcode><mobile>1801989098</mobile></address><address><street>江苏省南京市玄武大道1001号</street><zipcode>201001</zipcode><mobile>1811989098</mobile></address><created>1565691762404</created>
</user>

4.10 反序列化

 XStream xstream = new XStream();xstream.alias("person", Person.class);//设置节点person的名称xstream.alias("phonenumber", PhoneNumber.class);Person joe = new Person("Joe", "Walnes");joe.setPhone(new PhoneNumber(123, "1234-456"));joe.setFax(new PhoneNumber(123, "9999-999"));String xml = xstream.toXML(joe);//对象转 xmlSystem.out.println(xml);/** 输出简单示例xml* <person>*   <firstname>Joe</firstname>*   <lastname>Walnes</lastname>*   <phone>*     <code>123</code>*     <number>1234-456</number>*   </phone>*   <fax>*     <code>123</code>*     <number>9999-999</number>*   </fax>* </person>* */Person newJoe = (Person)xstream.fromXML(xml);//xml 转 对象

问题:

Exception in thread "main" java.lang.NoClassDefFoundError: org/jaxen/JaxenException

需要引入

<!-- https://mvnrepository.com/artifact/jaxen/jaxen -->
<dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version>
</dependency>

参考

  • https://dom4j.github.io/
  • http://x-stream.github.io/tutorial.html

Spring Boot 使用 Dom4j XStream 操作 Xml相关推荐

  1. Spring Boot Actuator(eureka xstream deserialization RCE)

    Spring Boot Actuator(eureka xstream deserialization RCE) - 简书 (jianshu.com) 寻找目标 app="Eureka-Se ...

  2. Spring Boot + JPA +MySQL 数据操作及示例环境搭建(自动建表)

    JPA 是Java官方提供的数据持久的统一API , 是一个接口标准,并没有具体实现. JPA的实现常见的有: Hibernate TopLink (Eclipse Link) Spring Boot ...

  3. Spring Boot之jdbc数据操作06

    Spring Boot之jdbc数据操作06 JDBC 通过快速创建spring boot项目选择 mysql 和jdbc 创建一个基于web的spring boot项目 依赖为 <depend ...

  4. Spring Boot实战:数据库操作

    From: https://www.cnblogs.com/paddix/p/8178943.html 上篇文章中已经通过一个简单的HelloWorld程序讲解了Spring boot的基本原理和使用 ...

  5. spring boot ---- jpa连接和操作mysql数据库

    环境: centos6.8,jdk1.8.0_172,maven3.5.4,vim,spring boot 1.5.13,mysql-5.7.23 1.引入jpa起步依赖和mysql驱动jar包 1 ...

  6. Spring Boot + Redis 实现各种操作,写得太好了吧!

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/qq_42105629/article/details/102589319 一.Jedis,Red ...

  7. spring boot分环境导出自定义xml配置

    背景介绍: 由于新的spring boot项目需要使用老的jar包,老的jar包的配置是用xml方式配置的,而且开发development.测试test.集成off.正式production环境都会有 ...

  8. Spring boot 集成工作流flowable去掉xml配置

    工作流Flowable和Spring集成时,有一个xml是用来配置ProcessEngine的信息,xml的内容如下所示: <?xml version="1.0" encod ...

  9. Spring Boot返回的数据格式是XML 而不是JSON之原因探求的和解决

    问题: 使用 @RestController 注解的控制器类, 期望返回的数据格式是JSON ,但是实际返回的确是XML 格式的. 如下图: 发生场景: 在Spring Boot项目创建的初期是正常的 ...

最新文章

  1. 华尔街风暴的深层原因
  2. mac电脑配置java环境变量_教你在Mac系统中配置JAVA环境变量的方法
  3. GitHub发福利:30多万元资源,学生可以免费用
  4. 太原理工软件学院c语言2020,太原理工软件工程C语言实验报告 数组.doc
  5. MySQL死锁案例分:先delete,再insert,导致死锁
  6. RabbitMQ 延迟队列,消息延迟推送
  7. 微信:进一步规范财经类自媒体帐号内容发布
  8. .exe已停止工作_Windows 10累积更新KB4565503和KB4565483已发布
  9. DDS(Direct Digital Synthesizer)数字频率合成器
  10. 用Django2.1开发易班联合登录
  11. git stash暂存修改
  12. 漏斗模型-数据分析师的必备神器
  13. 垃圾小白羊leetcode刷题记录2
  14. oracle database各个版本地址
  15. 手机连上wifi不能上网
  16. Box-constrained L-BFGS 相关知识拓展
  17. 结构化思维模型的构建(多种思维参考)
  18. 制作arch linux安装u盘,制作 Arch Linux 内存系统启动盘
  19. Oracle索引、视图、序列、同义词、事务、锁机制详解
  20. 迷你计算机可玩游戏,迷你电脑小主机打游戏可还行?

热门文章

  1. 跨境电商ERP有哪些?
  2. oracle数据库dca,有关Oracle数据库
  3. asp系统转换php系统时间函数,window_Asp常用通用函数之生成时间的整数,'函数名:GetMyTimeNumber()' - phpStudy...
  4. java中的泛型(一)
  5. pythonnamedtuple定义类型_python - namedtuple和可选关键字参数的默认值
  6. 血脂测试软件,医院检查血脂一般用什么仪器
  7. 最新csdnJS逆向分析
  8. Fluent API — 流畅API(基于Java介绍)
  9. 牙齿间隙变大怎么办_牙齿缝隙大怎么办 5个方法解决牙齿缝隙大
  10. Spring源码解析 -- SpringWeb请求映射Map初始化