XML SAX解析 附Java程序實例


 

XML解析之 SAX解析

 

SAX介紹

  SAX的全稱是Simple APIs for XML,也即XML簡單應用程序接口。

  與DOM不同,SAX提供的訪問模式是一種順序模式,這是一種快速讀寫XML數據的方式。

  當使用SAX分析器對XML文檔進行分析時,會觸發一系列事件,並激活相應的事件處理函數,應用程序通過這些事件處理函數實現對XML文檔的訪問,因而SAX接口也被稱作事件驅動接口

  

  局限性:

  1. SAX分析器在對XML文檔進行分析時,觸發了一系列的事件,由於事件觸發本身是有時序性的,因此,SAX提供的是一種順序訪問機制,對於已經分析過的部分,不能再倒回去重新處理。

  即,一旦經過了某個元素,我們沒有辦法返回去再去訪問它。

  2. SAX分析器只做了一些簡單的工作,大部分工作還要由應用程序自己去做。

  也就是說,SAX分析器在實現時,只是順序地檢查XML文檔中的字節流,判斷當前字節是XML語法中的哪一部分、是否符合XML語法,然后再觸發相應的事件,而事件處理函數本身則要由應用程序自己來實現。

  同DOM分析器相比,SAX分析器缺乏靈活性。

  優勢:

  然而,由於SAX分析器實現簡單,對內存要求比較低,(SAX不必將整個XML文檔加載到內存當中,因此它占據內存要比DOM小), 因此實現效率比較高。

  對於大型的XML文檔來說,通常會用SAX而不是DOM。

  並且對於那些只需要訪問XML文檔中的數據而不對文檔進行更改的應用程序來說,SAX分析器更為合適。

 

SAX分析器

 

 

 

  XML解析器實際上就是一段代碼,它讀入一個XML文檔並分析其結構。

 

  分類:

  帶校驗的解析器

  不校驗的解析器(效率高)

  支持DOM的解析器(W3C的官方標准)

  支持SAX的解析器(事實上的工業標准)

 

  SAX是事件驅動的,文檔的讀入過程就是SAX的解析過程。

  在讀入的過程中,遇到不同的項目,解析器會調用不同的處理方法。

 

SAX解析實例

  以一個xml文檔為例:

 

<?xml version="1.0" encoding="UTF-8"?>

<bookstore>
    <book category="children">
          <title lang="en">Harry Potter</title> 
          <author>J K. Rowling</author> 
          <year>2005</year> 
          <price>29.99</price> 
    </book>

    <book category="cooking">
          <title lang="en">Everyday Italian</title> 
          <author>Giada De Laurentiis</author> 
          <year>2005</year> 
          <price>30.00</price> 
    </book>

    <book category="web">
          <title lang="en">Learning XML</title> 
          <author>Erik T. Ray</author> 
          <year>2003</year> 
          <price>39.95</price> 
    </book>

    <book category="web">
          <title lang="en">XQuery Kick Start</title> 
          <author>James McGovern</author> 
          <author>Per Bothner</author> 
          <author>Kurt Cagle</author> 
          <author>James Linn</author> 
         <author>Vaidyanathan Nagarajan</author> 
          <year>2003</year> 
          <price>49.99</price> 
    </book>

</bookstore>

 

  用SAX解析這個文檔的Java代碼:

package com.example.xml.sax;

import java.io.File;
import java.util.Arrays;
import java.util.Stack;

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;

/**
 * SAX解析XML
 * 查看事件調用
 *
 */
public class SaxTest1
{

    public static void main(String[] args) throws Exception
    {
        // step 1: 獲得SAX解析器工廠實例
        SAXParserFactory factory = SAXParserFactory.newInstance();

        // step 2: 獲得SAX解析器實例
        SAXParser parser = factory.newSAXParser();

        // step 3: 開始進行解析
        // 傳入待解析的文檔的處理器
        parser.parse(new File("books.xml"), new MyHandler());

    }
}

class MyHandler extends DefaultHandler
{
    // 使用棧這個數據結構來保存
    private Stack<String> stack = new Stack<String>();

    @Override
    public void startDocument() throws SAXException
    {
        System.out.println("start document -> parse begin");
    }

    @Override
    public void endDocument() throws SAXException
    {

        System.out.println("end document -> parse finished");
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException
    {
        System.out.println("start element-----------");
        System.out.println("    localName: " + localName);
        System.out.println("    qName: " + qName);

    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException
    {
        System.out.println("characters-----------");
        // System.out.println("    ch: " + Arrays.toString(ch) );
        System.out.println("    ch: " + ch);
        System.out.println("    start: " + start);
        System.out.println("    length: " + length);
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException
    {
        System.out.println("end element-----------");

        System.out.println("    localName: " + localName);
        System.out.println("    qName: " + qName);

    }
}

  解析程序第二版:

package com.example.xml.sax;

import java.io.File;
import java.util.Stack;

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;

/**
 * SAX解析XML
 * 
 */
public class SaxTest2
{

    public static void main(String[] args) throws Exception
    {
        // step 1: 獲得SAX解析器工廠實例
        SAXParserFactory factory = SAXParserFactory.newInstance();

        // step 2: 獲得SAX解析器實例
        SAXParser parser = factory.newSAXParser();

        // step 3: 開始進行解析
        // 傳入待解析的文檔的處理器
        parser.parse(new File("books.xml"), new MySAXHandler());

    }
}

class MySAXHandler extends DefaultHandler
{
    // 使用棧這個數據結構來保存
    private Stack<String> stack = new Stack<String>();

    // 數據
    private String title;
    private String author;
    private String year;
    private double price;

    @Override
    public void startDocument() throws SAXException
    {
        System.out.println("start document -> parse begin");
    }

    @Override
    public void endDocument() throws SAXException
    {

        System.out.println("end document -> parse finished");
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException
    {
        // System.out.println("start element-----------");
        // System.out.println("    localName: " + localName);
        // System.out.println("    qName: " + qName);

        // 將標簽名壓入棧
        stack.push(qName);

        // 處理屬性
        for (int i = 0; i < attributes.getLength(); ++i)
        {
            String attrName = attributes.getQName(i);
            String attrValue = attributes.getValue(i);

            System.out.println("屬性: " + attrName + "=" + attrValue);

        }

    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException
    {
        // System.out.println("characters-----------");
        // System.out.println("    ch: " + Arrays.toString(ch) );
        // System.out.println("    ch: " + ch);
        // System.out.println("    start: " + start);
        // System.out.println("    length: " + length);

        // 取出標簽名
        String tag = stack.peek();

        if ("title".equals(tag))
        {
            title = new String(ch, start, length);

        }
        else if ("author".equals(tag))
        {
            author = new String(ch, start, length);
        }
        else if ("year".equals(tag))
        {
            year = new String(ch, start, length);
        }
        else if ("price".equals(tag))
        {
            price = Double.parseDouble(new String(ch, start, length));
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException
    {
        // System.out.println("end element-----------");
        //
        // System.out.println("    localName: " + localName);
        // System.out.println("    qName: " + qName);

        stack.pop();// 表示該元素解析完畢,需要從棧中彈出標簽

        if ("book".equals(qName))
        {
            System.out.println("Book info: -------");
            System.out.println("    title: " + title);
            System.out.println("    author: " + author);
            System.out.println("    year: " + year);
            System.out.println("    price: " + price);
            System.out.println();
        }

    }
}
SaxTest2

  SaxTest2程序輸出:

start document -> parse begin
屬性: category=children
屬性: lang=en
Book info: -------
    title: Harry Potter
    author: J K. Rowling
    year: 2005
    price: 29.99

屬性: category=cooking
屬性: lang=en
Book info: -------
    title: Everyday Italian
    author: Giada De Laurentiis
    year: 2005
    price: 30.0

屬性: category=web
屬性: lang=en
Book info: -------
    title: Learning XML
    author: Erik T. Ray
    year: 2003
    price: 39.95

屬性: category=web
屬性: lang=en
Book info: -------
    title: XQuery Kick Start
    author: Vaidyanathan Nagarajan
    year: 2003
    price: 49.99

end document -> parse finished
Console output

 

參考資料

  聖思園張龍老師XML教學視頻。

  Java API文檔:http://docs.oracle.com/javase/7/docs/api/index.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM