您的位置:首页 > 编程语言 > Java开发

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 dom