XML的读(解析)和写

    在学习XML(eXtensible Markup Language)可扩展标记语言时,我们就了解到XML文件可以用来配置文件,可以进行数据交换,能实现异构语言之间的通信,异构平台之间的交互。而实现这些功能就需要对XML进行读和写操作,下面就列出一些常见的XML解析(读)方法:DOM解析SAX解析DOM4J解析JDOM解析,DOM和SAX解析是Java官方给我们的解析方式,而DOM4J和JDOM解析是其他组织提供的方式,我们需要下载相应的jar包并导进我们的项目中。

一、使用DOM方式解析和写XML文件(基于简单工厂模式的解析方式)  

    在解析XML之前,首先要了解一下简单工厂模式:  

    简单工厂模式是类的创建模式,又叫静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出那一个产品类的实例。通常它根据变量的不同返回不同的类的实例。简单工厂模式实质是由一个工厂类根据传入的参数,动态决定应该生成那个产品类的实例对象

    构成:工厂类角色(Creator):担任这个角色的是简单工厂模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体类实现。
              抽象产品角色(Product):担任这个角色的类是简单工厂模式所创建的对象的父类,或它们共同拥有的接口。抽象产品角色可以用一个接口或抽象类实现。
              具体产品角色(Concrete Product):简单工厂模式所创建的任何对象都是这个角色的实例,具体产品角色由一个具体类实现。

View Code

     DOM解析是将整个XML文件加载到内存当中进行解析,又由于DOM的树型结构占用内存较多,这种解析方式在解析大文件时其性能会很低。

     利用递归的方式解析XML文件并将结果输出到控制台上。

 1 import org.w3c.dom.*;
 2 import org.xml.sax.SAXException;
 3 
 4 import javax.xml.parsers.DocumentBuilder;
 5 import javax.xml.parsers.DocumentBuilderFactory;
 6 import javax.xml.parsers.ParserConfigurationException;
 7 import java.io.File;
 8 import java.io.IOException;
 9 
10 public class Domrxml {
11     private static void parseXML(Element element){
12         String nodeName = element.getNodeName();
13         NodeList childNodes = element.getChildNodes();
14         System.out.println("<"+nodeName);
15         // element元素的所有属性构成的NamedNodeMap对象,需要对其进行判断
16         NamedNodeMap attrs = element.getAttributes();
17        //   如果该元素存在属性
18         if(null!=attrs && attrs.getLength()>0){
19             for(int i = 0;i < attrs.getLength();i++){
20                 Attr item = (Attr) attrs.item(i);
21                 String name = item.getName();
22                 String value = item.getValue();
23                 System.out.print(" "+name+"=\""+value+"\"");
24             }
25         }
26         System.out.println(">");
27         if(null!=childNodes && childNodes.getLength()>0){
28             for (int i = 0; i < childNodes.getLength(); i++) {
29                 Node node = childNodes.item(i);
30                 //  获得节点类型
31                 short nodeType = node.getNodeType();
32                 //  是元素节点,继续递归
33                 if(Node.ELEMENT_NODE == nodeType){
34                     parseXML((Element)node);
35                 }else if (Node.TEXT_NODE == nodeType){
36                     System.out.println(node.getNodeValue());
37                 }else if(Node.COMMENT_NODE == nodeType){
38                     System.out.print("<--");
39                     Comment comment = (Comment) node;
40                     //  获得注释内容
41                     String commentData = comment.getData();
42                     System.out.print(commentData);
43                     System.out.println("-->");
44                 }
45             }
46             System.out.println("</"+nodeName+">");
47         }
48     }
49 
50     public static void main(String[] args) {
51         // 获得dom解析器工厂(作用是用于创建具体的解析器)
52         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
53         try {
54             // 获得具体的dom解析器
55             DocumentBuilder db = dbf.newDocumentBuilder();
56             // 利用DocumentBuilder对象的parse方法加载xml文件
57             Document parse = db.parse(new File("C:\\Users\\ztf\\Desktop\\xml\\5264.xml"));
58             //  获得文档的根元素
59             Element root = parse.getDocumentElement();
60             parseXML(root);
61         } catch (ParserConfigurationException e) {
62             e.printStackTrace();
63         } catch (SAXException e) {
64             e.printStackTrace();
65         } catch (IOException e) {
66             e.printStackTrace();
67         }
68     }
69 }
View Code

     使用DOM方式写一个XML文件:

 1 import org.w3c.dom.Document;
 2 import org.w3c.dom.Element;
 3 
 4 import javax.xml.parsers.DocumentBuilder;
 5 import javax.xml.parsers.DocumentBuilderFactory;
 6 import javax.xml.parsers.ParserConfigurationException;
 7 import javax.xml.transform.*;
 8 import javax.xml.transform.dom.DOMSource;
 9 import javax.xml.transform.stream.StreamResult;
10 import java.io.File;
11 
12 public class Domwxml {
13     public DocumentBuilder getDocumentBuilder(){
14         DocumentBuilder db = null;
15         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
16         try {
17             db = dbf.newDocumentBuilder();
18         } catch (ParserConfigurationException e) {
19             e.printStackTrace();
20         }
21         return db;
22     }
23 
24     public void createXml(){
25         DocumentBuilder db = getDocumentBuilder();
26         // 创建一个新文档
27         Document document = db.newDocument();
28         // 设置standlone的属性为yes,其默认为不显示
29         document.setXmlStandalone(true);
30         // 创建节点
31         Element bookstore = document.createElement("bookstore");
32         // 向文档中添加节点
33         document.appendChild(bookstore);
34         Element book = document.createElement("book");
35         bookstore.appendChild(book);
36         book.setAttribute("id","1");
37         Element name = document.createElement("name");
38         book.appendChild(name);
39         name.setTextContent("小学生");
40         // 将文档树生成xml文件
41         TransformerFactory tf = TransformerFactory.newInstance();
42         try {
43             Transformer transformer = tf.newTransformer();
44             // 设置输出属性是否自动换行
45             transformer.setOutputProperty(OutputKeys.INDENT,"yes");
46             transformer.transform(new DOMSource(document),new StreamResult(new File("C:\\Users\\ztf\\Desktop\\xml\\book.xml")));
47         } catch (TransformerConfigurationException e) {
48             e.printStackTrace();
49         } catch (TransformerException e) {
50             e.printStackTrace();
51         }
52     }
53 }
View Code

二、使用SAX方式解析和写XML文件(基于事件驱动的方式)

     SAX解析方式是采用事件驱动的方式来解析XML文件,它不必将整个文档加载到内存中,对内存耗费小,在解析文档时每执行一行XML文件,就会调用SAX特有的Handler处理类去逐个分析遇到的每个节点,适合对XML文件进行顺序访问。

     首先需要创建一个类来继承DefaultHandler类,在其中来写解析XML文件的逻辑。

 1 //创建Handler类
 2 
 3 import com.water.entity.Book;
 4 import org.xml.sax.Attributes;
 5 import org.xml.sax.SAXException;
 6 import org.xml.sax.helpers.DefaultHandler;
 7 
 8 import java.util.ArrayList;
 9 
10 public class SaxParserHandler extends DefaultHandler {
11     // 设置全部变量
12     String value = null;
13     Book book = null;
14 
15     public ArrayList<Book> getBookArrayList() {
16         return bookArrayList;
17     }
18 
19     private ArrayList<Book> bookArrayList = new ArrayList<>();
20     int bookIndex = 0;
21     // 用来遍历xml文件的开始标签
22     @Override
23     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
24     //  调用DefaultHandler类的startElement方法
25         super.startElement(uri, localName, qName, attributes);
26     //  开始解析元素属性
27         if(qName.equals("book")){
28             bookIndex++;
29             book = new Book();
30               //  已知属性名的情况下获取值
31              //  String id = attributes.getValue("id");
32              //  不知属性名及个数情况下,获取属性名及个数
33             for (int i = 0; i < attributes.getLength(); i++) {
34                 //  获取属性名和属性值
35                 System.out.println(attributes.getQName(i)+attributes.getValue(i));
36                 if(attributes.getQName(i).equals("id")){
37                     book.setId(attributes.getValue(i));
38                 }
39             }
40         }else if (!qName.equals("book")&&!qName.equals("bookstore")){
41             System.out.println("节点名"+qName);
42         }
43     }
44 
45     // 用来遍历xml文件的结束标签
46     @Override
47     public void endElement(String uri, String localName, String qName) throws SAXException {
48         super.endElement(uri, localName, qName);
49         if(qName.equals("book")){
50             bookArrayList.add(book);
51             book = null;
52             System.out.println("第"+bookIndex+"个节点解析结束");
53         }else if (qName.equals("name")){
54             book.setName(value);
55         }
56     }
57 
58     // 用来标识解析开始
59     @Override
60     public void startDocument() throws SAXException {
61         super.startDocument();
62     }
63 
64     // 用来标识解析结束
65     @Override
66     public void endDocument() throws SAXException {
67         super.endDocument();
68     }
69 
70     @Override
71     public void characters(char[] ch, int start, int length) throws SAXException {
72         super.characters(ch, start, length);
73         value = new String(ch, start, length);
74         if (value.trim().equals("")){
75             System.out.println(value);
76         }
77     }
78 }
View Code

      解析XML文件是在Handler的基础上进行的,

 1 import com.water.entity.Book;
 2 import com.water.handler.SaxParserHandler;
 3 import org.xml.sax.SAXException;
 4 import org.xml.sax.helpers.AttributesImpl;
 5 
 6 import javax.xml.parsers.ParserConfigurationException;
 7 import javax.xml.parsers.SAXParser;
 8 import javax.xml.parsers.SAXParserFactory;
 9 import javax.xml.transform.OutputKeys;
10 import javax.xml.transform.Transformer;
11 import javax.xml.transform.TransformerConfigurationException;
12 import javax.xml.transform.TransformerFactory;
13 import javax.xml.transform.sax.SAXTransformerFactory;
14 import javax.xml.transform.sax.TransformerHandler;
15 import javax.xml.transform.stream.StreamResult;
16 import java.io.File;
17 import java.io.FileNotFoundException;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.util.ArrayList;
21 
22 public class Saxxml {
23     public ArrayList<Book> parseXml(){
24         // 获取一个SAXParserFactory的实例
25         SAXParserFactory spf = SAXParserFactory.newInstance();
26         SaxParserHandler sph = null;
27 
28         try {
29             // 获取SAXParser的实例
30             SAXParser sp = spf.newSAXParser();
31             // 创建一个SAXParserHandler对象
32             sph = new SaxParserHandler();
33             sp.parse("C:\\Users\\ztf\\Desktop\\xml\\5264.xml",sph);
34 
35         } catch (ParserConfigurationException e) {
36             e.printStackTrace();
37         } catch (SAXException e) {
38             e.printStackTrace();
39         } catch (IOException e) {
40             e.printStackTrace();
41         }
42         return sph.getBookArrayList();
43     }
44 
45 
46     // 生成xml文件
47     public void createXml(){
48         ArrayList<Book> books = parseXml();
49         // 创建一个TransformerFactory类的对象,返回的是一个TransformerFactory类型,需强制类型转换
50         SAXTransformerFactory tf = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
51 
52         try {
53             // 获取一个TransformerHandler对象
54             TransformerHandler tfh = tf.newTransformerHandler();
55             // 获取一个transformer对象,用于对xml的设置
56             Transformer transformer = tfh.getTransformer();
57             transformer.setOutputProperty(OutputKeys.ENCODING,"utf-8");
58             transformer.setOutputProperty(OutputKeys.INDENT,"yes");
59             //  创建一个result对象
60             StreamResult streamResult = new StreamResult(new FileOutputStream(new File("C:\\Users\\ztf\\Desktop\\xml\\book.xml")));
61             tfh.setResult(streamResult);
62              // 打开文档
63             tfh.startDocument();
64             // 创建一个属性对象
65             AttributesImpl attrs = new AttributesImpl();
66             tfh.startElement("","","bookstore",attrs);
67             for(Book book:books){
68                 // 清空attrs里的属性
69                 attrs.clear();
70                 attrs.addAttribute("","","id","int",book.getId());
71                 // 创建book节点
72                 tfh.startElement("","","book",attrs);
73                 attrs.clear();
74                 // 创建name节点
75                 if(book.getName()!=null && !book.getName().trim().equals("")){
76                     tfh.startElement("","","name",attrs);
77                     tfh.characters(book.getName().toCharArray(),0,book.getName().length());
78                     tfh.endElement("","","name");
79                 }
80                 tfh.endElement("","","book");
81             }
82             tfh.endElement("","","bookstore");
83             // 关闭文档
84             tfh.endDocument();
85         } catch (TransformerConfigurationException e) {
86             e.printStackTrace();
87         } catch (FileNotFoundException e) {
88             e.printStackTrace();
89         } catch (SAXException e) {
90             e.printStackTrace();
91         }
92 
93     }
94 
95     public static void main(String[] args) {
96 
97     }
98 }
View Code

三、使用JDOM的方式来解析和写XML文件

        JDOM中仅使用具体类而不使用接口,API大量使用了Collection类,容易理解。

  1 import com.water.entity.Book;
  2 import org.jdom2.Attribute;
  3 import org.jdom2.Document;
  4 import org.jdom2.Element;
  5 import org.jdom2.JDOMException;
  6 import org.jdom2.input.SAXBuilder;
  7 import org.jdom2.output.EscapeStrategy;
  8 import org.jdom2.output.Format;
  9 import org.jdom2.output.XMLOutputter;
 10 
 11 import java.io.File;
 12 import java.io.FileInputStream;
 13 import java.io.FileOutputStream;
 14 import java.io.IOException;
 15 import java.util.ArrayList;
 16 import java.util.List;
 17 
 18 public class Jdomxml {
 19     private static ArrayList<Book> booklist = new ArrayList();
 20 
 21     public static ArrayList<Book> getBooklist() {
 22         return booklist;
 23     }
 24 
 25     private void parseXml(){
 26         Book book;
 27         //  创建一个SAXBuileder的对象
 28         SAXBuilder saxBuilder = new SAXBuilder();
 29         try {
 30             // 创建一个输入流,将xml文件加载到输入流中来
 31             FileInputStream fis = new FileInputStream("5264.xml");
 32             //  利用build方法将输入流加载到saxBuilder中
 33             Document document = saxBuilder.build(fis);
 34             //    通过document对象获取根节点
 35             Element rootElement = document.getRootElement();
 36             //   通过根节点来获取子节点的list集合
 37             List<Element> childrenList = rootElement.getChildren();
 38             //   对子节点集合进行遍历解析
 39             for(Element bk :childrenList){
 40                 book = new Book();
 41                 System.out.println("现在解析第"+(childrenList.indexOf(bk)+1)+"本书");
 42                 //   已知属性名及数量
 43                 //  String id = book.getAttributeValue("ID");
 44                 //   解析属性(不知道属性值及数量)
 45                 List<Attribute> attrs = bk.getAttributes();
 46                 for(Attribute attr:attrs){
 47                     //  遍历的属性不同于dom和sax方式,它解析出来不包含空白节点和空格
 48                     String name = attr.getName();
 49                     String value = attr.getValue();
 50                     if("id".equals(attr.getName())){
 51                         book.setId(attr.getValue());
 52                     }
 53                 }
 54                 //   对book子节点名及内容进行解析
 55                 List<Element> children = bk.getChildren();
 56                 for(Element e :children){
 57                     System.out.println(e.getName()+e.getValue());
 58                     if("name".equals(e.getName())){
 59                         book.setName(e.getValue());
 60                     }
 61                 }
 62                 booklist.add(book);
 63                 book = null;
 64                 System.out.println("结束解析第"+(childrenList.indexOf(bk)+1)+"本书");
 65             }
 66         } catch (JDOMException e) {
 67             e.printStackTrace();
 68         } catch (IOException e) {
 69             e.printStackTrace();
 70         }
 71     }
 72 
 73     private void createXml(){
 74         //  生成一个根节点
 75         Element rss = new Element("rss");
 76         rss.setAttribute("version","2.0");
 77         //  生成一个document
 78         Document document = new Document(rss);
 79         Element channel = new Element("channel");
 80         rss.addContent(channel);
 81         //  创建节点及添加内容
 82         Element title = new Element("title");
 83         title.setText("\"<\"标题名字>");
 84         channel.addContent(title);
 85         //  设置格式
 86         Format prettyFormat = Format.getPrettyFormat();
 87         prettyFormat.setEncoding("utf-8");
 88         //  设置换行
 89         prettyFormat.setIndent("");
 90 
 91         //  利用xmlOutputter将document转换成xml文件
 92         XMLOutputter xmlOutputter = new XMLOutputter(prettyFormat);
 93         try {
 94             xmlOutputter.output(document,new FileOutputStream(new File("book.xml")));
 95         } catch (IOException e) {
 96             e.printStackTrace();
 97         }
 98 
 99     }
100 
101     public static void main(String[] args) {
102         
103     }
104 }
View Code

四、 使用DOM4J的方式来解析和写XML文件

         DOM4J是JDOM的一种智能分支,它合并了很多超出基本XML文档表示的功能。它使用了接口和抽象基本类方法,是一个优秀的java XML API,具有性能优异,灵活性好,功能强大和极易使用的特点。

 1 import org.dom4j.*;
 2 import org.dom4j.io.OutputFormat;
 3 import org.dom4j.io.SAXReader;
 4 import org.dom4j.io.XMLWriter;
 5 
 6 import java.io.*;
 7 import java.util.Iterator;
 8 import java.util.List;
 9 
10 public class Dom4jxml {
11     private void parseXml(){
12         // 创建SAXReader对象
13         SAXReader sr = new SAXReader();
14         try {
15             // 通过sr的reader方法加载xml文件,并获取document对象
16             Document read = sr.read(new File("5264.xml"));
17             // 通过read对象获取根节点
18             Element rootElement = read.getRootElement();
19             // 通过rootElement获取节点迭代器
20             Iterator it = rootElement.elementIterator();
21             // 遍历迭代器
22             while(it.hasNext()){
23                 Element book = (Element)it.next();
24                 // 获取book的属性名及属性值
25                 List<Attribute> attrs = book.attributes();
26                 for(Attribute attr:attrs){
27                     attr.getName();
28                     attr.getValue();
29                 }
30                 Iterator its = book.elementIterator();
31                 while(its.hasNext()){
32                     Element bookChild = (Element)its.next();
33                     System.out.println(bookChild.getName()+bookChild.getStringValue());
34                 }
35             }
36         } catch (DocumentException e) {
37             e.printStackTrace();
38         }
39     }
40 
41     private void createXml(){
42         // 创建document对象,代表整个xml文档
43         Document document = DocumentHelper.createDocument();
44         // 创建根节点
45         Element rss = document.addElement("rss");
46         // 向rss节点中添加version属性
47         Element versiion = rss.addAttribute("version", "2.0");
48         // 生成子节点及子节点内容
49         Element channel = rss.addElement("channel");
50         Element title = channel.addElement("title");
51         title.setText("新闻");
52         // 设置生成xml的格式
53         OutputFormat prettyPrint = OutputFormat.createPrettyPrint();
54         prettyPrint.setEncoding("gbk");
55         // 生成xml文件
56         XMLWriter xmlWriter = null;
57         try {
58             xmlWriter = new XMLWriter(new FileOutputStream(new File("book.xml")),prettyPrint);
59             // 设置是否转义,默认值为true,代表转义
60             xmlWriter.setEscapeText(false);
61             xmlWriter.write(document);
62             xmlWriter.close();
63         } catch (UnsupportedEncodingException e) {
64             e.printStackTrace();
65         } catch (FileNotFoundException e) {
66             e.printStackTrace();
67         } catch (IOException e) {
68             e.printStackTrace();
69         }
70 
71 
72     }
73 
74     public static void main(String[] args) {
75 
76     }
77 }
View Code

 

posted @ 2017-06-30 15:26  守明  阅读(309)  评论(0编辑  收藏  举报