• JAXP解析XML(基于DOM模型)


    对于XML解析通常分为两种:

    1.DOM解析(Document Object Model,文档对象模型),该方式是W3C 组织推荐的处理 XML 的一种方式。

    2.另一种是SAX(Simple API for XML)。

    当然IBM公司后面退出了JAXB,基于JavaBean的XML解析方式,不过本文描述的是DOM模型解析原理以及使用Java内置的API(JAXP---Java API for XML Processing)通过DOM模型来解析XML,因为JAXP作为JavaEE规范中的一种技术,所以作为一个Java程序猿来说掌握这套API是必须的

    一:什么是DOM?

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

    DOM模型定义访问和操作XML文档的标准方法。(即定义一种访问XML文档一种规范)

    下面来看一份XML文档:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <!--将DTD文件编写在XML文档内部-->
     3 <!DOCTYPE bookstore [
     4   <!ELEMENT bookstore (book)+>     
     5   <!ELEMENT book (title,author,year,price)>
     6   <!ELEMENT title (#PCDATA)>
     7   <!ELEMENT author (#PCDATA)>
     8   <!ELEMENT year (#PCDATA)>
     9   <!ELEMENT price (#PCDATA)>
    10   <!ATTLIST book category CDATA #REQUIRED>
    11   <!ATTLIST title lang CDATA #REQUIRED>
    12 ]>
    13 
    14 <bookstore>
    15   <book category="操作系统">
    16     <title lang="中文">鸟哥的私房菜</title>
    17     <author>鸟哥</author>
    18     <year>2005</year>
    19     <price>89.5</price>    
    20     </book>        
    21 </bookstore>

     

    这是一份有效(格式良好,且有DTD约束)的XML文档。

    当我们使用DOM方式去解析该XML文档的时候,XML文档会在内存中形成一个树形结构,而XML 文档中的每个成分都是一个节点

    这里特别要注意的是:

    W3C组织对DOM是这样定义的:

    整个文档是一个文档节点(Document)

    XML中的每个标签都是元素节点(Element Node)

    XML中的每个文本都是文本节点(Text Node)

    XML中的标签属性都是属性节点(Attr Node)

    XML中的注释被称为注释节点(Comment Node)

     

    文本总是存储在文本节点中,而不是存储在元素节点中的,在 DOM 处理中一个普遍的错误是,认为元素节点包含文本。

     不过,元素节点的文本是存储在文本节点中的。

     在这个例子中:<year>2005</year>,元素节点 <year>,拥有一个值为 "2005" 的文本节点。

     "2005" 不是 <year> 元素的值!

    最后需要注意的是:由于解析器会将XML文档中的所有节点都加载到内存之中,所以可以很方便的完成CRUD操作,但是此方法也过于暴力,XML文档内容过大时,可能会造成内存溢出的情况,这点大家都应该很清楚。

     

    二:使用JAXP采用DOM编程模型解析XML.

    解析XML的本质是通过解析器去完成的,但是我们并不是直接去调用解析器的方法去操作XML文档.而是SUN公司为我们提供了一套API让我们调用,与解析器交互的事情由SUN公司帮助我们完成.

     

      1 package cn.plx.jaxp;
      2 
      3 import java.io.File;
      4 
      5 import javax.xml.parsers.DocumentBuilder;
      6 import javax.xml.parsers.DocumentBuilderFactory;
      7 import javax.xml.transform.Transformer;
      8 import javax.xml.transform.TransformerFactory;
      9 import javax.xml.transform.dom.DOMSource;
     10 import javax.xml.transform.stream.StreamResult;
     11 
     12 import org.junit.Test;
     13 import org.w3c.dom.Attr;
     14 import org.w3c.dom.Comment;
     15 import org.w3c.dom.Document;
     16 import org.w3c.dom.Element;
     17 import org.w3c.dom.NamedNodeMap;
     18 import org.w3c.dom.Node;
     19 import org.w3c.dom.NodeList;
     20 
     21 /**
     22  * 使用SUN提供的JAXP解析XML文档
     23  * 
     24  * @author Administrator
     25  * 
     26  */
     27 public class JAXPTest {
     28 
     29     public static void main(String[] args) throws Exception {
     30         // 创建XML解析器工厂
     31         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     32         /*
     33          * om.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
     34          * xerces是由IBM公司提供的XML解析器
     35          */
     36         System.out.println(factory.getClass().getName());
     37 
     38         // 创建XML解析器
     39         DocumentBuilder builder = factory.newDocumentBuilder();
     40         System.out.println(builder.getClass().getName());
     41 
     42         /**
     43          * <pre>
     44          * 获取到Document对象,Document对象代表着DOM树的根节点
     45          * 使用Document对象可以对XML文档的数据进行基本操作
     46          * Document对象在DOM解析模型中也属于一个Node对象,
     47          * 它是其他Node对象所在的上下文,其他Node对象包括
     48          * Element,Text,Attr,Comment,Processing Instruction等等
     49          * 根节点 != 根元素,它们是包含关系
     50          * </pre>
     51          */
     52         Document document = builder.parse(new File("xml/book.xml"));
     53 
     54         /**
     55          * <pre>
     56          * 获取到XML文档的根元素
     57          * 对于XML中的Document是XML文档的根节点,而它的子元素是XML文档的XML文档根元素
     58          * </pre>
     59          */
     60         Element root = document.getDocumentElement();
     61         System.out.println("获取的XML文档的根元素节点:" + root.getTagName());
     62 
     63         /**
     64          * <pre>
     65          * 获取根元素节点的子节点
     66          * 对于XML文档而言,无论是Document,Elment,Text等等,
     67          * 它们在DOM解析模型中都属性一个Node,因此这里需要注意的一点是
     68          * 空白字符在DOM解析中也会被作为一个Node元素来处理。
     69          * </pre>
     70          */
     71         // 获取到根元素的子节点
     72         NodeList nodeList = root.getChildNodes();
     73 
     74         /*
     75          * 空白字符也会被当作子节点来处理,因为它也是一个Node来处理, 但是属性不会被作为子节点
     76          */
     77         System.out.println("子节点的个数为:" + nodeList.getLength());
     78 
     79         // 遍历所有的子节点
     80         for (int i = 0; i < nodeList.getLength(); i++) {
     81             Node node = nodeList.item(i);
     82             switch (node.getNodeType()) {
     83             case Node.ELEMENT_NODE:
     84                 System.out.println("获取的是元素:" + node.getNodeName());
     85                 break;
     86             case Node.TEXT_NODE:
     87                 System.out.println("获取的是文本" + node.getNodeName());
     88                 break;
     89             case Node.COMMENT_NODE:
     90                 System.out.println("获取的是注释:" + node.getNodeName());
     91                 Comment comment = (Comment) node;
     92                 System.out.println("注释的内容是:" + comment.getData());
     93                 break;
     94             }
     95         }
     96 
     97         System.out.println("--------访问属性----------");
     98         // 访问属性
     99         Attr attr = root.getAttributeNode("名字");
    100         System.out.println("根元素节点属性的值:" + attr.getValue());
    101 
    102         // 可以是使用一种更加直接的方式访问属性的值
    103         String attrValue = root.getAttribute("名字");
    104         System.out.println("另一种方式获取根元素节点属性的值:" + attrValue);
    105 
    106         // 获取元素的全部属性
    107         NamedNodeMap attrs = root.getAttributes();
    108         for (int i = 0; i < attrs.getLength(); i++) {
    109             Attr attr2 = (Attr) attrs.item(i);
    110             System.out.println("name:" + attr2.getName() + ",value:"
    111                     + attr2.getValue());
    112         }
    113 
    114     }
    115 
    116     /**
    117      * <pre>
    118      * 使用JAXP完成添加元素节点操作
    119      * 对于DOM解析模型来说,因为XML文档的上下文是Document对象
    120      * 所以对于XML文档的操作都使用Document对象来完成
    121      * </pre>
    122      */
    123     @Test
    124     public void addElementTest() throws Exception {
    125 
    126         // 创建解析器工厂
    127         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    128 
    129         // 创建解析器
    130         DocumentBuilder builder = factory.newDocumentBuilder();
    131 
    132         // 获取XML文档的根节点(root node)
    133         Document document = builder.parse(new File("xml/book2.xml"));
    134 
    135         // 返回新创建的Element节点
    136         Element book = document.createElement("书");
    137 
    138         Element bookName = document.createElement("书名");
    139         bookName.setTextContent("Liunx");
    140 
    141         Element author = document.createElement("作者");
    142         author.setTextContent("XXX");
    143 
    144         Element price = document.createElement("价格");
    145         price.setTextContent(String.valueOf(80.5));
    146 
    147         // 通过父元素添加子元素
    148         book.appendChild(bookName);
    149         book.appendChild(author);
    150         book.appendChild(price);
    151 
    152         document.getDocumentElement().appendChild(book);
    153 
    154         TransformerFactory transformerFactory = TransformerFactory
    155                 .newInstance();
    156         Transformer transformer = transformerFactory.newTransformer();
    157         transformer.transform(new DOMSource(document), new StreamResult(
    158                 new File("xml/book2.xml")));
    159     }
    160 
    161     /**
    162      * 更新节点元素
    163      */
    164     @Test
    165     public void updateElementTest() throws Exception {
    166 
    167         // 创建解析器工厂
    168         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    169 
    170         // 创建解析器
    171         DocumentBuilder builder = factory.newDocumentBuilder();
    172 
    173         // 获取XML文档的根节点(root node)
    174         Document document = builder.parse(new File("xml/book2.xml"));
    175 
    176         // 获取第3个价格元素
    177         Node priceNode = document.getElementsByTagName("价格").item(2);
    178         // 判断是否是Element类型
    179         if (priceNode.getNodeType() == Node.ELEMENT_NODE) {
    180             priceNode.setTextContent("200");
    181         }
    182 
    183         TransformerFactory transformerFactory = TransformerFactory
    184                 .newInstance();
    185         Transformer transformer = transformerFactory.newTransformer();
    186         transformer.transform(new DOMSource(document), new StreamResult(
    187                 new File("xml/book2.xml")));
    188     }
    189 
    190     @Test
    191     public void deleteElementTest() throws Exception {
    192         // 创建解析器工厂
    193         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    194 
    195         // 创建解析器
    196         DocumentBuilder builder = factory.newDocumentBuilder();
    197 
    198         // 获取XML文档的根节点(root node)
    199         Document document = builder.parse(new File("xml/book2.xml"));
    200 
    201         Node node = document.getElementsByTagName("书").item(2);
    202 
    203         document.getDocumentElement().removeChild(node);
    204         
    205         TransformerFactory transformerFactory = TransformerFactory
    206                 .newInstance();
    207         Transformer transformer = transformerFactory.newTransformer();
    208         transformer.transform(new DOMSource(document), new StreamResult(
    209                 new File("xml/book2.xml")));
    210     }
    211     
    212     /**
    213      * 添加子元素到到指定位置
    214      * @throws Exception
    215      */
    216     @Test
    217     public void insertElementTest() throws Exception{
    218 
    219         // 创建解析器工厂
    220         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    221 
    222         // 创建解析器
    223         DocumentBuilder builder = factory.newDocumentBuilder();
    224 
    225         // 获取XML文档的根节点(root node)
    226         Document document = builder.parse(new File("xml/book2.xml"));
    227 
    228         // 返回新创建的Element节点
    229         Element book = document.createElement("书");
    230 
    231         Element bookName = document.createElement("书名");
    232         bookName.setTextContent("Liunx");
    233 
    234         Element author = document.createElement("作者");
    235         author.setTextContent("XXX");
    236 
    237         Element price = document.createElement("价格");
    238         price.setTextContent(String.valueOf(80.5));
    239 
    240         // 通过父元素添加子元素
    241         book.appendChild(bookName);
    242         book.appendChild(author);
    243         book.appendChild(price);
    244 
    245         document.getDocumentElement().insertBefore(book, document.getElementsByTagName("书").item(1));
    246 
    247         TransformerFactory transformerFactory = TransformerFactory
    248                 .newInstance();
    249         Transformer transformer = transformerFactory.newTransformer();
    250         transformer.transform(new DOMSource(document), new StreamResult(
    251                 new File("xml/book2.xml")));
    252     }
    253     
    254     
    255     /**
    256      * 添加属性
    257      * @throws Exception
    258      */
    259     @Test
    260     public void addAttrTest() throws Exception{
    261 
    262         // 创建解析器工厂
    263         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    264 
    265         // 创建解析器
    266         DocumentBuilder builder = factory.newDocumentBuilder();
    267 
    268         // 获取XML文档的根节点(root node)
    269         Document document = builder.parse(new File("xml/book2.xml"));
    270         
    271         Node node = document.getElementsByTagName("书").item(1);
    272         if(node.getNodeType() == Node.ELEMENT_NODE){
    273             Element element  = (Element) node;
    274             element.setAttribute("名称","Java开发");
    275         }
    276         TransformerFactory transformerFactory = TransformerFactory
    277                 .newInstance();
    278         Transformer transformer = transformerFactory.newTransformer();
    279         transformer.transform(new DOMSource(document), new StreamResult(
    280                 new File("xml/book2.xml")));
    281     }
    282     
    283     
    284 
    285
  • 相关阅读:
    显示图案
    圆的面积和周长
    Python基础--list列表删除元素
    Python基础--列表添加元素
    Python基础--列表创建访问删除
    Python基础--序列简介
    一个网页通用的测试用例(转载)
    测试计划与测试方案的区别
    判断一棵树是否是二叉平衡树
    判断丑数与寻找丑数
  • 原文地址:https://www.cnblogs.com/plx927/p/3679101.html
Copyright © 2020-2023  润新知