1. 程式人生 > >Java學習總結(21)——XML文檔解析:DOM解析,SAX解析

Java學習總結(21)——XML文檔解析:DOM解析,SAX解析

Oz 學習總結 AR javax exce 天氣 efault ray XP

一.XML簡介
1.可擴展性標記語言(eXtensible Markup Language)
2.XML用於描述數據
3.應用場合:
(1)持久化存儲數據
(2)數據交換
(3)數據配置
4.XML語法
(1)文檔類型:
在編寫XML文檔時,需要先使用文檔聲明,聲明XML文檔的類型。
最簡單的聲明語法:
<?Xml version=”1.0” ?>
用encoding屬性說明文檔的字符編碼:
<?Xml version=”1.0” encoding=”GB2312” ?>
(2)元素
對於XML標簽中出現的所有空格和換行,XML解析程序都會當標簽中的內容進行處理,例如:下面兩段內容的意義是不一樣的:

技術分享圖片

由於在XML中,空格和換行都作為原始內容被處理,所以,在編寫XML文件時,使用換行和縮進等方式來讓原文中的把內容清晰可讀的“良好”書寫習慣可能要被迫改變

(3)註釋
XML文件中的註釋采用:“<!--註釋內容-->”格式
註意:
XML聲明之前不能有註釋
註釋不能嵌套
(4)格式:
必須有XML聲明語句
必須有且僅有一個根元素
標簽大小寫敏感
屬性值用雙引號或單引號
標簽成對
元素正確嵌套
例1(聯系):
使用XML描述下表中的學生成績信息,XML文件為student.xml

XML表示如下:

<?xml version="1.0" encoding="GBK"?>
<students>
    <student>
        <id>1</id>
        <name>張同</name>
        <subject>java</subject>
        <score>89</score>
    </student>
    <student>
        <id>2</id>
        <name>李佳</name>
        <subject>sql</subject>
        <score>58</score>
    </student>
</students>

將文件拉入瀏覽器看是否可以顯示:
顯示結果:

二.DOM(Doncument Object Model)解析
1.DOM解析是將XML文件在的內存中換成一個文檔對象模型(通常稱為DOM樹),應用程序可以在任何時候訪問XML文檔中的任何一部分數據,因此,DOM解析的機制也被稱為隨機訪問機制。
註意:DOM解析對內存的需求比較高
2.DOM解析的步驟:
(1)建立DocumentBuilderFactory
技術分享圖片

(2)建立DocumentBuilder
技術分享圖片

(3)建立Document
技術分享圖片

(4)建立NodeList

技術分享圖片
(5)進行XML信息讀取
3.DOM數模型
技術分享圖片
例2(DOM解析XML文件,我們以剛才寫好的XML文件為例):

package org.xml.dom;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class DOMParserDemo {

    public static void main(String[] args) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();// 1.建立DOM工廠
        DocumentBuilder builder = null;
        try {
            builder = factory.newDocumentBuilder();// 2.獲得DOM解析器
            Document document = builder.parse("e:" + File.separator
                    + "userinfo.xml");// 3.指定解析的文件路徑,將XML文件在解析成DOM樹
            NodeList nodelist = document.getElementsByTagName("province");// 根據標簽名獲取獲取所有該標簽名的節點
            String value = nodelist.item(3).getFirstChild().getTextContent();// 獲取節點中的內容
            System.out.println("解析節點名稱為province的第三個元素中的內容為:" + value);
            System.out.println("獲取節點名稱:" + nodelist.item(3).getNodeName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

運行結果:

技術分享圖片

例3(動態創建XML文件):

package org.xml.dom;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

public class DOMCreateDemo {

    public static void main(String[] args) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();// 1.創建DOM工廠
        DocumentBuilder builder = null;
        try {
            builder = factory.newDocumentBuilder();// 2.獲取DOM解析器
            Document doc = builder.newDocument();// 3.新建文檔
            Element students = doc.createElement("students");
            Element student = doc.createElement("student");
            Element id = doc.createElement("id");
            Element name = doc.createElement("name");
            Element subject = doc.createElement("subject");
            Element score = doc.createElement("score");
            Text idtext = doc.createTextNode("1");
            Text nametext = doc.createTextNode("王昭君");
            Text subjecttext = doc.createTextNode("java");
            Text scoretext = doc.createTextNode("99.4");
            students.appendChild(student);
            student.appendChild(id);
            student.appendChild(name);
            student.appendChild(subject);
            student.appendChild(score);
            id.appendChild(idtext);
            name.appendChild(nametext);
            subject.appendChild(subjecttext);
            score.appendChild(scoretext);
            doc.appendChild(students);
            TransformerFactory factory2 = TransformerFactory.newInstance();
            Transformer tf = factory2.newTransformer();
            tf.setOutputProperty(OutputKeys.INDENT, "yes");//自動換行
            tf.setOutputProperty(OutputKeys.ENCODING, "GBK");
            DOMSource soure = new DOMSource(doc);// 生成DOMSource裏邊包含了doc對象
            StreamResult rs = new StreamResult(new File("f:" + File.separator
                    + "student.xml"));//StreamResult封裝了目標輸出文件
            tf.transform(soure, rs);//開始寫入
            System.out.println("student.xml文件生成成功......");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

運行結果:

技術分享圖片

三.SAX(Simple APIs for XML)解析
1.SAXs是一個用於處理XML事件驅動的“推”模型,在讀取文檔時激活一系列事件,這些事件被推給事件處理器,然後由事件處理器提供對文檔內容的訪問
2.通常用於查找,讀取XML數據
3.SAX解析步驟:
(1)編寫SAX解析器,該解析器類繼承自DefaultHanderler類,同時覆寫相關方法
(2)建立SAX解析工廠:
技術分享圖片

(3)構造解析器:
技術分享圖片

(4)解析XML:
技術分享圖片

例4(利用SAX解析XML文檔):
(1)自定義SAX解析器

package org.xml.saxdemo;

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

//自定義解析器
public class MySAXHandler extends DefaultHandler {

    // 文檔開始解析時自動調用該方法
    @Override
    public void startDocument() throws SAXException {
        System.out.println("XMl文檔開始解析..");
    }

    // 開始解析元素時,自動調用此方法
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        System.out.print("<" + qName);
        for (int i = 0; i < attributes.getLength(); i++) {
            System.out.print(" " + attributes.getLocalName(i) + "=\""
                    + attributes.getValue(i) + "\"");
        }
        System.out.print(">");
    }

    // 元素解析結束時自動調用該方法
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        System.out.print("</" + qName + ">");
    }

    // 解析文本數據時自動調用該方法
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        System.out.print(new String(ch, start, length));
    }

    // 文檔解析結束時自動調用該方法
    @Override
    public void endDocument() throws SAXException {
        System.out.println("文檔解析結束..");
    }
}

(2)測試解析XML文件

package org.xml.saxdemo;

import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class SAXDemo {

    public static void main(String[] args) {
        MySAXHandler handler=new MySAXHandler();
        //1.建立sax解析工廠
        SAXParserFactory factory=SAXParserFactory.newInstance();
        //2.構造解析器
        try {
            SAXParser parser=factory.newSAXParser();
            //3.解析XML
            parser.parse("e:"+File.separator+"userinfo.xml",handler );
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

}

運行結果:
技術分享圖片

例5(解析XML文檔並將其封裝如JavaBean對象中):
(1)編寫JavaBean代碼:
User對象:

package org.xml.saxbean2;

import java.util.List;

public class User {
    private String id;
    private String name;
    private List<Address> adds;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Address> getAdds() {
        return adds;
    }

    public void setAdds(List<Address> adds) {
        this.adds = adds;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + ", adds=" + adds + "]";
    }

}

Address對象:

package org.xml.saxbean2;

public class Address {
    private String type;
    private String province;
    private String city;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address [type=" + type + ", province=" + province + ", city="
                + city + "]";
    }

}

(2)自定義解析器:

package org.xml.saxbean2;

import java.util.*;

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

// SAX解析器
public class MySAXHandler extends DefaultHandler {
    private User user;
    private Address address;
    private List<Address> addressList;
    private List<User> userList;
    private String text; // 存儲文本

    // XML文檔開始解析時自動調用該方法
    @Override
    public void startDocument() throws SAXException {
        System.out.println("開始讀取XML文檔..");
    }

    // 開始解析文檔元素時自動調用該方法
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        if ("users".equals(qName)) {
            userList = new ArrayList<User>();
        } else if ("user".equals(qName)) {
            user = new User();
        } else if ("adds".equals(qName)) {
            addressList = new ArrayList<Address>();
        } else if ("address".equals(qName)) {
            address = new Address();
            address.setType(attributes.getValue(0));
        }
    }

    // 解析文本數據時調用
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        text = new String(ch, start, length);
    }

    // 元素解析完畢時開始調用
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if ("id".equals(qName)) {
            user.setId(text);
        } else if ("name".equals(qName)) {
            user.setName(text);
        } else if ("province".equals(qName)) {
            address.setProvince(text);
        } else if ("city".equals(qName)) {
            address.setCity(text);
        } else if ("address".equals(qName)) {
            addressList.add(address);
        } else if ("adds".equals(qName)) {
            user.setAdds(addressList);
        } else if ("user".equals(qName)) {
            userList.add(user);
        }
    }

    // 文檔解析完畢時開始調用
    @Override
    public void endDocument() throws SAXException {
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

(3)測試代碼

package org.xml.saxbean2;

import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class SAXDemo {

    public static void main(String[] args) {
        SAXParserFactory factory=SAXParserFactory.newInstance();
        try {
            SAXParser parser=factory.newSAXParser();
            parser.parse(new File("e:"+File.separator+"userinfo.xml"),new MySAXHandler());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

運行結果:
技術分享圖片
例5(解析網絡XML文檔,獲取當前天氣預報):
(1)編寫天氣預報JavaBean
(2)自定義SAX解析器
(3)測試SAX解析,獲取當前天氣信息

Java學習總結(21)——XML文檔解析:DOM解析,SAX解析