Java解析XML的四种方法

XML文件解析方法 

XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已。基本的解析方式有两种,一种叫SAX,另一种叫DOM。SAX是基于事件流的解析,DOM是基于XML文档树结构的解析。假设我们XML的内容和结构如下:

<?xml version="1.0" encoding="UTF-8"?>   
  1. <employees>   
  2.   <employee>   
  3.     <name>ddviplinux</name>   
  4.     <sex>m</sex>   
  5.     <age>30</age>   
  6.   </employee>   
  7. </employees>  

本文实现DOM与SAX的XML文档生成与解析。 

首先定义一个操作XML文档的接口XmlDocument 它定义了XML文档的建立与解析的接口。

  1. package com.alisoft.facepay.framework.bean;  
  2.   
  3. /** 
  4.  *  
  5.  * @author hongliang.dinghl  
  6.  * 定义XML文档建立与解析的接口 
  7.  */  
  8. public interface XmlDocument {  
  9.     /** 
  10.      * 建立XML文档  
  11.      * @param fileName 文件全路径名称 
  12.      */  
  13.     public void createXml(String fileName);   
  14.   
  15.     /** 
  16.      * 解析XML文档 
  17.      * @param fileName 文件全路径名称 
  18.      */  
  19.     public void parserXml(String fileName);  
  20. }  

1.DOM生成和解析XML文档

为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构。优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。 

(1)DOM解析XML文档所使用到的jar:dom.jar

(2)DOM解析与创建XML文档示例代码

package com.alisoft.facepay.framework.bean;  
  1.   
  2. import java.io.FileNotFoundException;  
  3. import java.io.FileOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.PrintWriter;  
  6.   
  7. import javax.xml.parsers.DocumentBuilder;  
  8. import javax.xml.parsers.DocumentBuilderFactory;  
  9. import javax.xml.parsers.ParserConfigurationException;  
  10. import javax.xml.transform.OutputKeys;  
  11. import javax.xml.transform.Transformer;  
  12. import javax.xml.transform.TransformerConfigurationException;  
  13. import javax.xml.transform.TransformerException;  
  14. import javax.xml.transform.TransformerFactory;  
  15. import javax.xml.transform.dom.DOMSource;  
  16. import javax.xml.transform.stream.StreamResult;  
  17.   
  18. import org.w3c.dom.Document;  
  19. import org.w3c.dom.Element;  
  20. import org.w3c.dom.Node;  
  21. import org.w3c.dom.NodeList;  
  22. import org.xml.sax.SAXException;  
  23.   
  24. /** 
  25.  *  
  26.  * @author hongliang.dinghl DOM生成与解析XML文档 
  27.  */  
  28. public class DomDemo implements XmlDocument {  
  29.     private Document document;  
  30.     private String fileName;  
  31.       
  32.     public void init() {  
  33.         try {  
  34.             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  35.             DocumentBuilder builder = factory.newDocumentBuilder();  
  36.             this.document = builder.newDocument();  
  37.         } catch(ParserConfigurationException  e) {  
  38.             System.out.println(e.getMessage());  
  39.         }  
  40.     }  
  41.       
  42.     //创建一个xml文件  
  43.     public void createXml(String fileName) {  
  44.         Element root = this.document.createElement("employees");  //创建一个xml文件根节点  
  45.         this.document.appendChild(root); //把根节点加到xml文档结构下面  
  46.         Element employee = this.document.createElement("employee"); //创过employee节点  
  47.         Element name = this.document.createElement("name"); //创建name节点  
  48.         name.appendChild(this.document.createTextNode("丁宏亮")); //创建一个内容,并把内容加到name节点下面  
  49.         employee.appendChild(name);  //把name加到employee下面  
  50.         Element sex = this.document.createElement("sex"); //创建军一个sex节点  
  51.         sex.appendChild(this.document.createTextNode("m")); //创建一个性别添加到性别节点下面  
  52.         employee.appendChild(sex); //把性别添加到,人员节点下面  
  53.         Element age = this.document.createElement("age");   
  54.         age.appendChild(this.document.createTextNode("30"));   
  55.         employee.appendChild(age);   
  56.         root.appendChild(employee);   
  57.         TransformerFactory tf = TransformerFactory.newInstance();   
  58.         try {   
  59.             Transformer transformer = tf.newTransformer();   
  60.             DOMSource source = new DOMSource(document);   
  61.             transformer.setOutputProperty(OutputKeys.ENCODING, "gb2312");   
  62.             transformer.setOutputProperty(OutputKeys.INDENT, "yes");   
  63.             PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));    
  64.             StreamResult result = new StreamResult(pw);   
  65.             transformer.transform(source, result);   
  66.             System.out.println("生成XML文件成功!");   
  67.         } catch (TransformerConfigurationException e) {   
  68.             System.out.println(e.getMessage());   
  69.         } catch (IllegalArgumentException e) {   
  70.             System.out.println(e.getMessage());   
  71.         } catch (FileNotFoundException e) {   
  72.             System.out.println(e.getMessage());   
  73.         } catch (TransformerException e) {   
  74.             System.out.println(e.getMessage());   
  75.         }   
  76.   
  77.     }  
  78.   
  79.     //解释一个XML文件  
  80.     public void parserXml(String fileName) {  
  81.         try {  
  82.             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();  
  83.             DocumentBuilder db = dbf.newDocumentBuilder();  
  84.             Document document = db.parse(fileName); // 读取xml文件  
  85.             NodeList employees = document.getChildNodes();  
  86.   
  87.             for (int i = 0; i < employees.getLength(); i++) {  
  88.                 Node employee = employees.item(i);  
  89.                 NodeList employeeInfo = employee.getChildNodes();  
  90.                 for (int j = 0; j < employeeInfo.getLength(); j++) {  
  91.                     Node node = employeeInfo.item(j);  
  92.                     NodeList employeeMeta = node.getChildNodes();  
  93.                     for (int k = 0; k < employeeMeta.getLength(); k++) {  
  94.                         System.out.println(employeeMeta.item(k).getNodeName()  
  95.                                 + ":" + employeeMeta.item(k).getTextContent());  
  96.                     }  
  97.                 }  
  98.             }  
  99.   
  100.             System.out.println("解析完毕");  
  101.         } catch (FileNotFoundException e) {  
  102.             System.out.println(e.getMessage());  
  103.         } catch (ParserConfigurationException e) {  
  104.             System.out.println(e.getMessage());  
  105.         } catch (SAXException e) {  
  106.             System.out.println(e.getMessage());  
  107.         } catch (IOException e) {  
  108.             System.out.println(e.getMessage());  
  109.         }  
  110.     }   
  111.   
  112. }  

2.SAX生成和解析XML文档

为解决DOM的问题,出现了SAX。SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;

(1)SAX解析XML文档所使用到的jar包:sax.jar

(2)SAX关健类的,类结构图

Java解析XML的四种方法

(3)SAX文档解释示例代码

package com.alisoft.facepay.framework.bean;  
  1.   
  2. import java.io.BufferedOutputStream;  
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.PrintStream;  
  8. import org.xml.sax.Attributes;  
  9. import org.xml.sax.ContentHandler;  
  10. import org.xml.sax.ErrorHandler;  
  11. import org.xml.sax.InputSource;  
  12. import org.xml.sax.Locator;  
  13. import org.xml.sax.SAXException;  
  14. import org.xml.sax.SAXParseException;  
  15. import org.xml.sax.XMLReader;  
  16. import org.xml.sax.helpers.XMLReaderFactory;  
  17.   
  18. public class XMLParser {  
  19.     protected PrintStream output = new PrintStream(new BufferedOutputStream(  
  20.             new FileOutputStream(java.io.FileDescriptor.out), 128), true);  
  21.     // handler error info.  
  22.     protected PrintStream error = new PrintStream(new BufferedOutputStream(  
  23.             new FileOutputStream(java.io.FileDescriptor.err), 128), true);  
  24.   
  25.     public void parserXMLFile(String fileName) throws SAXException, IOException {  
  26.         XMLReader reader = XMLReaderFactory.createXMLReader();  
  27.         reader.setContentHandler(new MyContentHandler());  
  28.         reader.setErrorHandler(new MyErrorHandler());  
  29.         InputSource source = new InputSource(new FileInputStream(new File(  
  30.                 fileName)));  
  31.         reader.parse(source);  
  32.     }  
  33.   
  34.     class MyErrorHandler implements ErrorHandler {  
  35.   
  36.         public void error(SAXParseException exception) throws SAXException {  
  37.   
  38.             error.println(exception.getMessage());  
  39.         }  
  40.   
  41.         public void fatalError(SAXParseException exception) throws SAXException {  
  42.   
  43.             error.println(exception.getMessage());  
  44.         }  
  45.   
  46.         public void warning(SAXParseException exception) throws SAXException {  
  47.             output.println(exception.getMessage());  
  48.   
  49.         }  
  50.   
  51.     }  
  52.   
  53.     class MyContentHandler implements ContentHandler {  
  54.   
  55.         private StringBuffer buffer = new StringBuffer();  
  56.         private String key;  
  57.   
  58.         public void characters(char[] ch, int start, int length)  
  59.                 throws SAXException {  
  60.             buffer.append(ch, start, length); // 添加标记中间的内容  
  61.   
  62.         }  
  63.   
  64.         public void endDocument() throws SAXException {  
  65.   
  66.         }  
  67.   
  68.         public void endElement(String uri, String localName, String name)  
  69.                 throws SAXException {  
  70.             if (key.equals(localName)) {  
  71.                 output.print(buffer); // 输出标记中间的内容  
  72.             }  
  73.             output.print("</" + localName + ">");  
  74.         }  
  75.   
  76.         public void endPrefixMapping(String prefix) throws SAXException {  
  77.         }  
  78.   
  79.         public void ignorableWhitespace(char[] ch, int start, int length)  
  80.                 throws SAXException {  
  81.         }  
  82.   
  83.         public void processingInstruction(String target, String data)  
  84.                 throws SAXException {  
  85.         }  
  86.   
  87.         public void setDocumentLocator(Locator locator) {  
  88.         }  
  89.   
  90.         public void skippedEntity(String name) throws SAXException {  
  91.         }  
  92.   
  93.         public void startDocument() throws SAXException // XML文档开始读取时调用  
  94.         {  
  95.             output.println("<xml version=\"1.0\" encoding=\"utf-8\"?>");  
  96.         }  
  97.   
  98.         public void startElement(String uri, String localName, String name,  
  99.                 Attributes atts) throws SAXException // 获取标记开始信息  
  100.         {  
  101.             // uri is identifier of namespace  
  102.             // name-->prefix:localName  
  103.   
  104.             buffer.delete(0, buffer.length());  
  105.             key = localName;  
  106.   
  107.             output.print("<" + localName);  
  108.             for (int i = 0; i < atts.getLength(); i++) {  
  109.                 String attrName = atts.getLocalName(i);  
  110.                 String attrValue = atts.getValue(i);  
  111.                 output.print(" " + attrName + "=" + attrValue);  
  112.             }  
  113.             output.print(">" + "\r");  
  114.         }  
  115.   
  116.         public void startPrefixMapping(String prefix, String uri)  
  117.                 throws SAXException {  
  118.         }  
  119.     }  
  120.   
  121.     public static void main(String[] args) throws Exception, IOException {  
  122.         XMLParser parser = new XMLParser();  
  123.         parser.parserXMLFile("D:/testSpace/testPrj/src/xmlPackage/MyXml.xml"); // 解释XML文件  
  124.     }  
  125. }  

(4)SAX生成XML文档示例代码(生成XML)
package com.alisoft.facepay.framework.bean;  
  1.   
  2. import java.io.FileOutputStream;  
  3. import java.io.StringWriter;  
  4. import javax.xml.transform.OutputKeys;  
  5. import javax.xml.transform.Result;  
  6. import javax.xml.transform.Transformer;  
  7. import javax.xml.transform.TransformerConfigurationException;  
  8. import javax.xml.transform.sax.SAXTransformerFactory;  
  9. import javax.xml.transform.sax.TransformerHandler;  
  10. import javax.xml.transform.stream.StreamResult;  
  11. import org.xml.sax.SAXException;  
  12. import org.xml.sax.helpers.AttributesImpl;  
  13.   
  14. public class XMLHandler {  
  15.     public String createXMLFile() {  
  16.         String xmlStr = null;  
  17.         try {  
  18.             Result resultXml = new StreamResult(new FileOutputStream(  
  19.                     "E://cities.xml"));  
  20.             StringWriter writerStr = new StringWriter();  
  21.             SAXTransformerFactory sff = (SAXTransformerFactory) SAXTransformerFactory  
  22.                     .newInstance();  
  23.             TransformerHandler th = sff.newTransformerHandler();  
  24.             Transformer transformer = th.getTransformer();  
  25.             transformer.setOutputProperty(OutputKeys.INDENT, "yes");  
  26.             transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");  
  27.             th.setResult(resultXml);  
  28.             th.startDocument();  
  29.             String four = "\n    ";  
  30.             String eight = "\n        ";  
  31.             AttributesImpl attr = new AttributesImpl();  
  32.             th.startElement("""""country", attr);  
  33.             th.characters(four.toCharArray(), 0, four.length());  
  34.   
  35.             th.startElement("""""china", attr);  
  36.   
  37.             th.characters(eight.toCharArray(), 0, eight.length());  
  38.   
  39.             th.startElement("""""city", attr);  
  40.             String bj = "Beijing";  
  41.             th.characters(bj.toCharArray(), 0, bj.length());  
  42.             th.endElement("""""city");  
  43.   
  44.             th.characters(eight.toCharArray(), 0, eight.length());  
  45.   
  46.             th.startElement("""""city", attr);  
  47.             String sh = "Shanghai";  
  48.             th.characters(sh.toCharArray(), 0, sh.length());  
  49.             th.endElement("""""city");  
  50.   
  51.             th.characters(four.toCharArray(), 0, four.length());  
  52.   
  53.             th.endElement("""""china");  
  54.             th.endElement("""""country");  
  55.             th.endDocument();  
  56.             xmlStr = writerStr.getBuffer().toString();  
  57.         } catch (TransformerConfigurationException e) {  
  58.             e.printStackTrace();  
  59.         } catch (SAXException e) {  
  60.             e.printStackTrace();  
  61.         } catch (Exception e) {  
  62.             e.printStackTrace();  
  63.         }  
  64.         return xmlStr;  
  65.     }  
  66.   
  67.     public static void main(String args[]) {  
  68.         XMLHandler xh = new XMLHandler();  
  69.         xh.createXMLFile();  
  70.     }  
  71. }  

生成的XML文档:
 
 <?xml version="1.0" encoding="UTF-8" ?>  
  1. <country>  
  2.     <china>  
  3.         <city>Beijing</city>  
  4.         <city>Shanghai</city>  
  5.     </china>  
  6. </country>  

3.DOM4J生成和解析XML文档

DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的JAXM 也在用 DOM4J。

(1)Dom4j解析XML文档所使用到的jar包:dom4j.jar

(2)Dom4j文档解释示例代码

package com.alisoft.facepay.framework.bean;  
  1.   
  2. import java.io.File;  
  3. import java.io.FileWriter;  
  4. import java.io.IOException;  
  5. import java.io.Writer;  
  6. import java.util.Iterator;  
  7.   
  8. import org.dom4j.Document;  
  9. import org.dom4j.DocumentException;  
  10. import org.dom4j.DocumentHelper;  
  11. import org.dom4j.Element;  
  12. import org.dom4j.io.SAXReader;  
  13. import org.dom4j.io.XMLWriter;  
  14.   
  15. /** 
  16.  *  
  17.  * @author hongliang.dinghl Dom4j 生成XML文档与解析XML文档 
  18.  */  
  19. public class Dom4jDemo implements XmlDocument {  
  20.   
  21.     // Dom4j创建Xml文档  
  22.     public void createXml(String fileName) {  
  23.         Document document = DocumentHelper.createDocument(); // 创建一个文档对象  
  24.         Element employees = document.addElement("employees"); // 在根节点添加元素  
  25.         Element employee = employees.addElement("employee"); // 在employees下添加子节点  
  26.         Element name = employee.addElement("name"); // 在employee下添加子节点  
  27.         name.setText("ddvip"); // 给name节点添加内容  
  28.         Element sex = employee.addElement("sex");  
  29.         sex.setText("m");  
  30.         Element age = employee.addElement("age");  
  31.         age.setText("29");  
  32.         try {  
  33.             Writer fileWriter = new FileWriter(fileName);  
  34.             XMLWriter xmlWriter = new XMLWriter(fileWriter);  
  35.             xmlWriter.write(document);  
  36.             xmlWriter.close();  
  37.         } catch (IOException e) {  
  38.   
  39.             System.out.println(e.getMessage());  
  40.         }  
  41.   
  42.     }  
  43.   
  44.     // Dom4j解释Xml文档  
  45.     public void parserXml(String fileName) {  
  46.         File inputXml = new File(fileName);  
  47.         SAXReader saxReader = new SAXReader();  
  48.         try {  
  49.             Document document = saxReader.read(inputXml);  
  50.             Element employees = document.getRootElement();  
  51.             for (Iterator i = employees.elementIterator(); i.hasNext();) {  
  52.                 Element employee = (Element) i.next();  
  53.                 for (Iterator j = employee.elementIterator(); j.hasNext();) { // 遍例节点  
  54.                     Element node = (Element) j.next();  
  55.                     System.out.println(node.getName() + ":" + node.getText());  
  56.                 }  
  57.   
  58.             }  
  59.         } catch (DocumentException e) {  
  60.             System.out.println(e.getMessage());  
  61.         }  
  62.         System.out.println("dom4j parserXml");  
  63.     }  
  64. }  

4.JDOM生成和解析XML

为减少DOM、SAX的编码量,出现了JDOM;优点:20-80原则,极大减少了代码量。使用场合:要实现的功能简单,如解析、创建等,但在底层,JDOM还是使用SAX(最常用)、DOM、Xanan文档。

(1)JDOM解析XML文档所使用到的jar包jdom.jar
(2)JDOM文档解释示例代码

  1. package com.alisoft.facepay.framework.bean;  
  2.   
  3. import java.io.FileNotFoundException;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.util.List;  
  7.   
  8. import org.jdom.Document;  
  9. import org.jdom.Element;  
  10. import org.jdom.JDOMException;  
  11. import org.jdom.input.SAXBuilder;  
  12. import org.jdom.output.XMLOutputter;  
  13.   
  14. /** 
  15.  *  
  16.  * @author hongliang.dinghl JDOM 生成与解析XML文档 
  17.  *  
  18.  */  
  19. public class JDomDemo implements XmlDocument {  
  20.   
  21.     public void createXml(String fileName) {  
  22.         Document document;  
  23.         Element root;  
  24.         root = new Element("employees");  
  25.         document = new Document(root);  
  26.         Element employee = new Element("employee");  
  27.         root.addContent(employee);  
  28.         Element name = new Element("name");  
  29.         name.setText("ddvip");  
  30.         employee.addContent(name);  
  31.         Element sex = new Element("sex");  
  32.         sex.setText("m");  
  33.         employee.addContent(sex);  
  34.         Element age = new Element("age");  
  35.         age.setText("23");  
  36.         employee.addContent(age);  
  37.         XMLOutputter XMLOut = new XMLOutputter();  
  38.         try {  
  39.             XMLOut.output(document, new FileOutputStream(fileName));  
  40.         } catch (FileNotFoundException e) {  
  41.             e.printStackTrace();  
  42.         } catch (IOException e) {  
  43.             e.printStackTrace();  
  44.         }  
  45.     }  
  46.   
  47.     public void parserXml(String fileName) {  
  48.         SAXBuilder builder = new SAXBuilder(false);  
  49.         try {  
  50.             Document document = builder.build(fileName);  
  51.             Element employees = document.getRootElement();  
  52.             List employeeList = employees.getChildren();  
  53.             // 获取employee节点  
  54.             for (int i = 0; i < employeeList.size(); i++) {  
  55.                 Element employee = (Element) employeeList.get(i);  
  56.                 List employeeInfo = employee.getChildren();  
  57.                 // 获取employee节点下面的所有子节点  
  58.                 for(int j = 0; j < employeeInfo.size(); j++) {  
  59.                     Element info = (Element)employeeInfo.get(j);  
  60.                     System.out.println(info.getName() + ":" + info.getValue());  
  61.                 }  
  62.             }  
  63.         } catch (JDOMException  e) {  
  64.             System.out.println(e.getMessage());  
  65.         } catch (IOException e) {  
  66.             System.out.println(e.getMessage());  
  67.         }  
  68.     }  

比较

1)DOM4J性能最好,连Sun的JAXM也在用DOM4J.目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J.

2)JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM.虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。

3)SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。

 

转载于:https://my.oschina.net/u/242764/blog/482685