当前位置: 首页 > article >正文

Java解析XML文件--实现读取/导入、写入/导出功能

目录

  • 需求分析
  • 有点复杂
  • 实现思路
  • XML知识点
  • XML解析方式
  • SAX解析方式
  • DOM解析方式
  • JDOM解析方式
  • DOM4J解析方式
  • JAXB知识点
  • 一、JAXB概述 
  • 二、序列化
  • 三、反序列化
  • 四、JAXB工具类
  • 五、核心注解介绍

需求分析

        昨天客户给了一个XML文件,要求项目中支持读取和写入该格式的XML文件。其实之前项目已经支持一套XML的内容解析,现在相当于项目中再新增加一套XML模板。想想也不复杂,已经有一个一,再造一个一,还好吧。(因为之前的XML代码不是我写得)

有点复杂

        说干就干吧,于是打开客户给得XML文档,先打开看看总共有多少行内容。

        划~划~……31787

        这文档内容看着很多,仔细看看,还是有迹可循,于是着手慢慢干吧。(关键也没别人干) 

实现思路

        说说我是怎么做得。一开始时我是想写个解析XML的工具类直接读取就完事了,后来发现数据读取之后,不能作为Java对象去处理也是不行。于是动手写JavaBean(与XML结构匹配的实体类),写啊写啊,就写了上百个JavaBean。

        本文就不具体呈现每个JavaBean了。主要说说如何实现Java与XML的解析过程。

XML知识点

XML解析方式

SAX解析方式

SAX(simple API for XML)是一种XML解析的替代方法。相比于DOM,SAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析。 其优缺点分别为:
优点: 解析可以立即开始,速度快,没有内存压力
缺点: 不能对节点做修改

DOM解析方式

DOM(Document Object Model)文档对象模型是JAXP(Java API for XML Program)的一部分。Java DOM解析器负责解析XML文件并创建相应的DOM对象,这些DOM对象以树结构链接在一起。解析器将整个XML结构读入内存。其优缺点分别为:
优点:把xml文件在内存中构造树形结构,可以遍历和修改节点
缺点:如果文件比较大,内存有压力,解析的时间会比较长

JDOM解析方式

JDOM(Java-based Document Object Model)的目的是成为java特定文档模型,它简化与XML的交互并且比使用DOM实现更快。由于第一个Java特定模型,JDOM一直得到大力推广和促进。正在考虑通过“Java规范请求JSR-102”将它最终用作“Java标注扩展”。

优点:  使用具体类而不是接口,简化了DOM的API;大量使用了Java集合(Collections)类,方便了Java开发人员。

缺点:没有较好的灵活性;性能较差。

DOM4J解析方式

DOM4J(Document Object Model for Java)代表了完全独立的开发结果,但最初,它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能。包括集成的XPath支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。它提供了构建文档表示的选项,它通过DOM4J API和标准DOM接口具有并行访问功能 。

优点:大量使用了Java集合类,方便Java开发人员,同时提供一些提供性能的替代方法;性能优异、灵活性好、功能强大和易用的特点。

缺点:大量使用了接口,API较为复杂。

 当然,我选DOM4J的解析方式。

JAXB知识点

一、JAXB概述 

        JAXB的全称是Java Architecture for XML Binding,是一项可以通过XML产生Java对象,也可以通过Java对象产生XML的技术。JDK中关于JAXB部分有几个比较重要的接口或类,如:

Ø  JAXBContext:它是程序的入口类,提供了XML/Java绑定的操作,包括marshal、unmarshal等。

Ø  Marshaller:它负责把Java对象序列化为对应的XML。

Ø  Unmarshaller:它负责把XML反序列化为对应的Java对象。

二、序列化

        进行序列化的基本步骤如下:

//1、获取一个基于某个class的JAXBContext,即JAXB上下文
JAXBContext jaxbContext = JAXBContext.newInstance(obj.getClass());
//2、利用JAXBContext对象创建对象的Marshaller实例。
Marshaller marshaller = jaxbContext.createMarshaller();
//3、设置一些序列化时需要的指定的配置
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
StringWriter writer = new StringWriter();
//4、将对象进行序列化
marshaller.marshal(obj, writer);

1、  创建一个JAXB上下文对象。

2、  利用JAXB上下文对象创建对应的Marshaller对象。

3、  指定序列化时的配置参数,具体可以设置的参数和对应的参数的含义可以参考API文档。

4、  最后一步是将对应的对象序列化到一个Writer、OutputStream、File等输出对象中,具体可以参考Marshaller接口的API文档。

        使用JAXB进行对象的序列化时对应的对象类型必须是javax.xml.bind.JAXBElement类型,或者是使用了javax.xml.bind.annotation.XmlRootElement注解标注的类型。XmlRootElement用于标注在class上面,表示把一个class映射为一个XML Element对象。与之相配合使用的注解通常还有XmlElement和XmlAttribute。XmlElement注解用于标注在class的属性上,用于把一个class的属性映射为一个XML Element对象。XmlAttribute注解用于标注在class的属性上,用于把一个class的属性映射为其class对应的XML Element上的一个属性。默认情况下,当我们的一个属性没有使用XmlElement标注时也会被序列化为Xml元素的一个子元素,如果我们不希望Java对象中的某个属性被序列化则可以在对应的属性或对应的get方法上采用XMLTransient进行标注。

        示例代码如下:

Person类
@XmlRootElement
public class Person {private Integer id;private String name;private Integer age;private Address address;@XmlAttribute(name = "id")public Integer getId() {returnid;}public void setId(Integer id) {this.id = id;}@XmlAttributepublic String getName() {returnname;}public void setName(String name) {this.name = name;}@XmlElementpublic Integer getAge() {returnage;}public void setAge(Integer age) {this.age = age;}@XmlElementpublic Address getAddress() {returnaddress;}public void setAddress(Address address) {this.address = address;}}Address类@XmlRootElement
public class Address {private Integer id;private String province;private String city;private String area;private String other;@XmlAttribute(name="id")public Integer getId() {returnid;}public void setId(Integer id) {this.id = id;}@XmlElementpublic String getProvince() {returnprovince;}public void setProvince(String province) {this.province = province;}@XmlElementpublic String getCity() {returncity;}public void setCity(String city) {this.city = city;}@XmlElementpublic String getArea() {returnarea;}public void setArea(String area) {this.area = area;}@XmlElementpublic String getOther() {returnother;}public void setOther(String other) {this.other = other;}}
/*** 测试方法*/
@Test
public void testMarshal() throws JAXBException {JAXBContext context = JAXBContext.newInstance(Person.class);Marshaller marshaller = context.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);StringWriter writer = new StringWriter();Person person = new Person();person.setId(1);person.setName("张三");person.setAge(30);Address address = new Address();address.setId(1);address.setProvince("广东省");address.setCity("深圳市");address.setArea("南山区");address.setOther("其它");person.setAddress(address);marshaller.marshal(person, writer);System.out.println(writer.toString());
}

输出结果如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person id="1" name="张三">
    <address id="1">
        <area>南山区</area>
        <city>深圳市</city>
        <other>其它</other>
        <province>广东省</province>
    </address>
    <age>30</age>
</person>

三、反序列化

进行反序列化的基本步骤如下:

//1、创建一个指定class的JAXB上下文对象
JAXBContext context = JAXBContext.newInstance(Person.class);
//2、通过JAXBContext对象创建对应的Unmarshaller对象。
Unmarshaller unmarshaller = context.createUnmarshaller();
File file = new File("D:\\person.xml");
//3、调用Unmarshaller对象的unmarshal方法进行反序列化,接收的参数可以是一个InputStream、Reader、File等
Person person = (Person) unmarshaller.unmarshal(file);

        Unmarshaller对象在提供了一系列的unmarshal重载方法,对应的参数类型可以是File、InputStream、Reader等,具体的可以查看对应的API文档。

四、JAXB工具类

         除了使用JAXBContext来创建Marshaller和Unmarshaller对象来实现Java对象和XML之间的互转外,Java还为我们提供了一个工具类JAXB。JAXB工具类提供了一系列的静态方法来简化了Java对象和XML之间的互转,只需要简单的一行代码即可搞定。

@Test
public void testMarshal1() {Person person = new Person();person.setId(1);person.setName("张三");person.setAge(30);Address address = new Address();address.setId(1);address.setProvince("广东省");address.setCity("深圳市");address.setArea("南山区");address.setOther("其它");person.setAddress(address);JAXB.marshal(person, System.out);
}@Test
public void testUnmarshal1() {File xml = new File("D:\\person.xml");Person person = JAXB.unmarshal(xml, Person.class);System.out.println(person);
}

五、核心注解介绍

XmlRootElement:用于标注在根节点对应的Java类上。

XmlElement:用于标注Java类的属性或get/set方法上,表示对应的属性或get/set方法需要与
XML的某一个元素映射。

XmlAttribute:用于映射XML元素属性的,默认的属性名称与Java类的属性名称一致,可以通过name属性指定属性名称。

XmlValue:是用于映射直接应用XML元素的文本内容的。

XmlType:用于定义在类上,表示该类对应于XML的一个复杂类型对象。

XmlAccessorOrder:也是指定Java对象生成的XML元素/属性的顺序的。

XmlTransient:用于在进行Java对象和XML相互转换时定义需要忽略的Java属性。

XmlAccessorType:指定Java对象和XML相互转换时Java对象属性访问方式,即哪些属性会与XML进行映射。

XmlElementWrapper:用于进行集合类型的属性映射时,在XML元素的外层再多包一层元素。

XmlJavaTypeAdapter:可以用于在进行Java对象和XML相互转换时做一些适配工作。

XmlJavaTypeAdapters:只能标注在package上,是用于定义多个XmlJavaTypeAdapters的。

详见:https: //blog.csdn.net/qushaming/article/details/83658647

http://www.lryc.cn/news/2417345.html

相关文章:

  • 资源网站mark
  • 手機 Cell ID 與定位
  • 社招网站推荐
  • 【入门】Java使用htmlutil进行数据爬取 {一篇文章让你了解爬虫技术栈}
  • OpenWrt开发必备软件模块——进程管理服务procd
  • 信号状态关_HINET工业智能网关三种联网模式操作说明
  • wpf中EventHandler的使用
  • 2023-05-31【05】Windows 10安装Oracle10g客户端
  • U盘文件系统FAT32、exFAT、NTFS之间有什么区别?
  • 解决 Linux 桌面问题思路分享
  • 自动化无人值守网络装机(PXE网络装机)
  • SERVER-U搭建
  • Android SDK下载安装及配置
  • [嵌入式系统-72]:ARM芯片选型基础
  • Windows Server 2008 R2安装IIS
  • 我的Delphi7里程碑(认识Delphi7的基本类型)
  • 2024年如何解决企业IM即时通讯的发展瓶颈?企业应如何选择适合自己的企业聊天软件?
  • Oracle优化器介绍(RBO/CBO)和用法
  • 对ArrayList集合中的元素进行排序
  • java 乱写4 异常常常常
  • (linux)中文显示乱码问题解决方法(编码查看及转换)
  • 电脑常识——host文件修改(屏蔽网站或解开屏蔽)
  • Java 8 的 Nashorn 脚本引擎教程
  • 串行通信接口详细描述
  • APUE学习之socket网络编程
  • [JavaScript]如何将www.xxx.com变为com.xxx.www
  • Serialization全解析
  • 手把手教你ubuntu下移植MJPG-streamer
  • 软件的三层架构
  • php pathinfo 什么用,在php中pathinfo函数起什么作用呢?