a) DOM:DOM 解析器把 XML 文档转化为一个包含其内容的树,并能够对树进行遍历。用 DOM 解析模型的长处是编程容易,能够很容易的添加和修改树中的元素。然而
由于使用 DOM 解析器的时候需要处理整个 XML 文档,所以对性能和内存的需要比较高,尤其是碰到很大的 XML 文档的时候。
b)SAX:SAX 解析器采用了基于事件的模型(在解析 XML 文档的时候能够触发一系列的事件,当发现给定的tag的时候,他能够激活一个回调方法,告诉该方法定制的标
签已找到)。因为他让程序员自己来决定所要处理的tag,所以当只需要处理文档中所包含的部分数据时,SAX 有良好的表现。但用 SAX 解析器的时候编码工作会比较困
难,而且很难同时访问同一个文档中的多处不同数据。
c)JDOM:JDOM的目的是成为 Java 特定文档模型,他简化和 XML 的交互并且比使用 DOM 实现更快。
d)DOM4J:DOM4J 是很优秀的Java XML API,具备性能优异、功能强大和极端易用使用的特点,同时他也是个开放源代码的软件。
1dom解析
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.1dom组成
对于XML应用开发来说,DOM就是一个对象化的XML数据接口,一个与语言无关、与平台无关的标准接口规范。它定义了HTML文档和XML文档的逻辑结构,给出了一种
访问和处理HTML文档和XML文档的方法。利用DOM,程序开发人员可以动态地创建文档,遍历文档结构,添加、修改、删除文档内容,改变文档的显示方式等等。可以这样
说,文档代表的是数据,而DOM则代表了如何去处理这些数据。无论是在浏览器里还是在浏览器外,无论是在服务器上还是在客户端,只要有用到XML的地方,就会碰到对
DOM的应用。
作为W3C 的标准接口规范, 目前, DOM 由三部分组成, 包括: 核心(core )、HTML和XML。核心部分是结构化文档比较底层对象的集合,这一部分所定义的对象已经完全
可以表达出任何HTML和XML文档中的数据了。HTML接口和XML接口两部分则是专为操作具体的HTML文档和XML文档所提供的高级接口,使对这两类文件的操作更加方便。
1.2dom模型结构
1.3dom的四大接口
在DOM接口规范中,有四个基本的接口:Document,Node,NodeList以及NamedNodeMap。在这四个基本接口中,Document接口是对文档进行操作的入口,它是从
Node接口继承过来的。Node接口是其他大多数接口的父类,像Document,Element,Attribute,Text,Comment等接口都是从Node接口继承过来的。NodeList接口是一个节点
的集合,它包含了某个节点中的所有子节点。NamedNodeMap接口也是一个节点的集合,通过该接口,可以建立节点名和节点之间的一一映射关系,从而利用节点名可以直接
访问特定的节点。
a)Document接口
由于元素、文本节点、注释、处理指令等都不能脱离文档的上下文关系而独立存在,所以在Document接口提供了创建其他节点对象的方法,通过该方法创建的节点对象都有一
个ownerDocument属性,用来表明当前节点是由谁所创建的以及节点同Document之间的联系。
b)Node接口
Node接口在整个DOM树中具有举足轻重的地位,DOM接口中有很大一部分接口是从Node接口继承过来的,例如,Element、Attr、CDATASection等接口,都是从Node继承过来
的。在DOM树中,Node接口代表了树中的一个节点。
例:(利用DOM解析如下XML) <?xml version="1.0"?> <PEOPLE> <PERSON PERSONID="E01"> <NAME>ivan</NAME> <ADDRESS>dalian</ADDRESS> <EMAIL>ivan@163.com</EMAIL> </PERSON> <PERSON PERSONID="E02"> <NAME>lisa</NAME> <ADDRESS>beijing</ADDRESS> <EMAIL>lisa@163.com</EMAIL> </PERSON> <PERSON PERSONID="E03"> <NAME>grace</NAME> <ADDRESS>shanghai</ADDRESS> <EMAIL>grace@163.com</EMAIL> </PERSON> </PEOPLE>Java代码如下:
public static void main(String[] args) throws Exception { // step 1: 获得dom解析器工厂 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // step 2:获得具体的dom解析器 DocumentBuilder db = dbf.newDocumentBuilder(); // step3: 解析一个xml文档,获得Document对象(根结点) Document document = db.parse(new File("persons.xml")); NodeList list = document.getElementsByTagName("PERSON"); for(int i = 0; i < list.getLength(); i++) { Element element = (Element)list.item(i); String content = element.getElementsByTagName("NAME").item(0).getFirstChild().g etNodeValue(); System.out.println("name:" + content); content = element.getElementsByTagName("ADDRESS").item(0).getFirstChild().g etNodeValue(); System.out.println("address:" + content); content = element.getElementsByTagName("EMAIL").item(0).getFirstChild().get NodeValue(); System.out.println("email:" + content); } }
例:xml通用的解析(递归)
public static void main(String[] args) throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File("persons.xml")); Element root = doc.getDocumentElement(); parseElement(root); } private static void parseElement(Element element) { String tagName = element.getNodeName(); NodeList children = element.getChildNodes(); System.out.print("<" + tagName); //element元素的所有属性所构成的NamedNodeMap对象,需要对其进行判断 NamedNodeMap map = element.getAttributes(); //如果该元素存在属性 if(null != map) { for(int i = 0; i < map.getLength(); i++) { //获得该元素的每一个属性 Attr attr = (Attr)map.item(i); String attrName = attr.getName(); String attrValue = attr.getValue(); System.out.print(" " + attrName + "=\"" + attrValue + "\""); } } System.out.print(">"); for(int i = 0; i < children.getLength(); i++) { Node node = children.item(i); //获得结点的类型 short nodeType = node.getNodeType(); if(nodeType == Node.ELEMENT_NODE) { //是元素,继续递归 parseElement((Element)node); } else if(nodeType == Node.TEXT_NODE) { //递归出口 System.out.print(node.getNodeValue()); } else if(nodeType == Node.COMMENT_NODE) { System.out.print("<!--"); Comment comment = (Comment)node; //注释内容 String data = comment.getData(); System.out.print(data); System.out.print("-->"); } System.out.print("</" + tagName + ">"); }2sax解析
SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分
析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口.
SAX分析器在对XML文档进行分析时,触发了一系列的事件,由于事件触发本身是有时序性的,因此,SAX提供的是一种顺序访问机制,对于已经分析过的部分,不能再倒回
去重新处理。SAX之所以被叫做"简单"应用程序接口,是因为SAX分析器只做了一些简单的工作,大部分工作还要由应用程序自己去做。也就是说,SAX分析器在实现时,它只
是顺序地检查XML文档中的字节流,判断当前字节是XML语法中的哪一部分、是否符合XML语法,然后再触发相应的事件,而事件处理函数本身则要由应用程序自己来实现。同
DOM分析器相比,SAX分析器缺乏灵活性。然而,由于SAX分析器实现简单,对内存要求比较低,因此实现效率比较高,对于那些只需要访问XML文档中的数据而不对文档进
行更改的应用程序来说,SAX分析器更为合适。
2.1SAX分析器的大体构成框架
例:解析xml
public static void main(String[] args) throws Exception { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse(new File("student.xml"),new MyHandler2()); } } class MyHandler2 extends DefaultHandler { private Stack<String> stack = new Stack<String>(); private String name; private String address; private String email; @Override public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException { stack.push(qName); for(int i = 0; i < attributes.getLength(); i++) { String attrName = attributes.getQName(i); String attrValue = attributes.getValue(i); System.out.println(attrName + "=" + attrValue); } } @Override public void characters(char[] ch,int start,int length) throws SAXException { String tag = stack.peek(); if("NAME".equals(tag)){ name = new String(ch,start,length); } else if("ADDRESS".equals(tag)){ address = new String(ch,length); } else if("EMAIL".equals(tag)){ email = new String(ch,length); } } @Override public void endElement(String uri,String qName) throws SAXException { stack.pop(); //表示该元素已经解析完毕,需要从栈中弹出 if("PERSON".equals(qName)) { System.out.println("name:" + name); System.out.println("address:" + address); System.out.println("email:" + email); System.out.println(); } }3jdom解析
JDOM是一种使用 XML 的独特 Java 工具包,用于快速开发 XML 应用程序。它的设计包含 Java 语言的语法乃至语义。JDOM是一个开源项目,它基于树型结构,利用纯JAVA
的技术对XML文档实现解析、生成、序列化以及多种操作。(http://jdom.org)
JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念等),把SAX和DOM的功能有效地结合起来.JDOM是用Java语言读、写、操作
XML的新API函数。在直接、简单和高效的前提下,这些API函数被最大限度的优化。
JDOM 主要用来弥补DOM及SAX在实际应用当中的不足之处。这些不足之处主要在于SAX没有文档修改、随机访问以及输出的功能,而对于DOM来说,JAVA程序员在使用时来
用起来比较麻烦。
DOM的缺点主要是由于DOM是一个接口定义语言(IDL),它的任务是在不同语言实现中的一个最低的通用标准,并不是为JAVA特别设计的。
3.1JDOM的好处
1)在 JDOM 中,XML 元素就是 Element 的实例,XML 属性就是 Attribute 的实例,XML 文档本身就是 Document 的实例
2)JDOM 是 Java 平台专用的。只要有可能,API 都使用 Java 语言的内建String 支持,因此文本值也适用于 String 。它还可利用 Java 2 平台的类集,如 List 和Iterator
,给程序员提供了一个丰富的并且和Java 语言类似的环境。
3)没有层次性。在 JDOM 中,XML 元素就是 Element 的实例,XML 属性就是Attribute 的实例,XML文档本身就是 Document 的实例。由于在XML 中所有这些都
代表了不同的概念,因此它们总是作为自己的类型被引用,而不是作为一个含糊的“结点”。
4)类驱动。因为 JDOM 对象就是像 Document 、Element 和 Attribute 这些类的直接实例,因此创建一个新 JDOM 对象就如在 Java 语言中使用 new 操作符一样容易。它
还意味着不需要进行工厂化接口配置 -- JDOM 的使用是比较直接。
例:(创建一个xml)
public static void main(String[] args) throws Exception { Document document = new Document(); Element root = new Element("person"); document.addContent(root); Comment comment = new Comment("This is my comments"); root.addContent(comment); Element e = new Element("user"); e.setAttribute("id","1"); root.addContent(e); Element e2 = new Element("address"); Attribute attr = new Attribute("country","cn"); e2.setAttribute(attr); e.addContent(e2); e2.addContent(new Element("city").setAttribute("test1","value1") .setAttribute("test2","中文").setAttribute("test3","value3") .setText("text content")); Format format = Format.getPrettyFormat(); format.setIndent(" ");// 设置间隔 format.setEncoding("gbk");// 设置字符集 XMLOutputter out = new XMLOutputter(format); out.output(document,new FileWriter("test.xml")); }例:(读写上述创建的xml)
public static void main(String[] args) throws Exception { SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(new File("test.xml")); Element element = doc.getRootElement(); System.out.println(element.getName());// 输出根元素 Element user = element.getChild("user"); List list = user.getAttributes(); for (int i = 0; i < list.size(); i++) { // 获得该节点的所有的属性 Attribute attr = (Attribute) list.get(i); String attrName = attr.getName(); String attrValue = attr.getValue(); System.out.println(attrName + "=" + attrValue); } user.removeChild("address");// 删除address节点 XMLOutputter out = new XMLOutputter(Format.getPrettyFormat().setIndent( " ")); out.output(doc,new FileOutputStream("test2.xml")); }