zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    C#获取局域网MAC地址
    查看Linux是32位还是64位的方法
    JS判断不能为空实例代码
    SQL2005数据库行列转换
    mysql 导入导出数据库、数据表的方法
    linux kill 关闭进程命令
    设置CentOS控制台分辨率图文详解
    Windows 2003 IIS 不支持ASP问题的解决方法
    稳聘App设计图分享
    Sql 中存储过程详细案例
  • 原文地址:https://www.cnblogs.com/pengmn/p/5250653.html
Copyright © 2011-2022 走看看