zoukankan      html  css  js  c++  java
  • XML基础+Java解析XML +几种解析方式的性能比较

    XML基础+Java解析XML

    一:XML基础

    XML是什么:

    可扩展的标记语言

    XML能干什么:

    描述数据、存储数据、传输(交换)数据。

    XML与HTML区别:

    目的不一样

    XML 被设计用来描述数据,其焦点是数据的内容。

    HTML 被设计用来展示数据,其焦点是数据的外观。

    HTML可以不关闭标签(即标签可以不成对出现),但XML必须关闭标签(即标签必须成对出现)。

    HTML中的标签标识文本如何展示,而XML中的标签标识文本是什么含义(什么类型的文本)。

    XML文档节点类型

    u     文档(document)

    u     元素(element)

    u     属性(attribute)

    u     文本(PCDATA--parsed character data)

    u     注释(comment)

    u     DOCTYPE :主要验证文档内容的正确性

    u     实体(ENTITIES)

    u     CDATA(character data)

    XML语法

    1、声明:<?xmlversion="1.0" encoding="UTF-8"?>

    2、根节点:必须有一个根节点

    3、标签:标签必须有结束且区分大小写,标签必须顺序嵌套

    4、属性:必须引号引起值

    5、空格会被保留,HTML空格最多保留一个

    6、命名规则:命名必须见名知意

         a)名字可包含字母、数字以及其他的字符 

         b)名字不能以数字或者标点符号开始

         c)名字不能以字符“xml”(或者XML、Xml)开始

    7、名字不能包含空格

    8、 不应在 XML 元素名称中使用 ":" ,这是由于它用于命名空间(namespaces)的保留字。

    9、标签优先于属性。

    10、XML 命名空间可提供避免元素命名冲突的方法。

    11、CDATA:字符数据,<![CDATA[字符数据]]> ,字符数据不进行转义

    12、实体:&实体;

    Xml约束

    XML DTD 约束

    DTD(DocType Definition 文档类型定义)的作用是定义 XML 文档的合法构建模块。

    它使用一系列的合法元素来定义文档结构。用于约定XML格式。

    1、DTD引用方式
      1、内部 <!DOCTYPE 根元素 [元素声明]>

    例如:

    <?xml version="1.0"encoding="UTF-8" standalone="yes"?>

    <!DOCTYPE 书架 [

    <!ELEMENT 书架 (书+)>

    <!ELEMENT 书 (书名,作者,售价)>

    <!ELEMENT 书名 (#PCDATA)>

    <!ELEMENT 作者 (#PCDATA)>

    <!ELEMENT 售价 (#PCDATA)>

    ]>

    <书架>

    <书>

            <书名>Java就业培训教程</书名>

            <作者>张孝祥</作者>

            <售价>39.00元</售价>

    </书>

    ...

    </书架>

      2、外部私有的 SYSTEM   一般是我们自己定义的,可能只是一个公司内部使用

    <!DOCTYPE 根元素 SYSTEM "dtd文件位置">

    例如:

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE 书架 SYSTEM "book.dtd">

    <书架>

       <书>

          <书名>java编程思想</书名>

          <作者>Brnee</作者>

          <售价>80</售价>

       </书>

    </书架>

      3、外部公有的  PUBLIC   一般是一些标准,可能非常多的人用

     <!DOCTYPE 根元素 PUBLIC "命名空间""dtd文件位置">

    首先根据“命名空间”去问环境要相应的dtd文件,如果有,直接提供,如果没有再根据dtd文件位置找。

     

          例如:<!DOCTYPE web-app PUBLIC

                   "-//SunMicrosystems, Inc.//DTD Web Application 2.3//EN"

                   "http://java.sun.com/dtd/web-app_2_3.dtd">

    2、例子:
    <?xml version="1.0"?>
    <!DOCTYPE note [
      <!ELEMENT note (to,from,heading,body)>
      <!ELEMENT to      (#PCDATA)>
      <!ELEMENT from    (#PCDATA)>
      <!ELEMENT heading (#PCDATA)>
      <!ELEMENT body    (#PCDATA)>
    ]>
    <note>
      <to>Tove</to>
      <from>Jani</from>
      <heading>Reminder</heading>
      <body>Don't forget me this weekend</body>
    </note>
    3、参考文档:

    点击打开链接

    XML Schema 约束

    XML Schema 是基于 XML 的 DTD 替代者。XML Schema 描述 XML 文档的结构。XML Schema 语言也称作 XML Schema 定义(XML Schema Definition,XSD)。

    DTD不是通过XML语法定义文档结构, 不能定义数据类型和限制Schema通过XML语法定义文档结构,可以定义数据类型和限制

    约定XML格式

    • 定义可出现在文档中的元素
    • 定义可出现在文档中的属性
    • 定义哪个元素是子元素
    • 定义子元素的次序
    • 定义子元素的数目
    • 定义元素是否为空,或者是否可包含文本
    • 定义元素和属性的数据类型
    • 定义元素和属性的默认值以及固定值
    1、为何使用Schema

    XML Schema 是 DTD 的继任者

    • XML Schema 可针对未来的需求进行扩展
    • XML Schema 更完善,功能更强大
    • XML Schema 基于 XML 编写
    • XML Schema 支持数据类型和限制
    • XML Schema 支持命名空间
    2、Schema引用方式

    <users xmlns="命名空间"

           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

           xsi:schemaLocation="命名空间 Schema位置">

    如何找Schema,和DTD一样,首先根据命名空间问环境要,找不到再根据Schema位置找。

    3、例子:

     

    [html] view plain copy
     
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"  
    3.             <!--xs="http://www.w3.org/2001/XMLSchema" 声名了w3c的名称空间,方便下面调用 -->    
    4.               
    5.              targetNamespace="http://www.zhong.cn"  
    6.                       elementFormDefault="qualified">      
    7. <!--  
    8.     schema 是根元素  
    9.       
    10.     xmlns:xs="http://www.w3.org/2001/XMLSchema"                     
    11.     指明了在schema中使用的元素和数据种类来自http://www.w3.org/2001/XMLSchema名称空间(namespace)。  
    12.     它也指定了来自"http://www.w3.org/2001/XMLSchema"名称空间(namespace)的元素和数据种类必须带前缀“xs:”    
    13.       
    14.     targetNamespace="http://www.zhong.cn"(将全部元素绑定给这个名称空间)  
    15.     暗示了由这份schema(shiporder, orderperson, shipto, ....)定义的元素来自"http://www.zhong.com"名称空间  
    16.       
    17.     xmlns="http://www.w3schools.com"   
    18.     指明了默认名称空间(namespace)是http://www.w3schools.com.   
    19.       
    20.     elementFormDefault="qualified" (“unqualified”)将根节点绑定到名称空间  
    21.         将所有元素绑定到名称空间  
    22.   -->                    
    23.                         
    24.     <!--xs:element  指的是element这个元素来自于xs名称空间 -->                   
    25.     <xs:element name="shiporder"<!-- 定义一个元素 shiporder -->  
    26.      <xs:complexType>             <!-- 类型是:复合类型(里面包含元素或者属性) -->  
    27.       <xs:sequence>                   <!-- 元素要有顺序 -->  
    28.        <xs:element name="orderperson" type="xs:string"/>          <!-- 定义一个元素 orderperson 类型为:字符串 -->  
    29.        <xs:element name="shipto" minOccurs="1" maxOccurs="1"<!-- 定义一个元素 shipto 最少出现1次,最多出现1次  -->  
    30.         <xs:complexType<!-- shipto元素也是复合类型 -->  
    31.          <xs:sequence>   <!-- 元素要有顺序 -->  
    32.           <xs:element name="name" type="xs:string"/> <!-- 在shipto元素中定义一个元素 name 类型为:字符串 -->  
    33.           <xs:element name="address" type="xs:string"/>  
    34.           <xs:element name="city" type="xs:string"/>  
    35.           <xs:element name="country" type="xs:string"/>  
    36.          </xs:sequence>  
    37.         </xs:complexType>  
    38.        </xs:element>  
    39.        <xs:element name="item" maxOccurs="unbounded">  <!-- 在shiporder元素中定义一个元素 item 出现次数可以无限次 -->  
    40.         <xs:complexType>  
    41.          <xs:sequence>  
    42.           <xs:element name="title" type="xs:string"/>  
    43.           <xs:element name="note" type="xs:string" minOccurs="0"/>  
    44.           <xs:element name="quantity" type="xs:positiveInteger"/>  
    45.           <xs:element name="price" type="xs:decimal"/>  
    46.          </xs:sequence>  
    47.         </xs:complexType>  
    48.        </xs:element>  
    49.       </xs:sequence>  
    50.       <xs:attribute name="orderid" type="xs:string" use="required"/>  
    51.      </xs:complexType>  
    52.     </xs:element>   
    53. </xs:schema>  
    4、参考文档:

    点击打开链接

    二、Java解析XML

    l XML解析方式分为两种:dom和sax

    •    dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式。

    •    sax: (Simple API for XML) 不是官方标准,但它是XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。

    l XML解析器

    •    Crimson、Xerces 、Aelfred2

    l XML解析开发包

    •    Jaxp、Jdom、dom4j

    1、DOM解析

    DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的。

    DOM解析器把XML文档转化为一个包含其内容的树,并可以对树进行遍历。

    DOM是拉模型,在遍历文档时,会把感兴趣的部分从读取器中拉出,不需要引发事件,允许我们选择性地处理节点。这大大提高了灵活性,以及整体效率。

    JAXP(DOM解析)

    l  JAXP 开发包是J2SE的一部分,它由javax.xml、org.w3c.dom 、org.xml.sax 包及其子包组成

    l  在 javax.xml.parsers 包中,定义了几个工厂类,程序员调用这些工厂类,可以得到对xml文档进行解析的 DOM 或 SAX的解析器对象。

    1、java代码显例:

     

    [html] view plain copy
     
    1. <?xml version="1.0" encoding="UTF-8" standalone="no"?><exam>  
    2.     <student examid="111" idcard="123">  
    3.         <name>张三</name>  
    4.         <location>广州</location>  
    5.         <grade>100</grade>  
    6.     </student>  
    7.     <student examid="444" idcard="333">  
    8.         <name>李四</name>  
    9.         <location>大连</location>  
    10.         <grade>97</grade>  
    11.     </student>  
    12.       
    13.     <student examid="1111111" idcard="22222">  
    14.         <name>小毛</name>  
    15.         <location>广州</location>  
    16.         <grade>23.0</grade>  
    17.     </student>  
    18.         <student examid="199" idcard="300">  
    19.         <grade>80.0</grade>  
    20.         <location>广州</location>  
    21.         <name>钟源茂</name>  
    22. </student>  
    23. </exam>  
    [java] view plain copy
     
    1. package com.zhong.xml.parse;  
    2.   
    3. import java.io.BufferedReader;  
    4. import java.io.File;  
    5. import java.io.IOException;  
    6. import java.io.InputStreamReader;  
    7.   
    8. import javax.xml.parsers.DocumentBuilder;  
    9. import javax.xml.parsers.DocumentBuilderFactory;  
    10. import javax.xml.parsers.ParserConfigurationException;  
    11. import javax.xml.transform.Transformer;  
    12. import javax.xml.transform.TransformerException;  
    13. import javax.xml.transform.TransformerFactory;  
    14. import javax.xml.transform.dom.DOMSource;  
    15. import javax.xml.transform.stream.StreamResult;  
    16.   
    17. import org.w3c.dom.Document;  
    18. import org.w3c.dom.Element;  
    19. import org.w3c.dom.Node;  
    20. import org.w3c.dom.NodeList;  
    21. import org.xml.sax.SAXException;  
    22.   
    23. public class JaxpDemo {  
    24.   
    25.     /** 
    26.      * @param args 
    27.      * @throws IOException  
    28.      */  
    29.     public static void main(String[] args) throws Exception {  
    30.   
    31.           
    32.         System.out.print("添加用户:(a)  ");  
    33.         System.out.print("删除用户:(b)  ");  
    34.         System.out.println("查询成绩:(c)");  
    35.         System.out.print("请输入操作类型:");  
    36.         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  
    37.         String type = br.readLine();  
    38.           
    39.         if("a".equals(type)){  
    40.               
    41.             //添加用户  
    42.             Student student = new Student();  
    43.             System.out.print("请输入学生姓名:");  
    44.             String name = br.readLine();  
    45.             student.setName(name);  
    46.             System.out.print("请输入学生准考证号:");  
    47.             String examid = br.readLine();  
    48.             student.setExamid(examid);  
    49.             System.out.print("请输入学生身份证号:");  
    50.             String idcart = br.readLine();  
    51.             student.setIdcart(idcart);  
    52.             System.out.print("请输入学生所在地:");  
    53.             String location = br.readLine();  
    54.             student.setLocation(location);  
    55.             System.out.print("请输入学生成绩:");  
    56.             String grade = br.readLine();  
    57.             student.setGrade(grade);  
    58.               
    59.             add(student);  
    60.             System.out.println("------添加数据成功------");  
    61.         }else if("b".equals(type)){  
    62.             //删除用户  
    63.             System.out.print("请输入删除的学生姓名:");  
    64.             String name = br.readLine();  
    65.             delete(name);  
    66.             System.out.println("------已成功删除学生信息------");  
    67.               
    68.         }else if("c".equals(type)){  
    69.             //查询成绩  
    70.             System.out.print("请输入查询的学生准考证号:");  
    71.             String examid = br.readLine();  
    72.             Student student = find(examid);  
    73.             System.out.println("您查询的学生信息为:");  
    74.             System.out.println(student);  
    75.               
    76.         }else{  
    77.             System.out.println("对不起,您的操作有误!!");  
    78.         }  
    79.     }  
    80.   
    81.     private static Student find(String examid) throws Exception {  
    82.   
    83.         Document document = getDocument();  
    84.         NodeList list = document.getElementsByTagName("student");  
    85.         for(int i=0;i<list.getLength();i++){  
    86.             Element element = (Element) list.item(i);  
    87.             String value = element.getAttribute("examid");  
    88.             if(examid.equals(value)){  
    89.                 Student student = new Student();  
    90.                 student.setExamid(examid);  
    91.                 student.setIdcart(element.getAttribute("idcart"));  
    92.                 student.setName(element.getElementsByTagName("name").item(0).getTextContent());  
    93.                 student.setLocation(element.getElementsByTagName("location").item(0).getTextContent());  
    94.                 student.setGrade(element.getElementsByTagName("grade").item(0).getTextContent());  
    95.                 return student;  
    96.             }  
    97.         }  
    98.         return null;  
    99.     }  
    100.   
    101.     private static void delete(String name) throws ParserConfigurationException, SAXException, IOException, TransformerException {  
    102.         Document document = getDocument();  
    103.         NodeList list = document.getElementsByTagName("name");  
    104.         for(int i=0;i<list.getLength();i++){  
    105.             Node node = list.item(i);  
    106.             if(node.getTextContent().equals(name)){  
    107.                 node.getParentNode().getParentNode().removeChild(node.getParentNode());  
    108.             }  
    109.         }  
    110.         writeXml(document);  
    111.     }  
    112.   
    113.     private static void add(Student student) throws Exception {  
    114.           
    115.         Document document = getDocument();  
    116.           
    117.         Element student_node = document.createElement("student");  
    118.         student_node.setAttribute("idcart", student.getIdcart());  
    119.         student_node.setAttribute("examid", student.getExamid());  
    120.           
    121.         Node name = document.createElement("name");  
    122.         name.setTextContent(student.getName());  
    123.         Node location = document.createElement("location");  
    124.         location.setTextContent(student.getLocation());  
    125.         Node grade = document.createElement("grade");  
    126.         grade.setTextContent(student.getGrade());  
    127.           
    128.         student_node.appendChild(name);  
    129.         student_node.appendChild(location);  
    130.         student_node.appendChild(grade);  
    131.           
    132.         Element root = document.getDocumentElement();  
    133.         root.appendChild(student_node);  
    134.           
    135.         writeXml(document);  
    136.     }  
    137.   
    138.     //将内存中的数据保存到XML文件中  
    139.     private static void writeXml(Document document) throws TransformerException {  
    140.           
    141.         DOMSource source = new DOMSource(document);  
    142.         StreamResult result = new StreamResult(new File("src/exam.xml"));  
    143.           
    144.         TransformerFactory factory = TransformerFactory.newInstance();  
    145.         Transformer trans = factory.newTransformer();  
    146.         trans.transform(source, result);  
    147.     }    
    148.   
    149.     //获得操作xml文件的对象  
    150.     private static Document getDocument() throws ParserConfigurationException,  
    151.             SAXException, IOException {  
    152.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();//得到创建 DOM 解析器的工厂。  
    153.         DocumentBuilder builder = factory.newDocumentBuilder();//得到 DOM 解析器对象。  
    154.         Document document = builder.parse(new File("src/exam.xml")); //得到代表整个文档的 Document 对象  
    155.         Element e = document.getDocumentElement();  
    156.         return document;  
    157.     }  
    158.   
    159. }  
    160.   
    161. class Student{  
    162.     private String name;  
    163.     private String examid;  
    164.     private String idcart;  
    165.     private String location;  
    166.     private String grade;  
    167.     public String getName() {  
    168.         return name;  
    169.     }  
    170.     public void setName(String name) {  
    171.         this.name = name;  
    172.     }  
    173.     public String getExamid() {  
    174.         return examid;  
    175.     }  
    176.     public void setExamid(String examid) {  
    177.         this.examid = examid;  
    178.     }  
    179.     public String getIdcart() {  
    180.         return idcart;  
    181.     }  
    182.     public void setIdcart(String idcart) {  
    183.         this.idcart = idcart;  
    184.     }  
    185.     public String getLocation() {  
    186.         return location;  
    187.     }  
    188.     public void setLocation(String location) {  
    189.         this.location = location;  
    190.     }  
    191.     public String getGrade() {  
    192.         return grade;  
    193.     }  
    194.     public void setGrade(String grade) {  
    195.         this.grade = grade;  
    196.     }  
    197.       
    198.     public String toString(){  
    199.         return "姓名:" + name + ",身份证号:" + idcart + ",准考证号:" + examid + ",地区:" + location + ",成绩:" + grade;  
    200.     }  
    201. }  



    2、DOM的基本对象有5个:Document,Node,NodeList,Element和Attr。
     2.1、Document对象

    代表了整个XML的文档,所有其它的Node,都以一定的顺序包含在Document对象之内,排列成一个树形的结构,程序员可以通过遍历这颗树来得到XML文档的所有的内容,这也是对XML文档操作的起点。我们总是先通过解析XML源文件而得到一个Document对象,然后再来执行后续的操作。此外,Document还包含了创建其它节点的方法,比如createAttribut()用来创建一个Attr对象。它所包含的主要的方法有:

    createAttribute(String):用给定的属性名创建一个Attr对象,并可在其后使用setAttributeNode方法来放置在某一个Element对象上面。

    createElement(String):用给定的标签名创建一个Element对象,代表XML文档中的一个标签,然后就可以在这个Element对象上添加属性或进行其它的操作。

    createTextNode(String):用给定的字符串创建一个Text对象,Text对象代表了标签或者属性中所包含的纯文本字符串。如果在一个标签内没有其它的标签,那么标签内的文本所代表的Text对象是这个Element对象的唯一子对象。

    getElementsByTagName(String):返回一个NodeList对象,它包含了所有给定标签名字的标签。

    getDocumentElement():返回一个代表这个DOM树的根节点的Element对象,也就是代表XML文档根元素的那个对象。

     2.2、Node对象

    是DOM结构中最为基本的对象,代表了文档树中的一个抽象的节点。在实际使用的时候,很少会真正的用到Node这个对象,而是用到诸如Element、Attr、Text等Node对象的子对象来操作文档。Node对象为这些对象提供了一个抽象的、公共的根。虽然在Node对象中定义了对其子节点进行存取的方法,但是有一些Node子对象,比如Text对象,它并不存在子节点,这一点是要注意的。Node对象所包含的主要的方法有:

    appendChild(org.w3c.dom.Node):为这个节点添加一个子节点,并放在所有子节点的最后,如果这个子节点已经存在,则先把它删掉再添加进去。

    getFirstChild():如果节点存在子节点,则返回第一个子节点,对等的,还有getLastChild()方法返回最后一个子节点。

    getNextSibling():返回在DOM树中这个节点的下一个兄弟节点,对等的,还有getPreviousSibling()方法返回其前一个兄弟节点。

    getNodeName():根据节点的类型返回节点的名称。

    getNodeType():返回节点的类型。

    getNodeValue():返回节点的值。

    hasChildNodes():判断是不是存在有子节点。

    hasAttributes():判断这个节点是否存在有属性。

    getOwnerDocument():返回节点所处的Document对象。

    insertBefore(org.w3c.dom.Node new,org.w3c.dom.Node ref):在给定的一个子对象前再插入一个子对象。

    removeChild(org.w3c.dom.Node):删除给定的子节点对象。

    replaceChild(org.w3c.dom.Node new,org.w3c.dom.Node old):用一个新的Node对象代替给定的子节点对象。

     2.3、NodeList对象

    顾名思义,就是代表了一个包含了一个或者多个Node的列表。可以简单的把它看成一个Node的数组,我们可以通过方法来获得列表中的元素:

    getLength():返回列表的长度。

    item(int):返回指定位置的Node对象。

     2.4、Element对象

    代表的是XML文档中的标签元素,继承于Node,亦是Node的最主要的子对象。在标签中可以包含有属性,因而Element对象中有存取其属性的方法,而任何Node中定义的方法,也可以用在Element对象上面。

    getElementsByTagName(String):返回一个NodeList对象,它包含了在这个标签中其下的子孙节点中具有给定标签名字的标签。

    getTagName():返回一个代表这个标签名字的字符串。

    getAttribute(String):返回标签中给定属性名称的属性的值。在这儿需要主要的是,应为XML文档中允许有实体属性出现,而这个方法对这些实体属性并不适用。这时候需要用到getAttributeNodes()方法来得到一个Attr对象来进行进一步的操作。

    getAttributeNode(String):返回一个代表给定属性名称的Attr对象。

     2.5、Attr对象

    代表了某个标签中的属性。Attr继承于Node,但是因为Attr实际上是包含在Element中的,它并不能被看作是Element的子对象,因而在DOM中Attr并不是DOM树的一部分,所以Node中的getParentNode(),getPreviousSibling()和getNextSibling()返回的都将是null。也就是说,Attr其实是被看作包含它的Element对象的一部分,它并不作为DOM树中单独的一个节点出现。这一点在使用的时候要同其它的Node子对象相区别。

     

    2、SAX解析

    SAX是Simple API forXML的缩写,它并不是由W3C官方所提出的标准,可以说是“民间”的事实标准。实际上,它是一种社区性质的讨论产物。虽然如此,在XML中对SAX的应用丝毫不比DOM少,几乎所有的XML解析器都会支持它。

    与DOM比较而言,SAX是一种轻量型的方法。我们知道,在处理DOM的时候,我们需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上的每个Node对象。当文档比较小的时候,这不会造成什么问题,但是一旦文档大起来,处理DOM就会变得相当费时费力。特别是其对于内存的需求,也将是成倍的增长,以至于在某些应用中使用DOM是一件很不划算的事(比如在applet中)。这时候,一个较好的替代解决方法就是SAX。

    SAX在概念上与DOM完全不同。首先,不同于DOM的文档驱动,它是事件驱动的,也就是说,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。所谓事件驱动,是指一种基于回调(callback)机制的程序运行方法。(如果你对Java新的代理事件模型比较清楚的话,就会很容易理解这种机制了)  

    回调:由我们在组件中定义,而不由我们调用,由容器或框架调用

    SAX是推模型,它是一种靠事件驱动的模型。当它每发现一个节点就引发一个事件,而我们需要编写这些事件的处理程序。这样的做法很麻烦,且不灵活。

    一、StAX 解析

    针对于XML的流式API(StAX),是在2004年3月的JSR 173规范中引入,这是一种针对XML的流式拉分析API。StAX是JDK 6.0提供的一种新特征。

    一个推模型分析器不断地生成事件,直到XML文档被完全分析结束。但是,拉分析由应用程序进行调整;因此,分析事件是由应用程序生成的。这意味着,使用StaX,你可以推迟分析-在分析时跳过元素并且分析多个文档。在使用DOM API的时候,你必须把整个的XML文档分析成一棵DOM结构,这样也就降低了分析效率。而借助于StAX,在分析XML文档时生成分析事件。

    二、JDOM

    JDOM的目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快。由于是第一个Java特定模型,JDOM一直得到大力推广和 促进。正在考虑通过“Java规范请求JSR-102”将它最终用作“Java标准扩展”。从2000年初就已经开始了JDOM开发。

    JDOM与DOM主要有两方面不同。首先,JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。第二,API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者的使用。 

    JDOM文档声明其目的是“使用20%(或更少)的精力解决80%(或更多)Java/XML问题”(根据学习曲线假定为20%)。JDOM对于大多数Java/XML应用程序来说当然是有用的,并且大多数开发者发现API比DOM容易理解得多。JDOM还包括对程序行为的相当广泛检查以防止用户做任何在XML中无意义的事。然而,它仍需要您充分理解XML以便做一些超出基本的工作(或者甚至理解某些情况下的错误)。这也许是比学习DOM或JDOM接口 都更有意义的工作。 
    JDOM自身不包含解析器。它通常使用SAX2解析器来解析和验证输入XML文档(尽管它还可以将以前构造的DOM表示作为输入)。它包含一些转换器以将 JDOM表示输出成SAX2事件流、DOM模型或XML文本文档。JDOM是在Apache许可证变体下发布的开放源码。 

    三、DOM4J

    http://dom4j.sourceforge.NET 

    虽然DOM4J代表了完全独立的开发结果,但最初,它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、 XML Schema支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,它通过DOM4J API和标准DOM接口具有并行访问功能。从2000下半年开始,它就一直处于开发之中。 

    为支持所有这些功能,DOM4J使用接口和抽象基本类方法。DOM4J大量使用了API中的Collections类,但是在许多情况下,它还提供一些替 代方法以允许更好的性能或更直接的编码方法。直接好处是,虽然DOM4J付出了更复杂的API的代价,但是它提供了比JDOM大得多的灵活性。 

    在添加灵活性、XPath集成和对大文档处理的目标时,DOM4J的目标与JDOM是一样的:针对Java开发者的易用性和直观操作。它还致力于成为比 JDOM更完整的解决方案,实现在本质上处理所有Java/XML问题的目标。在完成该目标时,它比JDOM更少强调防止不正确的应用程序行为。

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

    代码显例:

    用dom4j解析xml要导入dom4j.jar

    下载:点击打开链接

     

    [html] view plain copy
     
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <exam>  
    3.     <student examid="111" idcard="123">  
    4.         <name>张三</name>  
    5.         <location>广州</location>  
    6.         <grade>100</grade>  
    7.     </student>  
    8.     <student examid="444" idcard="333">  
    9.         <name>李四</name>  
    10.         <location>大连</location>  
    11.         <grade>97</grade>  
    12.     </student>  
    13.       
    14.     <student examid="1111111" idcard="22222">  
    15.         <name>小毛</name>  
    16.         <location>广州</location>  
    17.         <grade>23.0</grade>  
    18.     </student>  
    19.         <student examid="199" idcard="300">  
    20.         <grade>80.0</grade>  
    21.         <location>广州</location>  
    22.         <name>钟源茂</name>  
    23. </student>  
    24. </exam>  
    [java] view plain copy
     
    1. package cn.zhong.dao;  
    2.   
    3. import java.io.BufferedReader;  
    4. import java.io.File;  
    5. import java.io.FileOutputStream;  
    6. import java.io.IOException;  
    7. import java.io.InputStreamReader;  
    8. import java.util.Iterator;  
    9. import java.util.List;  
    10.   
    11. import javax.xml.parsers.ParserConfigurationException;  
    12.   
    13. import org.dom4j.Document;  
    14. import org.dom4j.DocumentException;  
    15. import org.dom4j.Element;  
    16. import org.dom4j.io.SAXReader;  
    17. import org.dom4j.io.XMLWriter;  
    18. import org.junit.Test;  
    19. import org.xml.sax.SAXException;  
    20.   
    21. public class Dom4j_demo {  
    22.   
    23.     public static void main(String[] args) throws IOException,  
    24.             ParserConfigurationException, SAXException, DocumentException {  
    25.         System.out.println("添加学生 (a) 查找学生 (b) 删除学生 (c)");  
    26.         System.out.print("请输入想要的操作:");  
    27.   
    28.         BufferedReader buf = new BufferedReader(  
    29.                 new InputStreamReader(System.in));  
    30.         String value = buf.readLine();  
    31.         if (value.equalsIgnoreCase("a")) {  
    32.             try {  
    33.                 System.out.print("请输入学生姓名:");  
    34.                 String name = buf.readLine();  
    35.   
    36.                 System.out.print("请输入学生准考证号:");  
    37.                 String examid = buf.readLine();  
    38.   
    39.                 System.out.print("请输入学生身份证号:");  
    40.                 String idcard = buf.readLine();  
    41.   
    42.                 System.out.print("请输入学生所在地:");  
    43.                 String location = buf.readLine();  
    44.   
    45.                 System.out.print("请输入学生成绩:");  
    46.                 String grade = buf.readLine();  
    47.   
    48.                 Student student = new Student();  
    49.                 student.setExamid(examid);  
    50.                 student.setGrade(Double.parseDouble(grade));  
    51.                 student.setIdcard(idcard);  
    52.                 student.setLocation(location);  
    53.                 student.setName(name);  
    54.   
    55.                 // StudentDaoByJaxp sd = new StudentDaoByJaxp();  
    56.                 // sd.appUser(student);  
    57.                 Dom4j_demo dj = new Dom4j_demo();  
    58.                 dj.appUser(student);  
    59.   
    60.                 System.out.println("恭喜你,添加成功");  
    61.                 dj.appUser(student);  
    62.   
    63.             } catch (IOException e) {  
    64.                 System.out.println("输入有误,添加失败,请重新输入");  
    65.             }  
    66.   
    67.         } else if (value.equalsIgnoreCase("b")) {  
    68.             System.out.print("请输入想查找的学生准考证号:");  
    69.             String examid = buf.readLine();  
    70.             Dom4j_demo dj = new Dom4j_demo();  
    71.             Student s = dj.selectUser(examid);  
    72.   
    73.             if (s != null) {  
    74.                 System.out.println("你要查找的学生的信息如下:");  
    75.                 System.out.println("姓名:" + s.getName());  
    76.                 System.out.println("准考证号:" + s.getExamid());  
    77.                 System.out.println("身份证号:" + s.getIdcard());  
    78.                 System.out.println("所在地:" + s.getLocation());  
    79.                 System.out.println("成绩:" + s.getGrade());  
    80.             } else {  
    81.                 System.out.println("你所查找的学生不存在");  
    82.             }  
    83.   
    84.         } else if (value.equalsIgnoreCase("c")) {  
    85.   
    86.             try {  
    87.                 System.out.print("请输入想删除的学生姓名:");  
    88.                 String name = buf.readLine();  
    89.                 Dom4j_demo dj = new Dom4j_demo();  
    90.                 dj.deleteUser(name);  
    91.   
    92.                 System.out.println("恭喜你,删除成功");  
    93.             } catch (Exception e) {  
    94.                 System.out.println("删除失败,请重新来过");  
    95.             }  
    96.         } else {  
    97.             System.out.println("请输入正确的指令");  
    98.         }  
    99.   
    100.     }  
    101.   
    102.     // 增加学生  
    103.     @Test  
    104.     public void appUser(Student student) {  
    105.         try {  
    106.             Document document = getDocument();  
    107.             Element rootNode = document.getRootElement();  
    108.   
    109.             Element sNode = rootNode.addElement("student");  
    110.             sNode.addAttribute("examid", student.getExamid());  
    111.             sNode.addAttribute("idcard", student.getIdcard());  
    112.   
    113.             sNode.addElement("name").setText(student.getName());  
    114.             sNode.addElement("location").setText(student.getLocation());  
    115.             sNode.addElement("grade").setText(student.getGrade() + "");  
    116.   
    117.             write2Xml(document);  
    118.   
    119.         } catch (Exception e) {  
    120.   
    121.             throw new RuntimeException();  
    122.         }  
    123.     }  
    124.   
    125.     // 查找学生  
    126.     @Test  
    127.     public Student selectUser(String examid) throws DocumentException {  
    128.         Document document = getDocument();  
    129.   
    130.         Element e = (Element) document.selectSingleNode("//student[@examid='"  
    131.                 + examid + "']");  
    132.         if (e != null) {  
    133.             Student s = new Student();  
    134.             s.setExamid(e.attributeValue("examid"));  
    135.             s.setIdcard(e.attributeValue("idcard"));  
    136.   
    137.             s.setName(e.element("name").getText());  
    138.             s.setLocation(e.element("location").getText());  
    139.             s.setGrade(Double.parseDouble(e.element("grade").getText()));  
    140.   
    141.             return s;  
    142.         } else {  
    143.             return null;  
    144.         }  
    145.   
    146.         /* 
    147.          * // List list=document.getRootElement().selectNodes("student"); List 
    148.          * list=document.selectNodes("//student");//使用xpath Iterator 
    149.          * it=list.iterator(); while(it.hasNext()) { Element e=(Element) 
    150.          * it.next(); String value=e.attributeValue("examid"); 
    151.          * if(value.equals(examid)) { Student s = new Student(); 
    152.          * s.setExamid(e.attributeValue("examid")); 
    153.          * s.setIdcard(e.attributeValue("idcard")); 
    154.          *  
    155.          * s.setName(e.element("name").getText()); 
    156.          * s.setLocation(e.element("location").getText()); 
    157.          * s.setGrade(Double.parseDouble(e.element("grade").getText())); 
    158.          *  
    159.          * return s; } } 
    160.          *  
    161.          * return null; 
    162.          */  
    163.     }  
    164.   
    165.     // 删除学生  
    166.     @Test  
    167.     public void deleteUser(String name) {  
    168.         try {  
    169.             Document document = getDocument();  
    170.             List list = document.selectNodes("//name");  
    171.             Iterator it = list.iterator();  
    172.             // Element nameNode1=(Element) it.next();  
    173.             // System.out.println(nameNode1.getText());  
    174.             while (it.hasNext()) {  
    175.                 Element nameNode = (Element) it.next();  
    176.                 String value = nameNode.getText();  
    177.                 if (value.equals(name)) {  
    178.                     // System.out.println(nameNode.getText());  
    179.                     nameNode.getParent().getParent()  
    180.                             .remove(nameNode.getParent());  
    181.                     write2Xml(document);  
    182.                     return;  
    183.                 }  
    184.             }  
    185.             throw new RuntimeException("删除失败");  
    186.   
    187.         } catch (Exception e) {  
    188.             throw new RuntimeException(e);  
    189.         }  
    190.     }  
    191.   
    192.     // 获得操作xml的对象 获得document对象     
    193.     public Document getDocument() throws DocumentException {  
    194.         SAXReader reader = new SAXReader();  
    195.         Document document = reader.read(new File("src//student.xml"));  
    196.   
    197.         /* 
    198.          * 2.解析XML形式的文本,得到document对象.               
    199.          * String text ="<members></members>"; 
    200.          * Document document =DocumentHelper.parseText(text); 
    201.          *  
    202.          * 3.主动创建document对象.               
    203.          * Document document =DocumentHelper.createDocument(); 
    204.          * //创建根节点 Element root =document.addElement("members"); 
    205.          */  
    206.   
    207.         return document;  
    208.     }  
    209.   
    210.     // 将内存中的内容写入xml  
    211.     public void write2Xml(Document document) throws IOException {  
    212.         //1.文档中全为英文,不设置编码,直接写入的形式  
    213.         XMLWriter writer = new XMLWriter(new FileOutputStream("src//student.xml"));  
    214.         writer.write(document);  
    215.         writer.close();  
    216.           
    217. //      2.文档中含有中文,设置编码格式写入的形式  
    218. //      OutputFormat format = OutputFormat.createPrettyPrint(); // 指定XML编码                     
    219. //       format.setEncoding("GBK");         
    220. //       XMLWriter writer = new XMLWriter(newFileWriter("output.xml"),format);  
    221. //       writer.write(document); writer.close();  
    222.   
    223.     }  
    224. }  
    225.   
    226. class Student {  
    227.     /* 
    228.      * <student examid="111" idcard="123" > <name>张三</name> 
    229.      * <location>广州</location> <grade>100</grade> </student> 
    230.      */  
    231.   
    232.     private String examid;  
    233.     private String idcard;  
    234.     private String name;  
    235.     private String location;  
    236.     private double grade;  
    237.   
    238.     public String getExamid() {  
    239.         return examid;  
    240.     }  
    241.   
    242.     public void setExamid(String examid) {  
    243.         this.examid = examid;  
    244.     }  
    245.   
    246.     public String getIdcard() {  
    247.         return idcard;  
    248.     }  
    249.   
    250.     public void setIdcard(String idcard) {  
    251.         this.idcard = idcard;  
    252.     }  
    253.   
    254.     public String getName() {  
    255.         return name;  
    256.     }  
    257.   
    258.     public void setName(String name) {  
    259.         this.name = name;  
    260.     }  
    261.   
    262.     public String getLocation() {  
    263.         return location;  
    264.     }  
    265.   
    266.     public void setLocation(String location) {  
    267.         this.location = location;  
    268.     }  
    269.   
    270.     public double getGrade() {  
    271.         return grade;  
    272.     }  
    273.   
    274.     public void setGrade(double grade) {  
    275.         this.grade = grade;  
    276.     }  
    277. }  



    3、DMO与SAX的区别

    一、DOM:拉模型,把整个文档加载到内存中
            优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;
            缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;
            使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)

    二、SAX:推模型,事件驱动编程,基于回调SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。
        优点:不用事先调入整个文档,占用资源少;

    缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;

    使用场合:数据量较大的XML文档,占用内存高,机器内存少,无法一次加载XML到内存;只需XML文档的少量内容,很少回头访问;
                              

    三、JDOM:为减少DOM、SAX的编码量,出现了JDOM;
            优点:20-80原则,极大减少了代码量,提供常用API减少重复劳动
             使用场合:要实现的功能简单,如解析、创建等Java程序

     但在底层,JDOM还是使用SAX(最常用)、DOM

    性能比较 

    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流被读入时,会有部分文档暂时隐藏在内存中)。 

  • 相关阅读:
    SparkSql初级编程实践
    云时代架构之苏宁安全架构演进及实践
    云时代架构之知乎网站架构变迁史
    质量属性的六个常见属性场景之《淘宝网》
    云时代架构之游戏服务器的架构演进
    《架构漫谈阅读心得》
    转换后缀表达式
    约瑟夫环(改进3.0)
    栈结构之后缀表达式
    约瑟夫环(改进2.0)
  • 原文地址:https://www.cnblogs.com/xtdxs/p/6628851.html
Copyright © 2011-2022 走看看