XML解析——Java中XML的四种解析方式
2017-10-17 21:13
459 查看
1.概念
XML是一种通用的数据交换格式,它的平台无关性、语言无关性、系统无关性、给数据集成与交互带来了极大的方便。XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已。XML的解析方式分为四种:1、DOM解析;2、SAX解析;3、JDOM解析;4、DOM4J解析。其中前两种属于基础方法,是官方提供的平台无关的解析方式;后两种属于扩展方法,它们是在基础的方法上扩展出来的,只适用于java平台。
针对以下XML文件,会对四种方式进行详细描述:
一、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文件比较大,容易影响解析性能且可能会造成内存溢出。
二、SAX解析
SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口。
优点:
1、采用事件驱动模式,对内存耗费比较小。
2、适用于只处理XML文件中的数据时。
缺点:
1、编码比较麻烦。
2、很难同时访问XML文件中的多处不同数据。
三、JDOM解析
特征:
1、仅使用具体类,而不使用接口。
2、API大量使用了Collections类。
4、DOM4J解析
特征:
1、JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能。
2、它使用接口和抽象基本类方法。
3、具有性能优异、灵活性好、功能强大和极端易用的特点。
4、是一个开放源码的文件
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流被读入时,会有部分文档暂时隐藏在内存中)。
2.代码
添加maven依赖<!-- xml --> <!-- https://mvnrepository.com/artifact/dom4j/dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> <!-- xml -->
1.一般xml文件解析
/** * dom解析xml文件 * @param filePath */ public static void parseXml(String filePath){ //创建SAXReader对象 SAXReader reader = new SAXReader(); try { //读取文件 转换成Document Document document = reader.read(new File(filePath)); //获取根节点元素对象 Element root = document.getRootElement(); long s = System.currentTimeMillis(); getChildNodes(root); long e = System.currentTimeMillis(); System.out.println(root.getName() + "节点元素遍历结束,耗时共:" + (e - s) + " ms"); } catch (DocumentException e) { e.printStackTrace(); } } /** * 遍历节点下的所有子节点和属性 * @param ele 元素节点 */ private static void getChildNodes(Element ele){ String eleName = ele.getName(); System.out.println("开始遍历当前:" + eleName + "节点元素"); List<Attribute> attributes = ele.attributes(); for(Attribute attr : attributes){ System.out.println("name=" + attr.getName() + ",value=" + attr.getValue()); } //同时迭代当前节点下面的所有子节点 //使用递归 Iterator<Element> iterator = ele.elementIterator(); if(!iterator.hasNext()){ String text = ele.getTextTrim(); System.out.println("text=" + text); } while(iterator.hasNext()){ Element e = iterator.next(); getChildNodes(e); } }
2.大型xml文件解析
/** * sax解析xml配置文件 * @param filePath */ public static void parseHandler(String filePath){ //创建SAXReader对象 SAXReader reader = new SAXReader(); reader.setDefaultHandler(new ElementHandler(){ @Override public void onStart(ElementPath elementPath) { } @Override public void onEnd(ElementPath elementPath) { //获得当前节点 Element e = elementPath.getCurrent(); System.out.println(e.getName()); //记得从内存中移去 e.detach(); } }); try { reader.read(new BufferedInputStream(new FileInputStream(new File(filePath)))); } catch (DocumentException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } }
3.xml写入
public static void writeXml(String filePath, Document doc){ // 设置XML文档格式 OutputFormat outputFormat = OutputFormat.createPrettyPrint(); // 设置XML编码方式,即是用指定的编码方式保存XML文档到字符串(String),这里也可以指定为GBK或是ISO8859-1 outputFormat.setEncoding("UTF-8"); //是否生产xml头 outputFormat.setSuppressDeclaration(true); //设置是否缩进 outputFormat.setIndent(true); //以四个空格方式实现缩进 outputFormat.setIndent(" "); //设置是否换行 outputFormat.setNewlines(true); XMLWriter out = null; try{ out = new XMLWriter(new FileWriter(new File(filePath)), outputFormat); out.write(doc); }catch(IOException e){ e.printStackTrace(); } finally{ IOUtils.close(out); } }
4.性能测试
String filePath = "src/main/resources/xml/test.xml"; File file = new File(filePath); if(!file.exists()){ long s = System.currentTimeMillis(); Document doc = DocumentHelper.createDocument(); Element root = doc.addElement("root"); for(int i = 0; i <= 10000000; i++){ Element testElement = DocumentHelper.createElement("eleTest"); testElement.addAttribute("name", "testEle"); testElement.addText("this is another text"); root.add(testElement); } writeXml("src/main/resources/xml/test.xml", doc); long e = System.currentTimeMillis(); System.out.println("共耗时:" + (e - s) + "ms"); } // parseXml(filePath); parseHandler(filePath);
源码地址请移步 https://github.com/followwwind/javautils[/code]
相关文章推荐
- java解析XML的四种方式及比较
- java 解析xml的四种方式
- java 解析xml的四种方式:sax,dom,dom4j,jdom
- XML解析——Java中XML的四种解析方式
- [收藏转帖]JAVA对XML文档的四种解析方式
- JAVA解析XML的四种方式
- JAVA解析XML的四种方式
- Java Xml 的四种解析方式
- JAVA解析xml的四种方式比较
- XML解析——Java中XML的四种解析方式
- JAVA 中的四种解析XML方式
- JAVA XML 解析的四种方式
- java解析XML的四种方式-学习总结
- java中四种主流xml解析方式介绍
- JAVA 中的四种解析XML方式
- Java的四种解析XML方式
- java中四种主流xml解析方式介绍
- Java解析xml的四种方式
- JAVA 中的四种解析XML方式
- XML解析——Java中XML的四种解析方式