1. 程式人生 > 其它 >Java解析XML與建立

Java解析XML與建立

一、什麼是 XML?

  • XML 指可擴充套件標記語言(EXtensible Markup Language)
  • XML 是一種標記語言,很類似 HTML
  • XML 的設計宗旨是傳輸資料,而非顯示資料
  • XML 標籤沒有被預定義。您需要自行定義標籤。
  • XML 被設計為具有自我描述性。
  • XML 是 W3C 的推薦標準

一個xml文件,用於描述傳輸圖書資訊

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="1">
        <name>射鵰英雄傳</name>
        <
author>金庸</author> <publisher>三聯出版社</publisher> <price>200</price> </book> <book id="2"> <name>神鵰俠侶</name> <author>金庸</author> <publisher>三聯出版社</publisher> <price>200</
price> </book> <book id="3"> <name>倚天屠龍記</name> <author>金庸</author> <publisher>三聯出版社</publisher> <price>200</price> </book> <book id="4"> <name>鹿鼎記</name> <
author>金庸</author> <publisher>三聯出版社</publisher> <price>500</price> </book> <book id="5"> <name>天龍八部</name> <author>金庸</author> <publisher>三聯出版社</publisher> <price>500</price> </book> </books>

二、xml解析

  JAVA 解析 XML 通常有兩種方式,DOM 和 SAX。

  1、dom解析

package edu.cduestc.xml.domain;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class DOMParseXml {
    public static List<Book> parseXml(InputStream is){
        List<Book> list = new ArrayList<Book>();
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(is);
            Element root = document.getDocumentElement();
            NodeList nodes = root.getElementsByTagName("book");
            for(int i = 0; i < nodes.getLength(); i++) {
                Book book = new Book();
                Element node =  (Element)nodes.item(i);
                Integer id = Integer.valueOf(node.getAttribute("id"));
                book.setId(id);
                NodeList childNodes = node.getChildNodes();
                for(int j = 0; j < childNodes.getLength(); j++) {
                    //Element childNode =  (Element)childNodes.item(j);
                    if(childNodes.item(j).getNodeType() == Node.ELEMENT_NODE){
                        Element childNode =  (Element)childNodes.item(j);
                        if("name".equals(childNode.getTagName()))
                            book.setName(childNode.getTextContent());
                        if("author".equals(childNode.getTagName()))
                            book.setAuthor(childNode.getTextContent());
                        if("publisher".equals(childNode.getTagName()))
                            book.setPublisher(childNode.getTextContent());
                        if("price".equals(childNode.getTagName()))
                            book.setPrice(Float.parseFloat(childNode.getTextContent()));
                    }

                }
                list.add(book);
            }
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
    
    public static void main(String[] args) throws FileNotFoundException {
        BufferedInputStream is = new BufferedInputStream(new FileInputStream("books.xml"));
        parseXml(is).forEach(System.out::println);;
    }
}

  DOM 雖然是 W3C 的標準,提供了標準的解析方式,但它的解析效率一直不盡如人意,因為使用DOM解析XML時,解析器讀入整個文件並構建一個駐留記憶體的樹結構(節點樹),然後您的程式碼才可以使用 DOM 的標準介面來操作這個樹結構。但大部分情況下我們只對文件的部分內容感興趣,根本就不用先解析整個文件,並且從節點樹的根節點來索引一些我們需要的資料也是非常耗時的。

  SAX是一種XML解析的替代方法。相比於文件物件模型DOM,SAX 是讀取和操作 XML 資料的更快速、更輕量的方法。SAX 允許您在讀取文件時處理它,從而不必等待整個文件被儲存之後才採取操作。它不涉及 DOM 所必需的開銷和概念跳躍。 SAX API是一個基於事件的API ,適用於處理資料流,即隨著資料的流動而依次處理資料。SAX API 在其解析您的文件時發生一定事件的時候會通知您。在您對其響應時,您不作儲存的資料將會 被拋棄。

package edu.cduestc.xml.domain;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXParseXml {
    public static List<Book> parseXml(InputStream is) throws Exception, SAXException{
        
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();
        BookHandler handler = new BookHandler();
        parser.parse(is, handler);
        return handler.getBooks();
    }

    private static class BookHandler extends DefaultHandler{
        private List<Book> books;
        private Book book;
        private String tag;
        @Override
        public void startDocument() throws SAXException {
            books = new ArrayList<Book>();
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes)
                throws SAXException {
            if("book".equals(qName)) {
                book = new Book();
                book.setId(Integer.valueOf(attributes.getValue("id")));
            }
            tag = qName;
            
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if("book".equals(qName)) {
                books.add(book);
            }
            tag = null;
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if(tag != null) {
                String data = new String(ch,start,length);
                if("name".equals(tag))book.setName(data);
                else if("author".equals(tag))book.setAuthor(data);
                else if("publisher".equals(tag))book.setPublisher(data);
                else if("price".equals(tag))book.setPrice(Float.parseFloat(data));
            }
            
        }

        public List<Book> getBooks() {
            return books;
        }
        
    }
    
    public static void main(String[] args) throws Exception {
        BufferedInputStream is = new BufferedInputStream(new FileInputStream("books.xml"));
        parseXml(is).forEach(System.out::println);
        
    }
}

PULL解析類似於SAX解析,都採用事件驅動(利用getEventType()方法)方式進行解析,當PULL解析器開始解析之後,可以不斷地呼叫PULL解析器的next()方法獲取下一個解析事件(開始文件START_DOCUMENT、結束文件END_DOCUMENT、開始標籤START_TAG、結束標籤END_TAG等),當處於某個元素時,可呼叫XmlPullParser的getAttributeValue()方法來獲取該元素的屬性值(可以利用屬性索引和屬性名皆可),也可呼叫XmlPullParser的nextText()方法來獲取文字節點的值。

package edu.cduestc.xml.domain;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import org.xml.sax.SAXException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

public class PullParseXml {
    public static List<Book> parseXml(Reader reader) throws Exception, SAXException {
        List<Book> books = new ArrayList<Book>();
        Book book = null;
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        XmlPullParser parser = factory.newPullParser();
        
        parser.setInput(reader);
        
        int event = parser.getEventType();// 觸發第一個事件
        while (event != XmlPullParser.END_DOCUMENT) {
            switch (event) {
            case XmlPullParser.START_TAG:
                if ("book".equals(parser.getName())) {
                    book = new Book();
                    book.setId(Integer.valueOf(parser.getAttributeValue(0)));
                }
                if (book != null) {
                    if ("name".equals(parser.getName()))
                        book.setName(parser.nextText());
                    if ("author".equals(parser.getName()))
                        book.setAuthor(parser.nextText());
                    if ("publisher".equals(parser.getName()))
                        book.setPublisher(parser.nextText());
                    if ("price".equals(parser.getName()))
                        book.setPrice(Float.parseFloat(parser.nextText()));
                }
                break;
            case XmlPullParser.END_TAG:
                if ("book".equals(parser.getName())) {
                    books.add(book);
                    book = null;
                }
            }
            event = parser.next();// 繼續下一次事件
        }
        return books;
    }

    public static void main(String[] args) throws FileNotFoundException, SAXException, Exception {
        parseXml(new FileReader("books.xml")).forEach(System.out::println);
    }
}