目前java解析XML有四种方式:(SAX、DOM、JDOM、DOM4J)
第一种:SAX解析
SAX处理机制:SAX是一种基于事件驱动的API。利用SAX解析XML文档,牵涉到两个部分:解析器和事件处理器。解析器负责读取XML文档,并向事件处理器发生事件,如元素开始和元素结束事件;而事件处理器则负责对事件做出响应,对传递的XML数据进行处理。
SAX 解析器采用了基于事件的模型,它在解析 XML 文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX 对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag。特别是当开发人员只需要处理文档中所包含的部分数据时,SAX 这种扩展能力得到了更好的体现。但用 SAX 解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据。
我平常很少使用这种解析方式,根工作性质有关。
第二种:DOM解析
DOM 采用建立树形结构的方式访问 XML 文档,而 SAX 采用的事件模型。
DOM 解析器把 XML 文档转化为一个包含其内容的树,并可以对树进行遍历。用 DOM 解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用 DOM 解析器的时候需要处理整个 XML 文档,所以对性能和内存的要求比较高,尤其是遇到很大的 XML 文件的时候。由于它的遍历能力,DOM 解析器常用于 XML 文档需要频繁的改变的服务中。
DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准。DOM 是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而 DOM 被认为是基于树或基于对象的。DOM 以及广义的基于树的处理具有几个优点。首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改。它还可以在任何时候在树中上下导航,而不是像 SAX 那样是一次性的处理。DOM 使用起来也要简单得多。
DOM创建XML:
private void getDocument() { doc = DocumentHelper.createDocument(); } /** * 创建XML * @param path */ public void createXML() { this.getDocument(); Element root = doc.addElement("root");//根节点 int i = 0 ; Element base= null ; while(i < baseNodes) { //在root节点下循环创建 baseNodes 个节点 base= root.addElement("baseNodes_"+i) ; base.addAttribute("id", "base_"+i); int j = 0 ; Element child = null ; while( j < childNodes) { //在baseNodes_节点下循环创建 childNodes 个节点 child = base.addElement("childNode_"+j); child.addText("child_"+j); child.addAttribute("child_id", "cd_"+j); j ++ ; } i++ ; } this.saveXML("c://11//Adom4j"+(long) Math.round(Math.floor(Math.random() * 10000000))+".xml");//输出 } /** * 保存XML * @param path 保存路劲 */ private void saveXML(String path) { XMLWriter Wxml=null; OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); File file=new File(path); try { FileOutputStream fos = new FileOutputStream(file); Wxml = new XMLWriter(fos, format); Wxml.write(doc.getDocument()); Wxml.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
DOM读取XML
/** * 读取XML * @param path */ public void readXML(String path) { SAXReader saxReader = new SAXReader(); saxReader.setIgnoreComments(true); try { doc = saxReader.read(new File(path)); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } List docList = doc.content(); Iterator iter = docList.iterator(); Element element = null ; while(iter.hasNext()) { element = (Element)iter.next(); System.out.println("e="+element.getName()); this.parseElement(element); } } /** * 取Element内容 * @param element */ private void parseElement(Element element) { try { List attrList = element.attributes(); Iterator attrIt = attrList.iterator() ; Attribute attr = null ; while(attrIt.hasNext()) { //循环打印属性 attr = (Attribute)attrIt.next(); System.out.println(element.getName()+">>>> attrName="+attr.getName()+"----attrValue="+attr.getValue()+"--text="+element.getText()); } List eleList = element.elements(); Iterator eleiter = eleList.iterator(); Element nodeele = null ; while(eleiter.hasNext()) { nodeele = (Element)eleiter.next(); this.parseElement(nodeele); //递归解析 } }catch(Exception e) { e.printStackTrace(); } }
第三种JDOM解析 http://www.jdom.org/
JDOM利用了java语言的优秀特性,极大地简化了对XML文档的处理,相比DOM简单易用。JDOM也使用对象树来表示XML文档,JDOM使用SAXj解析器来分析XML文档,构建JDOM树。然而JOMD本身并没有提供解析器,它使用其他开发商提供的标准SAX解析器,JDOM默认通过JAXP来选择解析器,可以通过手动知道解析器的类名来设置。
JDOM创建XML
public void createXML() { doc = new Document(new Element("root")); //跟节点 int i = 0 ; Element baseNode = null ; while(i < baseNodes) { //在root节点下循环创建 baseNodes 个节点 baseNode = new Element("baseNodes_"+i); baseNode.setAttribute("id", "base_"+i); int j = 0 ; Element child = null ; while(j < childNodes) { //在baseNodes_节点下循环创建 childNodes 个节点 child = new Element("childNode_"+j); child.setAttribute("child_id", "cd_"+j); child.setText("child_"+j); baseNode.addContent(child); j++; } doc.getRootElement().addContent(baseNode); i++ ; } this.saveXML("c://11//Bjdom"+(long) Math.round(Math.floor(Math.random() * 10000000))+".xml"); //输出 } /** * 保存XML * @param path 保存路劲 */ private void saveXML(String path) { XMLOutputter domstream = new XMLOutputter(); try { domstream.output(doc, new FileOutputStream(path)); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
JDOM读取XML:
/** * 读取XML * @param path */ public void readXML(String path) { SAXBuilder saxBuilder=new SAXBuilder(); try { doc=saxBuilder.build(new File(path)); } catch (JDOMException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } Element root = doc.getRootElement(); List list = root.getChildren(); Iterator it = list.iterator(); Element ele = null ; while(it.hasNext()) { ele = (Element)it.next(); this.parseElement(ele); } } private void parseElement(Element ele) { List attrList = ele.getAttributes(); Iterator attrit = attrList.iterator(); Attribute attr = null ; while(attrit.hasNext()) { attr = (Attribute)attrit.next(); System.out.println(ele.getName()+">>> attrName="+attr.getName()+"----attrValue="+attr.getValue()+"--text="+ele.getText()); } List chlist = ele.getChildren(); Iterator ct = chlist.iterator(); Element ctele = null ; while(ct.hasNext()) { //递归读取 ctele = (Element)ct.next(); this.parseElement(ctele); } }
第四种:DOM4J解析
dom4j与JDOM一样,也是一种用于解析XML文档的开放源代码的XML框架,dom4j也应用于java平台,dom4j API使用了java集合框架并完全支持DOM、SAX和JAXP。与JDOM不同的是,dom4j使用接口和抽象类,虽然dom4j的API相对复杂些,但它提供了比JDOM更好的灵活性。dom4j也使用SAX解析器来分析XML文档,创建dom4j树。此外dom4j也可以接收DOM格式的内容,并提供了从dom4j树到SAX事件流或W3C DOM树的输出机制。与JDOM不同,dom4j自带了一个SAX解析器Aelfred2,如果没有显示的设置SAX解析器,也没有通过系统属性org.xml.sax.driver设置解析器,dom3j将会使用JAXP来加载JAXP配置的解析器,如果创建解析器失败,那么最后才使用dom4j自带的Aelfred2解析器。
在添加灵活性、XPath 集成和对大文档处理的目标时,DOM4J 的目标与 JDOM 是一样的:针对 Java 开发者的易用性和直观操作。它还致力于成为比 JDOM 更完整的解决方案,实现在本质上处理所有 Java/XML 问题的目标。在完成该目标时,它比 JDOM 更少强调防止不正确的应用程序行为。
DOM4J创建XML
private void getDocument() { doc = DocumentHelper.createDocument(); } /** * 创建XML * @param path */ public void createXML() { this.getDocument(); Element root = doc.addElement("root");//根节点 int i = 0 ; Element base= null ; while(i < baseNodes) { //在root节点下循环创建 baseNodes 个节点 base= root.addElement("baseNodes_"+i) ; base.addAttribute("id", "base_"+i); int j = 0 ; Element child = null ; while( j < childNodes) { //在baseNodes_节点下循环创建 childNodes 个节点 child = base.addElement("childNode_"+j); child.addText("child_"+j); child.addAttribute("child_id", "cd_"+j); j ++ ; } i++ ; } this.saveXML("c://11//Adom4j"+(long) Math.round(Math.floor(Math.random() * 10000000))+".xml");//输出 } /** * 保存XML * @param path 保存路劲 */ private void saveXML(String path) { XMLWriter Wxml=null; OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); File file=new File(path); try { FileOutputStream fos = new FileOutputStream(file); Wxml = new XMLWriter(fos, format); Wxml.write(doc.getDocument()); Wxml.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
DOM4J读取XML:
/** * 读取XML * @param path */ public void readXML(String path) { SAXReader saxReader = new SAXReader(); saxReader.setIgnoreComments(true); try { doc = saxReader.read(new File(path)); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } List docList = doc.content(); Iterator iter = docList.iterator(); Element element = null ; while(iter.hasNext()) { element = (Element)iter.next(); System.out.println("e="+element.getName()); this.parseElement(element); } } /** * 取Element内容 * @param element */ private void parseElement(Element element) { try { List attrList = element.attributes(); Iterator attrIt = attrList.iterator() ; Attribute attr = null ; while(attrIt.hasNext()) { //循环打印属性 attr = (Attribute)attrIt.next(); System.out.println(element.getName()+">>>> attrName="+attr.getName()+"----attrValue="+attr.getValue()+"--text="+element.getText()); } List eleList = element.elements(); Iterator eleiter = eleList.iterator(); Element nodeele = null ; while(eleiter.hasNext()) { nodeele = (Element)eleiter.next(); this.parseElement(nodeele); //递归解析 } }catch(Exception e) { e.printStackTrace(); } }
关于这四种解析的性能问题,可参考http://www.it.com.cn/f/edu/053/27/93819.htm 这篇文章的作者已经说
或者参考我的另一篇博客:XML解析器性能测试 http://blog.csdn.net/jarvis_java/archive/2010/10/22/5959163.aspx