xml常用四种解析方式优缺点的分析×××××

      最近用得到xml的解析方式,于是就翻了翻自己的笔记同时从网上查找了资料,自己在前人的基础上总结了下,贴出来大家分享下。

首先介绍一下xml语言:

可扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。

xml的语法:

XML 分为两部分:头信息,主体信息

头信息是用来描述 XML 的一些属性,例如:版本,编码等,还可以提供 XML 显示的样式,和 dtd 编写格式。

主体信息中包含的是 XML 的具体数据。

 

头信息的语法:

<?xml version =”1.0” encoding =”GBK” ?>

其中 version 是必须加的,而 encoding 可以不写,则默认编码是 ISO8859-1 ,不支持中文。

除了这个功能外,头信息还可以进行编写格式的规定,通过 dtd 或 xsd 文件。

头信息还支持样式表的导入,允许通过样式表控制 XML 的显示。

这样可以使用 XML+ CSS 完成页面的显示,通过这种形式完成 MVC 中的 View 层:

优点:代码的安全性很高,可以很容易的替换模板。

缺点:开发成本太高

主体信息 就是由三种节点组成的,节点之间存在父与子的关系,注意的点:

  一个节点只能有一个父节点,如果没有父节点,该节点称为根节点。

  一个节点可以有多个子节点。只有元素节点可以拥有子节点。

  元素节点的标记必须成对出现,或直接结束。

特殊字符必须转义。依据字符所处的位置是否对 XML 格式造成影响来决定是否进行转义

根节点只能有一个

xml常用的四种解析方式:

1)DOM(Document Object Model)

文档对象模型分析方式。以层次结构(类似于树型)来组织节点和信息片段,映射XML文档的结构,允许获取和操作文档的任意部分。是W3C的官方标准。

优点:
1、允许应用程序对数据和结构做出更改。
2、访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。

缺点:
1、通常需要加载整个XML文档来构造层次结构,消耗资源大

2)SAX(Simple API for XML)

流模型中的推模型分析方式。通过事件驱动,每发现一个节点就引发一个事件,通过回调方法完成解析工作,解析XML文档的逻辑需要应用程序完成。

优点:
1、不需要等待所有数据都被处理,分析就能立即开始。
2、只在读取数据时检查数据,不需要保存在内存中。
3、可以在某个条件得到满足时停止解析,不必解析整个文档。
4、效率和性能较高,能解析大于系统内存的文档。

缺点:
1、需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),使用麻烦。
2、单向导航,很难同时访问同一文档的不同部分数据,不支持XPath。

3)JDOM(Java-based Document Object Model)

Java特定的文档对象模型。自身不包含解析器,使用SAX。

优点:
1、使用具体类而不是接口,简化了DOM的API。
2、大量使用了Java集合类,方便了Java开发人员。

缺点:
1、没有较好的灵活性。
2、性能较差。

4)DOM4J(Document Object Model for Java)

简单易用,采用Java集合框架,并完全支持DOM、SAX和JAXP。

优点:
1、大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。
2、支持XPath。
3、有很好的性能。

缺点:
1、大量使用了接口,API较为复杂。

下面把四种解析方式的代码贴一下,首先是DOM方式

Java代码  
  1. public class DOMXml {  
  2.       
  3.     public static void createXML(String outputPath) {  
  4.         // 建立Document对象  
  5.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  6.         // 创建DocumentBuilder  
  7.         try {  
  8.             DocumentBuilder db = factory.newDocumentBuilder();  
  9.             // 创建Document,建立新的对象  
  10.             Document doc = db.newDocument();  
  11.   
  12.             // 建立各个节点  
  13.             // 元素节点  
  14.             Element allplus = doc.createElement("allplus");  
  15.               
  16.             Element areaplus = doc.createElement("areaplus");  
  17.             Element id = doc.createElement("id");  
  18.             Element title = doc.createElement("title");  
  19.             // 创建文本节点  
  20.             Text idText = doc.createTextNode("1");  
  21.             Text titleText = doc.createTextNode("123");  
  22.   
  23.             // 配置父子节点的关系  
  24.             id.appendChild(idText);  
  25.             title.appendChild(titleText);  
  26.   
  27.             areaplus.appendChild(id);  
  28.             areaplus.appendChild(title);  
  29.   
  30.             allplus.appendChild(areaplus);  
  31.   
  32.   
  33.             // allplus是根节点,应该设置为doc的子节点  
  34.             doc.appendChild(allplus);  
  35.   
  36.             // 执行保存操作  
  37.             TransformerFactory tf = TransformerFactory.newInstance();  
  38.   
  39.             Transformer t = tf.newTransformer();  
  40.   
  41.             // 包装要保存的doc  
  42.             DOMSource source = new DOMSource(doc);  
  43.             // 设置输出流  
  44.             StreamResult sr = new StreamResult(new File(outputPath));  
  45.   
  46.             // 设置输出的属性  
  47.             t.setOutputProperty("encoding", "UTF-8");  
  48.             // t.setOutputProperty("version", "1.0");  
  49.   
  50.             // 输出  
  51.             t.transform(source, sr);  
  52.   
  53.         } catch (DOMException e) {  
  54.             // TODO Auto-generated catch block  
  55.             e.printStackTrace();  
  56.         } catch (ParserConfigurationException e) {  
  57.             // TODO Auto-generated catch block  
  58.             e.printStackTrace();  
  59.         } catch (Exception e) {  
  60.             // TODO Auto-generated catch block  
  61.             e.printStackTrace();  
  62.         }  
  63.   
  64.     }  
  65.   
  66.   
  67.     public static void parseXML(String xmlPath) {  
  68.           
  69.         /*优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能; 
  70.          * 缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间; 
  71.          * 使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。  
  72.          * 10M文档导致内存溢出   
  73.          */  
  74.           
  75.         // 建立Document对象  
  76.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  77.         // 创建DocumentBuilder  
  78.         try {  
  79.             DocumentBuilder db = factory.newDocumentBuilder();  
  80.             // 创建Document,形成树型结构  
  81.             Document doc = db.parse(new File(xmlPath));  
  82.             // 先取得所有的data  
  83.             NodeList datas = doc.getElementsByTagName("data");  
  84.             // 循环取得每个data  
  85.             for (int i = 0; i < datas.getLength(); i++) {  
  86.                 Node data = datas.item(i);  
  87.                 // 由于直接取得第一个和最后一个不符合要求,因此使用取得全部子节点的方式  
  88.                 NodeList actorInfos = data.getChildNodes();  
  89.                 for (int j = 0; j < actorInfos.getLength(); j++) {  
  90.                     Node actorInfo = actorInfos.item(j);  
  91.                     NodeList allChild = actorInfo.getChildNodes();  
  92.                     for (int t = 0; t < allChild.getLength(); t++) {  
  93.                         //判断节点  
  94.                         Node child = allChild.item(t);  
  95.                         if (child.getNodeType() == Node.ELEMENT_NODE) {  
  96.                             if (child.getNodeName().equals("id")) {  
  97.                                 //判断是否有孩子节点,然后再取值  
  98.                                 if(child.hasChildNodes()) {  
  99.                                     System.out.println(child.getFirstChild().getNodeValue());  
  100.                                 }  
  101.                             }  
  102.                             if (child.getNodeName().equals("name")) {  
  103.                                 //判断是否有孩子节点,然后再取值  
  104.                                 if(child.hasChildNodes()) {  
  105.                                     System.out.println(child.getFirstChild().getNodeValue());  
  106.                                 }  
  107.                             }  
  108.                         }  
  109.                     }  
  110.                 }  
  111.             }  
  112.         } catch (ParserConfigurationException e) {  
  113.             // TODO Auto-generated catch block  
  114.             e.printStackTrace();  
  115.         } catch (SAXException e) {  
  116.             // TODO Auto-generated catch block  
  117.             e.printStackTrace();  
  118.         } catch (IOException e) {  
  119.             // TODO Auto-generated catch block  
  120.             e.printStackTrace();  
  121.         }  
  122.   
  123.     }  
  124.   
  125.     public static void main(String[] args) {  
  126.         parseXML("D:/actor_info.xml");  
  127.         createXML("d:/fxb.xml");  
  128.     }  

 SAX解析方式

Java代码  
  1. public class SAXXml extends DefaultHandler {  
  2.     private List<Book> books = null;  
  3.     private Book book = null;  
  4.     private String preTag = null;// 作用是记录解析时的上一个节点名称  
  5.   
  6.     public List<Book> getBooks(InputStream xmlStream) throws Exception {  
  7.         SAXParserFactory factory = SAXParserFactory.newInstance();  
  8.         SAXParser parser = factory.newSAXParser();  
  9.         SAXXml handler = new SAXXml();  
  10.         parser.parse(xmlStream, handler);  
  11.         return handler.getBooks();  
  12.     }  
  13.   
  14.     public List<Book> getBooks() {  
  15.         return books;  
  16.     }  
  17.   
  18.     @Override  
  19.     public void startDocument() throws SAXException {  
  20.         books = new ArrayList<Book>();  
  21.     }  
  22.   
  23.     @Override  
  24.     public void startElement(String uri, String localName, String qName,  
  25.             Attributes attributes) throws SAXException {  
  26.         if ("book".equals(qName)) {  
  27.             book = new Book();  
  28.             book.setId(Integer.parseInt(attributes.getValue(0)));  
  29.         }  
  30.         preTag = qName;// 将正在解析的节点名称赋给preTag  
  31.     }  
  32.   
  33.     @Override  
  34.     public void endElement(String uri, String localName, String qName)  
  35.             throws SAXException {  
  36.         if ("book".equals(qName)) {  
  37.             books.add(book);  
  38.             book = null;  
  39.         }  
  40.         preTag = null;  
  41.         /** 
  42.          * 当解析结束时置为空。这里很重要,例如,当图中画3的位置结束后,会调用这个方法 
  43.          * ,如果这里不把preTag置为null,根据startElement(....)方法,preTag的值还是book,当文档顺序读到图 
  44.          * 中标记4的位置时,会执行characters(char[] ch, int start, int 
  45.          * length)这个方法,而characters(....)方 
  46.          * 法判断preTag!=null,会执行if判断的代码,这样就会把空值赋值给book,这不是我们想要的。 
  47.          */  
  48.     }  
  49.   
  50.     @Override  
  51.     public void characters(char[] ch, int start, int length)  
  52.             throws SAXException {  
  53.         if (preTag != null) {  
  54.             String content = new String(ch, start, length);  
  55.             if ("name".equals(preTag)) {  
  56.                 book.setName(content);  
  57.             } else if ("price".equals(preTag)) {  
  58.                 book.setPrice(Float.parseFloat(content));  
  59.             }  
  60.         }  
  61.     }  
  62.   
  63.     public static void main(String args[]) {  
  64.           
  65.         SAXXml handler = new SAXXml();  
  66.   
  67.         // 定义SUN自带解析对象  
  68.         SAXParser parser;  
  69.         try {  
  70.             parser = SAXParserFactory.newInstance().newSAXParser();  
  71.             parser.parse(new File("D:/book.xml"), handler);  
  72.         } catch (ParserConfigurationException e) {  
  73.             // TODO Auto-generated catch block  
  74.             e.printStackTrace();  
  75.         } catch (SAXException e) {  
  76.             // TODO Auto-generated catch block  
  77.             e.printStackTrace();  
  78.         } catch (IOException e) {  
  79.             // TODO Auto-generated catch block  
  80.             e.printStackTrace();  
  81.         }  
  82.         List<Book> books = handler.getBooks();  
  83.         for (Book book : books) {  
  84.             System.out.println(book.toString());  
  85.         }  
  86.     }  

 JDOM解析方式

Java代码  
  1. public class JDOMXml {  
  2.       
  3.     public static void createXML(String outputPath) {  
  4.         // 先建立Document对象  
  5.         Document doc = new Document();  
  6.         // 建立元素节点  
  7.         Element allplus = new Element("allplus");  
  8.   
  9.         try {  
  10.             // 建立多个Element  
  11.             Element areaplus = new Element("areaplus");  
  12.             Element id = new Element("id");  
  13.             Element title = new Element("title");  
  14.             // 设置节点内容  
  15.             id.addContent("id");  
  16.             title.addContent("title");  
  17.             // 设置父子节点关系  
  18.             areaplus.addContent(id);  
  19.             areaplus.addContent(title);  
  20.             allplus.addContent(areaplus);  
  21.             // 设置根节点  
  22.             doc.setRootElement(allplus);  
  23.   
  24.             // 使用IO流操作  
  25.             FileWriter writer = new FileWriter(new File(outputPath));  
  26.   
  27.             // 定义输出对象  
  28.             XMLOutputter outputter = new XMLOutputter();  
  29.             // 设置编码  
  30.             outputter.setEncoding("UTF-8");  
  31.             // 输出  
  32.             outputter.output(doc, writer);  
  33.             writer.close();  
  34.   
  35.         } catch (Exception e) {  
  36.             // TODO Auto-generated catch block  
  37.             e.printStackTrace();  
  38.         }  
  39.   
  40.     }  
  41.   
  42.     public static void parseXML(String xmlPath) {  
  43.         /* 
  44.          * 10M文档导致内存溢出 
  45.          */  
  46.         //完成解析功能。  
  47.         SAXBuilder builder = new SAXBuilder();  
  48.         try {  
  49.             Document doc = builder.build(new File(xmlPath));  
  50.             // 开始解析,取得根节点  
  51.             Element data = doc.getRootElement();  
  52.             // 取得所有的areaplus  
  53.             List<Element> actorInfos = data.getChildren("actor_info");  
  54.             if(actorInfos != null && actorInfos.size()>0) {  
  55.                 for(Element actorInfo:actorInfos) {  
  56.                     Element id = actorInfo.getChild("id");  
  57.                     Element name = actorInfo.getChild("name");  
  58.                     System.out.println(id.getTextTrim() + " --- " + name.getTextTrim());  
  59.                 }  
  60.             }  
  61.         } catch (JDOMException e) {  
  62.             e.printStackTrace();  
  63.         } catch (IOException e) {  
  64.             e.printStackTrace();  
  65.         }  
  66.     }  
  67.   
  68.     public static void main(String[] args) {  
  69.         parseXML("D:/actor_info.xml");  
  70.         createXML("d:/fdfdsf.xml");  
  71.     }  

 DOM4J解析方式

Java代码  
  1. package com.fxb.test;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileWriter;  
  5. import java.io.IOException;  
  6. import java.io.Writer;  
  7. import java.util.Iterator;  
  8.   
  9. import org.dom4j.Document;  
  10. import org.dom4j.DocumentException;  
  11. import org.dom4j.DocumentHelper;  
  12. import org.dom4j.Element;  
  13. import org.dom4j.io.SAXReader;  
  14. import org.dom4j.io.XMLWriter;  
  15.   
  16. /** 
  17.  *  
  18.  * @author hongliang.dinghl Dom4j 生成XML文档与解析XML文档 
  19.  */  
  20. public class DOM4JXml {  
  21.   
  22.     public void createXml(String fileName) {  
  23.         Document document = DocumentHelper.createDocument();  
  24.         Element employees = document.addElement("data");  
  25.         Element employee = employees.addElement("actor_info");  
  26.         Element id = employee.addElement("id");  
  27.         id.setText("1");  
  28.         Element name = employee.addElement("name");  
  29.         name.setText("你好");  
  30.         Element message = employee.addElement("message");  
  31.         message.setText("你好吗");  
  32.         Element pic = employee.addElement("pic");  
  33.         pic.setText("123");  
  34.         Element sex = employee.addElement("sex");  
  35.         pic.setText("男");  
  36.         Element birthday = employee.addElement("birthday");  
  37.         pic.setText("19881212");  
  38.         try {  
  39.             Writer fileWriter = new FileWriter(fileName);  
  40.             XMLWriter xmlWriter = new XMLWriter(fileWriter);  
  41.             xmlWriter.write(document);  
  42.             xmlWriter.close();  
  43.         } catch (IOException e) {  
  44.             System.out.println(e.getMessage());  
  45.         }  
  46.   
  47.     }  
  48.   
  49.     public void parserXml(String fileName) {  
  50.         File inputXml = new File(fileName);  
  51.         SAXReader saxReader = new SAXReader();  
  52.         try {  
  53.             Document document = saxReader.read(inputXml);  
  54.             Element data = document.getRootElement();  
  55.             for (Iterator i = data.elementIterator(); i.hasNext();) {  
  56.                 Element actorInfo = (Element) i.next();  
  57.                 //System.out.println(employee.getName() + "->" + employee.getText());  
  58.                 for (Iterator j = actorInfo.elementIterator(); j.hasNext();) {  
  59.                     Element child = (Element) j.next();  
  60.                     System.out.println(child.getName() + ":" + child.getText());  
  61.                 }  
  62.                 System.out.println("=================");  
  63.             }  
  64.         } catch (DocumentException e) {  
  65.             System.out.println(e.getMessage());  
  66.         }  
  67.     }  
  68.       
  69.     public static void main(String args[]) {  
  70.         DOM4JXml dom = new DOM4JXml();  
  71.         //dom.parserXml("d:/actor_info.xml");  
  72.         dom.createXml("d:/fxb.xml");  
  73.     }  
  74. }  
 

 

 

4 
2 
分享到:  
评论
1 楼 hecal 2012-08-11  
god,兄弟你的代码有个bug.
在你的SAX解析方式里,有一个小bug.其他的没看。

50.    @Override  
51.    public void characters(char[] ch, int start, int length)  
52.            throws SAXException {  
53.        if (preTag != null) {  
54.            String content = new String(ch, start, length);  
55.            if ("name".equals(preTag)) {  
56.                book.setName(book.getName() + content);  
57.            } else if ("price".equals(preTag)) {  
58.                book.setPrice(Float.parseFloat(content));  
59.            }  
60.        }  
61.    }  

原因:当name是很长的文章的时候,就被切断了,结果出错了。
http://lewis-fxb.iteye.com/blog/1243298
posted @ 2016-03-07 15:08  a318013800  阅读(300)  评论(0编辑  收藏  举报