【JAVA解析XML文件实现CRUD操作】

一、简介。

1.xml解析技术有两种:dom和sax

2.dom:Document Object Model,即文档对象模型,是W3C组织推荐的解析XML的一种方式。

sax:Simple API for XML,不是官方标准,单它是xml社区事实上的标准。

3.XML解析器:Crimson(sun,jdk自带)、Xerces(IBM 最好的解析器)、A elfred2(dom4j),使用哪种解析器对程序员基本上没有什么影响,我们学习的是解析开发包,解析开发包调用什么样的解析器对程序员没有意义。

4.XML解析开发包:Jaxp(sun)、Jdom(不推荐使用)、dom4j(比较不错),Pull(android的sdk自带,它使用的是另外的解析方式streaming api for xml,即stax)

5.JAXP:Java API for xml Processing,jaxp是sun提供的一套xml解析API,jaxp很好地支持了dom和sax解析方式

解析XML文档使用的包名:

javax.xml
org.xml.sax
org.w3c.dom

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

6.DOM解析过程:首先将整个文档加载到内存,形成DOM树。使用dom进行解析,得到Document对象

7.使用DOM解析方式的缺点:整个文档需要全部放入内存,如果是大文件极易出现内存溢出的情况。

使用DOM解析方式的有点:操作速度快。

二、使用DOM对XML文档实现CRUD操作。

首先创建一个类:Book,该类对应着XML文档的一个节点。

 1 package p00.domain;
 2 
 3 public class Book {
 4     public String title;
 5     public double price;
 6     public String id;
 7     public String getId()
 8     {
 9     return id;
10     }
11     public void setId(String id)
12     {
13     this.id=id;
14     }
15     public String getTitle()
16     {
17     return title;
18     }
19     public double getPrice()
20     {
21     return price;
22     }
23     public void setTitle(String title)
24     {
25     this.title=title;
26     }
27     public void setPrice(double price)
28     {
29     this.price=price;
30     }
31     public String toString()
32     {
33     return "图书ISBN为:"+id+"   书名为:"+title+"    价格为:"+price;
34     }
35     
36 }
Book.java

得到Document对象的公共方法:

 1 private static Document getDocument() throws Exception {
 2     DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
 3     //获得解析器实例
 4     DocumentBuilder db=dbf.newDocumentBuilder();
 5     //获得Document实例
 6     File file=new File("xmldata/books.xml");
 7     if(!file.exists())
 8     {
 9         System.out.println("目标文件不存在!");
10         return null;
11     }
12     Document document=db.parse(file);
13     return document;
14     }
View Code

通过接受Document对象参数写入到新文件newbooks.xml的方法:

 1  /**
 2     * 根据得到的Document对象将其中的内容保存到硬盘中的XML文件,完成持久化的工作。
 3     * @param document
 4     * @throws Exception
 5     */
 6     private static void saveToAnotherPlace(Document document) throws Exception {
 7     TransformerFactory tf=TransformerFactory.newInstance();
 8     Transformer transformer=tf.newTransformer();
 9     
10     Element rootSource=document.getDocumentElement();
11     Source xmlSource=new DOMSource(rootSource);
12     Result outputTarget=new StreamResult("xmldata/books1.xml");
13     transformer.transform(xmlSource, outputTarget);
14     }
View Code

原本books.xml文档中的内容:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <books>
 3     <book id="book1">
 4         <title>JAVA编程思想</title>
 5         <price>80.00</price>
 6     </book>
 7     <book id="book2">
 8         <title>JAVA核心技术</title>
 9         <price>100.00</price>
10     </book>
11 </books>

1、读取(R)

  1 package p01.getElementsByDomDemo;
  2 
  3 import java.io.File;
  4 import java.util.ArrayList;
  5 import java.util.Iterator;
  6 import java.util.List;
  7 
  8 import javax.xml.parsers.DocumentBuilder;
  9 import javax.xml.parsers.DocumentBuilderFactory;
 10 
 11 import org.w3c.dom.Document;
 12 import org.w3c.dom.Element;
 13 import org.w3c.dom.Node;
 14 import org.w3c.dom.NodeList;
 15 
 16 import p00.domain.Book;
 17 
 18 public class getElementsDemo {
 19     /**
 20      * 该类演示使用dom对xml文档的查询,包括元素节点查询和元素属性值查询。
 21      */
 22     public static List<Book>list=new ArrayList<Book>();
 23     public static void main(String[] args) throws Exception {
 24     /**
 25      * 得到所有的元素并保存到list中。
 26      */
 27         list=getAllElementsToList();
 28         traverse(list);//遍历集合,查看集合中的内容是否正确。
 29     }
 30     /**
 31      * 该方法用于遍历集合元素。
 32      * @param list2
 33      */
 34     private static void traverse(List<Book> list2) {
 35     System.out.println();
 36     System.out.println("得到的集合内容为:");
 37     Iterator<Book>it=list2.iterator();
 38     while(it.hasNext())
 39     {
 40         Book book=it.next();
 41         System.out.println(book);
 42     }
 43     }
 44     public static List<Book> getAllElementsToList() throws Exception
 45     {
 46     List<Book>list=new ArrayList<Book>();
 47     DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
 48     DocumentBuilder db=dbf.newDocumentBuilder();
 49     File file=new File("xmldata/books.xml");
 50     if(!file.exists())
 51     {
 52         System.out.println("目标文件不存在!");
 53         return list;
 54     }
 55     Document domtree=db.parse(file);
 56     //得到根元素列表
 57     NodeList roots=domtree.getElementsByTagName("books");
 58     Node root=roots.item(0);
 59     //根据根节点,遍历xml文档中的元素。
 60     NodeList books=root.getChildNodes();
 61     //显示结果为5本书,事实上包含了回车和换行。
 62 //    System.out.println("books节点的子节点长度为:"+books.getLength());
 63     //遍历得到的结果集,并去除回车和换行。
 64     for(int i=0;i<books.getLength();i++)
 65     {
 66         Node node=books.item(i);
 67         String name=node.getNodeName();
 68         if("book".equals(name))
 69         {
 70         Book book=new Book();
 71         Element bookElement=(Element)node;//父接口向子接口强制转换发生异常。
 72         String idValue=bookElement.getAttribute("id");
 73         book.setId(idValue);
 74         System.out.println("id属性值为:"+idValue);
 75         
 76         NodeList tp=node.getChildNodes();
 77         //这里由于回车换行的关系,所以长度为5
 78 //        System.out.println("book节点的子节点长度为:"+tp.getLength());
 79         for(int j=0;j<tp.getLength();j++)
 80         {
 81             Node node1=tp.item(j);
 82             String nodename=node1.getNodeName();
 83             if("title".equals(nodename))
 84             {
 85             String bookName=node1.getTextContent();
 86             book.setTitle(bookName);
 87             System.out.println("书名为:"+bookName);
 88             }
 89             if("price".equals(nodename))
 90             {
 91             String bookPrice=node1.getTextContent();
 92             System.out.println("价格为:"+bookPrice);
 93             double bookprice=Double.parseDouble(bookPrice);
 94             book.setPrice(bookprice);
 95             }
 96         }
 97         list.add(book);
 98         }
 99         else
100         continue;
101     }
102     return list;
103     }
104 
105 }
View Code

读取的时候应当注意的事项是调用getChildNodes方法的时候会将回车换行符作为一个子节点,应当加以判断识别才行。

2、修改(U)

 1 /**
 2      * 修改XML文档的内容,将JAVA编程思想修改为Thinking in Java
 3      * @param document
 4      */
 5     private static void updateXMLContent(Document document) {
 6     Element root=document.getDocumentElement();
 7     NodeList books=root.getElementsByTagName("book");
 8     for(int i=0;i<books.getLength();i++)
 9     {
10         Node node=books.item(i);
11         Element book=(Element)node;
12         String id=book.getAttribute("id");
13         if("book1".equals(id))
14         {
15         NodeList childs=node.getChildNodes();
16         for(int j=0;j<childs.getLength();j++)
17         {
18             Node title=childs.item(j);
19             String nodeName=title.getNodeName();
20             if("title".equals(nodeName))
21             {
22             Element aim=(Element)title;
23             aim.setTextContent("Thinking in java");
24             }
25             else
26             continue;
27         }
28         }
29         else
30         continue;
31     }
32     }
View Code

修改后的内容:

 1 <?xml version="1.0" encoding="UTF-8"?><books>
 2     <book id="book1">
 3         <title>Thinking in java</title>
 4         <price>80.00</price>
 5     </book>
 6     <book id="book2">
 7         <title>JAVA核心技术</title>
 8         <price>100.00</price>
 9     </book>
10 </books>

3、删除(D)

 1 /**
 2      * 删除指定元素的方法,要求:删除id值为002的元素。
 3      * @param document
 4      */
 5     private static void removeOldNodeFromXML(Document document) {
 6 
 7     Element root=document.getDocumentElement();
 8     NodeList books=root.getElementsByTagName("book");
 9     for(int i=0;i<books.getLength();i++)
10     {
11         Node node=books.item(i);
12         Element book=(Element)node;
13         String id=book.getAttribute("id");
14         if("book2".equals(id))
15         {
16         Node parent=node.getParentNode();
17         parent.removeChild(node);
18         }
19         else
20         continue;
21     }
22     
23     }
View Code

删除后内容:

1 <?xml version="1.0" encoding="UTF-8"?><books>
2     <book id="book1">
3         <title>JAVA编程思想</title>
4         <price>80.00</price>
5     </book>
6     
7 </books>

4、添加(C)

 1  /**
 2      * 添加新元素的方法。
 3      * :添加一个新节点,节点要求:id为book3,title为计算机网络,price为1.0
 4      * @param document
 5      */
 6     private static void addNewNodeToXML(Document document) {
 7     Element root=document.getDocumentElement();
 8     Element book=document.createElement("book");
 9     book.setAttribute("id", "book3");
10     Element title=document.createElement("title");
11     Element price=document.createElement("price");
12     title.setTextContent("计算机网络");
13     price.setTextContent("1.0");
14     book.appendChild(title);
15     book.appendChild(price);
16     root.appendChild(book);
17     }
View Code

添加后内容:

 1 <?xml version="1.0" encoding="UTF-8"?><books>
 2     <book id="book1">
 3         <title>JAVA编程思想</title>
 4         <price>80.00</price>
 5     </book>
 6     <book id="book2">
 7         <title>JAVA核心技术</title>
 8         <price>100.00</price>
 9     </book>
10 <book id="book3"><title>计算机网络</title><price>1.0</price></book></books>

注意使用这种方式添加的元素没有格式上的缩进。

5、完整代码。

  1 package p01.getElementsByDomDemo;
  2 
  3 import java.io.File;
  4 
  5 import javax.xml.parsers.DocumentBuilder;
  6 import javax.xml.parsers.DocumentBuilderFactory;
  7 import javax.xml.transform.Result;
  8 import javax.xml.transform.Source;
  9 import javax.xml.transform.Transformer;
 10 import javax.xml.transform.TransformerFactory;
 11 import javax.xml.transform.dom.DOMSource;
 12 import javax.xml.transform.stream.StreamResult;
 13 
 14 import org.w3c.dom.Document;
 15 import org.w3c.dom.Element;
 16 import org.w3c.dom.Node;
 17 import org.w3c.dom.NodeList;
 18 
 19 public class CUDDemo {
 20 
 21     public static void main(String[] args) throws Exception {
 22     Document document=getDocument();
 23     //修改操作:把id为book1的书籍title的值改为Thinking in java
 24 //    updateXMLContent(document);
 25     
 26     //添加新元素操作
 27 //    addNewNodeToXML(document);
 28     
 29     //删除指定元素的方法。
 30 //    removeOldNodeFromXML(document);
 31     //作为一个独立的方法将得到的document对象中的内容写入到硬盘中的文件。
 32     saveToAnotherPlace(document);
 33     }
 34     /**
 35      * 删除指定元素的方法,要求:删除id值为002的元素。
 36      * @param document
 37      */
 38     private static void removeOldNodeFromXML(Document document) {
 39 
 40     Element root=document.getDocumentElement();
 41     NodeList books=root.getElementsByTagName("book");
 42     for(int i=0;i<books.getLength();i++)
 43     {
 44         Node node=books.item(i);
 45         Element book=(Element)node;
 46         String id=book.getAttribute("id");
 47         if("book2".equals(id))
 48         {
 49         Node parent=node.getParentNode();
 50         parent.removeChild(node);
 51         }
 52         else
 53         continue;
 54     }
 55     
 56     }
 57     /**
 58      * 添加新元素的方法。
 59      * :添加一个新节点,节点要求:id为book3,title为计算机网络,price为1.0
 60      * @param document
 61      */
 62     private static void addNewNodeToXML(Document document) {
 63     Element root=document.getDocumentElement();
 64     Element book=document.createElement("book");
 65     book.setAttribute("id", "book3");
 66     Element title=document.createElement("title");
 67     Element price=document.createElement("price");
 68     title.setTextContent("计算机网络");
 69     price.setTextContent("1.0");
 70     book.appendChild(title);
 71     book.appendChild(price);
 72     root.appendChild(book);
 73     }
 74 
 75     /**
 76      * 修改XML文档的内容,将JAVA编程思想修改为Thinking in Java
 77      * @param document
 78      */
 79     private static void updateXMLContent(Document document) {
 80     Element root=document.getDocumentElement();
 81     NodeList books=root.getElementsByTagName("book");
 82     for(int i=0;i<books.getLength();i++)
 83     {
 84         Node node=books.item(i);
 85         Element book=(Element)node;
 86         String id=book.getAttribute("id");
 87         if("book1".equals(id))
 88         {
 89         NodeList childs=node.getChildNodes();
 90         for(int j=0;j<childs.getLength();j++)
 91         {
 92             Node title=childs.item(j);
 93             String nodeName=title.getNodeName();
 94             if("title".equals(nodeName))
 95             {
 96             Element aim=(Element)title;
 97             aim.setTextContent("Thinking in java");
 98             }
 99             else
100             continue;
101         }
102         }
103         else
104         continue;
105     }
106     }
107 
108    /**
109     * 根据得到的Document对象将其中的内容保存到硬盘中的XML文件,完成持久化的工作。
110     * @param document
111     * @throws Exception
112     */
113     private static void saveToAnotherPlace(Document document) throws Exception {
114     TransformerFactory tf=TransformerFactory.newInstance();
115     Transformer transformer=tf.newTransformer();
116     
117     Element rootSource=document.getDocumentElement();
118     Source xmlSource=new DOMSource(rootSource);
119     Result outputTarget=new StreamResult("xmldata/books1.xml");
120     transformer.transform(xmlSource, outputTarget);
121     }
122 
123     /**
124      * 得到Document对象的方法。
125      * @return
126      * @throws Exception
127      */
128     private static Document getDocument() throws Exception {
129     DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
130     //获得解析器实例
131     DocumentBuilder db=dbf.newDocumentBuilder();
132     //获得Document实例
133     File file=new File("xmldata/books.xml");
134     if(!file.exists())
135     {
136         System.out.println("目标文件不存在!");
137         return null;
138     }
139     Document document=db.parse(file);
140     return document;
141     }
142 
143 }
View Code

三、SAX

使用该解析技术只能实现对XML文档的读取操作。使用这种方式的优点就是它的解析方式为“逐行读取”,并非将XML文档一次性加载进内存,这样就能够避免内存溢出的情况了,该解析方式是dom4j的解析方式。

注意DefaultHandler类,该类实现了某些处理xml文档必须的接口,但是均没有具体的方法,也就是说是空方法,如果想要解析xml文档,需要覆写该方法。

 1 package p02.readElementsBySaxDemo;
 2 
 3 import java.io.File;
 4 
 5 import javax.xml.parsers.ParserConfigurationException;
 6 import javax.xml.parsers.SAXParser;
 7 import javax.xml.parsers.SAXParserFactory;
 8 
 9 import org.xml.sax.Attributes;
10 import org.xml.sax.SAXException;
11 import org.xml.sax.helpers.DefaultHandler;
12 
13 /**
14  * 该类的功能是通过Sax技术实现对xml文档的查找操作。
15  * 使用SAX技术不能实现对XML文档的增删改操作。
16  * @author kdyzm
17  *
18  */
19 public class ReadXMLBySax {
20 
21     public static void main(String[] args) throws Exception, SAXException {
22     SAXParserFactory spf=SAXParserFactory.newInstance();
23     SAXParser sp=spf.newSAXParser();
24     File file=new File("xmldata/books.xml");
25     MyHandler mh=new MyHandler();
26     sp.parse(file, mh);
27     }
28 
29 }
30 
31 /**
32  * 该类重写了默认处理类中的部分方法。
33  * @author kdyzm
34  *
35  */
36 class MyHandler extends DefaultHandler
37 {
38     
39     //文档开始的时候触发该事件
40     @Override
41     public void startDocument() throws SAXException {
42     System.out.println("开始解析文档!");
43     super.startDocument();
44     }
45 
46     //文档结束的时候触发该事件
47     @Override
48     public void endDocument() throws SAXException {
49     System.out.println("解析文档结束!");
50     super.endDocument();
51     }
52 
53     //当开始解析一个元素的时候触发该事件
54     @Override
55     public void startElement(String uri, String localName, String qName,
56         Attributes attributes) throws SAXException {
57     System.out.println("开始解析元素:"+qName+"    属性id的值是:"+attributes.getValue("id"));
58     super.startElement(uri, localName, qName, attributes);
59     }
60 
61     //解析完成一个元素的时候触发该事件
62     @Override
63     public void endElement(String uri, String localName, String qName)
64         throws SAXException {
65     super.endElement(uri, localName, qName);
66     System.out.println("解析元素结束:"+qName);
67     }
68 
69     //遇到字符串的时候触发该事件。
70     @Override
71     public void characters(char[] ch, int start, int length)
72         throws SAXException {
73     System.out.println("解析得到的字符串是:"+new String(ch,start,length));
74     super.characters(ch, start, length);
75     }
76     
77 }
View Code

输出:

开始解析文档!
开始解析元素:books    属性id的值是:null
解析得到的字符串是:
    
开始解析元素:book    属性id的值是:book1
解析得到的字符串是:
        
开始解析元素:title    属性id的值是:null
解析得到的字符串是:JAVA编程思想
解析元素结束:title
解析得到的字符串是:
        
开始解析元素:price    属性id的值是:null
解析得到的字符串是:80.00
解析元素结束:price
解析得到的字符串是:
    
解析元素结束:book
解析得到的字符串是:
    
开始解析元素:book    属性id的值是:book2
解析得到的字符串是:
        
开始解析元素:title    属性id的值是:null
解析得到的字符串是:JAVA核心技术
解析元素结束:title
解析得到的字符串是:
        
开始解析元素:price    属性id的值是:null
解析得到的字符串是:100.00
解析元素结束:price
解析得到的字符串是:
    
解析元素结束:book
解析得到的字符串是:

解析元素结束:books
解析文档结束!
View Code

四、使用dom4j解析包快速解析XML文档,实现CRUD操作。

posted @ 2015-03-22 17:13  狂盗一枝梅  阅读(418)  评论(0编辑  收藏  举报