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
原文地址:https://www.cnblogs.com/plx927/p/3679101.html