本文共 11169 字,大约阅读时间需要 37 分钟。
XML是一种通用的数据交换格式,它的平台无关性、语言无关性、系统无关性、给数据集成与交互带来了极大的方便。XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已。
XML的解析方式分为四种:1、DOM解析;2、SAX解析;3、JDOM解析;4、DOM4J解析。其中前两种属于基础方法,是官方提供的平台无关的解析方式,其他语言也在使用的方法;后两种属于扩展方法,它们是在基础的方法上扩展出来的,只适用于java平台。
demo中使用的xml原文:
cxx1 Bob1 stars1 85 cxx2 Bob2 stars2 85 cxx3 Bob3 stars3 85
一、DOM解析
DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口的机制也被称作随机访问机制。
DOM接口提供了一种通过分层对象模型来访问XML文档信息的方式,这些分层对象模型依据XML的文档结构形成了一棵节点树。无论XML文档中所描述的是什么类型的信息,即便是制表数据、项目列表或一个文档,利用DOM所生成的模型都是节点树的形式。也就是说,DOM强制使用树模型来访问XML文档中的信息。由于XML本质上就是一种分层结构,所以这种描述方法是相当有效的。 DOM树所提供的随机访问方式给应用程序的开发带来了很大的灵活性,它可以任意地控制整个XML文档中的内容。然而,由于DOM分析器把整个XML文档转化成DOM树放在了内存中,因此,当文档比较大或者结构比较复杂时,对内存的需求就比较高。而且,对于结构复杂的树的遍历也是一项耗时的操作。所以,DOM分析器对机器性能的要求比较高,实现效率不十分理想。不过,由于DOM分析器所采用的树结构的思想与XML文档的结构相吻合,同时鉴于随机访问所带来的方便,因此,DOM分析器还是有很广泛的使用价值的。优点:
1、形成了树结构,有助于更好的理解、掌握,且代码容易编写。
2、解析过程中,树结构保存在内存中,方便修改。
缺点:
1、由于文件是一次性读取,所以对内存的耗费比较大。
2、如果XML文件比较大,容易影响解析性能且可能会造成内存溢出。
package com.xxx.org;import org.w3c.dom.*;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;/** * @Author: xxx * Dom操作xml * @Date: 2018/5/29 20:19 */public class MyDom { //用Element方式 public static void element(NodeList list){ for (int i = 0; i
运行结果:
二、SAX解析
SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口。
优点:
1、采用事件驱动模式,对内存耗费比较小。
2、适用于只处理XML文件中的数据时。
缺点:
1、编码比较麻烦。
2、很难同时访问XML文件中的多处不同数据。
package jaxp_sax;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;/** * @Author: xxx * SAX解析DOM * 一行一行 Handler * startElement * endElement * @Date: 2018/5/29 20:03 */public class mySax { public static void main(String[] args) throws Exception { //1.或去SAXParserFactory实例 SAXParserFactory factory = SAXParserFactory.newInstance(); //2.获取SAXparser实例 SAXParser saxParser = factory.newSAXParser(); //创建Handel对象 SAXDemoHandel handel = new SAXDemoHandel(); saxParser.parse("src/resources/demo.xml", handel); }}class SAXDemoHandel extends DefaultHandler { //遍历xml文件开始标签 @Override public void startDocument() throws SAXException { super.startDocument(); System.out.println("sax解析开始"); } //遍历xml文件结束标签 @Override public void endDocument() throws SAXException { super.endDocument(); System.out.println("sax解析结束"); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); if (qName.equals("student")){ System.out.println("============开始遍历student============="); //System.out.println(attributes.getValue("rollno")); } else if (!qName.equals("student")&&!qName.equals("class")){ System.out.print("节点名称:"+qName+"----"); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if (qName.equals("student")){ System.out.println(qName+"遍历结束"); System.out.println("============结束遍历student============="); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); String value = new String(ch,start,length).trim(); if (!value.equals("")) { System.out.println(value); } }}
运行结果:
三、JDOM解析
特征:
1、仅使用具体类,而不使用接口。
2、API大量使用了Collections类。
org.jdom jdom 1.1.3
package com.xxx.MyJDOM;import org.jdom.Attribute;import org.jdom.Document;import org.jdom.Element;import org.jdom.input.SAXBuilder;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.InputStream;import java.util.List;/** * @Author: xxx * JDom解析xml * 快速开发XML应用程序。 * 是一个开源项目 * JDOM主要用来弥补DOM和SAX在实际应用当中的不足。 * @Date: 2018/5/30 11:44 */public class test { public static void main(String[] args) throws Exception { //1.创建SAXBuilder对象 SAXBuilder saxBuilder = new SAXBuilder(); //2.创建输入流 InputStream is = new FileInputStream(new File("src/test/java/resources/demo.xml")); //3.将输入流加载到build中 Document document = saxBuilder.build(is); //4.获取根节点 Element rootElement = document.getRootElement(); //5.获取子节点 Listchildren = rootElement.getChildren(); for (Element child : children) { System.out.println("通过rollno获取属性值:"+child.getAttribute("rollno")); List attributes = child.getAttributes(); //打印属性 for (Attribute attr : attributes) { System.out.println(attr.getName()+":"+attr.getValue()); } List childrenList = child.getChildren(); System.out.println("======获取子节点-start======"); for (Element o : childrenList) { System.out.println("节点名:"+o.getName()+"---"+"节点值:"+o.getValue()); } System.out.println("======获取子节点-end======"); } }}
运行结果:
4、DOM4J解析
特征:
1、JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能。
2、它使用接口和抽象基本类方法。
3、具有性能优异、灵活性好、功能强大和极端易用的特点。
4、是一个开放源码的文件
dom4j dom4j 1.6.1
package com.xxx.DOM4J;import org.dom4j.Attribute;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;import java.io.File;import java.util.Iterator;import java.util.List;/** * @Author: xxx * Dom4j解析xml * @Date: 2018/5/30 12:21 */public class App { public static void main(String[] args) throws Exception { //1.创建Reader对象 SAXReader reader = new SAXReader(); //2.加载xml Document document = reader.read(new File("src/main/java/resources/demo.xml")); //3.获取根节点 Element rootElement = document.getRootElement(); Iterator iterator = rootElement.elementIterator(); while (iterator.hasNext()){ Element stu = (Element) iterator.next(); Listattributes = stu.attributes(); System.out.println("======获取属性值======"); for (Attribute attribute : attributes) { System.out.println(attribute.getValue()); } System.out.println("======遍历子节点======"); Iterator iterator1 = stu.elementIterator(); while (iterator1.hasNext()){ Element stuChild = (Element) iterator1.next(); System.out.println("节点名:"+stuChild.getName()+"---节点值:"+stuChild.getStringValue()); } } }}
运行结果:
Final:比较总结
DOM4J性能最好,连Sun的JAXM也在用DOM4J。目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J。
JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM。虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。 SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。
既然DOM4J是比较好的选择,那么就多整点关于他的操作demo,已被不时之需。
dom4j dom4j 1.6.1 jaxen jaxen 1.1-beta-6
package com.xxx.DOM4J_2;import java.io.File;import java.io.FileOutputStream;import java.util.List;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.io.OutputFormat;import org.dom4j.io.SAXReader;import org.dom4j.io.XMLWriter;import org.junit.Test;public class Demo3 { @Test public void method1() throws Exception { // 创建解析器 SAXReader reader = new SAXReader();//这个是用来读取文件内容的 Document doc = reader.read(new File("students.xml")); //指定要读取的文件 //System.out.println(doc.asXML()); //打印出文件 } //实现对XML文件的复制 @Test public void method2() throws Exception { // 得到Document SAXReader reader = new SAXReader(); Document doc = reader.read(new File("students.xml")); // 保存Document,指定将写入的目的文件(复制功能) XMLWriter writer = new XMLWriter(new FileOutputStream("students_copy.xml")); writer.write(doc); //开始写入 } //遍历Document @Test public void method3() throws Exception { // 要遍历文档,首先要得到Document对象 SAXReader reader = new SAXReader(); Document doc = reader.read(new File("students.xml")); //获取根元素 Element root = doc.getRootElement(); //获取根元素中所有student元素 ListstuEleList = root.elements("student"); // 循环遍历所有学生元素 for(Element stuEle : stuEleList) { //获取学生元素的number String number = stuEle.attributeValue("number"); //获取学生元素名为name的子元素的文本内容 String name = stuEle.elementText("name"); //获取学生元素名为age的子元素的文本内容 String age = stuEle.elementText("age"); //获取学生元素名为sex的子元素的文本内容 String sex = stuEle.elementText("sex"); System.out.println(number + ", " + name + ", " + age + ", " + sex); } } //添加元素 @Test public void method4() throws Exception { // 得到Document SAXReader reader = new SAXReader(); Document doc = reader.read(new File("src/students.xml")); //获取root元素 Element root = doc.getRootElement(); Element stuEle = root.addElement("student"); //添加了student元素 // 给stuEle添加属性,名为number,值为1003 stuEle.addAttribute("number", "1003"); // 分别为stuEle添加名为name、age、sex的子元素,并为子元素设置文本内容 stuEle.addElement("name").setText("wangWu"); stuEle.addElement("age").setText("18"); stuEle.addElement("sex").setText("male"); // 设置保存的格式化器 1. \t,使用什么来完成缩进 2. true, 是否要添加换行 OutputFormat format = new OutputFormat("\t", true); format.setTrimText(true); //去掉空白 // 在创建Writer时,指定格式化器 XMLWriter writer = new XMLWriter(new FileOutputStream("src/students_copy.xml"), format); writer.write(doc); } //修改元素 @Test public void method5() throws Exception { // 得到Document SAXReader reader = new SAXReader(); Document doc = reader.read(new File("src/students_copy.xml")); //使用XPath找到符合条件的元素 // 查询student元素,条件是number属性的值为1003 Element stuEle = (Element) doc.selectSingleNode("//student[@number='ITCAST_1003']"); //修改stuEle的age子元素内容为81 stuEle.element("age").setText("81"); //修改stuEle的sex子元素的内容为female stuEle.element("sex").setText("female"); } //删除元素 @Test public void method6() throws Exception { // 得到Document SAXReader reader = new SAXReader(); Document doc = reader.read(new File("src/students_copy.xml")); // 查找student元素,条件是name子元素的文本内容为wangWu Element stuEle = (Element) doc.selectSingleNode("//student[name='wangWu']"); // 2. 获取父元素,使用父元素删除指定子元素 stuEle.getParent().remove(stuEle); }}
转载地址:http://xgooi.baihongyu.com/