Thứ Tư, 29 tháng 5, 2013

Hướng dẫn Dùng SAX đọc XML trong Java

Làm việc với SAX

SAX là viết tắt của Simple API for XML, gồm có 2 interface chính: XMLReader là interface dùng để đọc XML và ContentHandler dùng để nhận  dữ liệu từ XML. Hai interface này giải quyết 90% nhu cầu của người dùng với SAX. Trong bài này chúng ta sẽ tìm hiểu về 2 interface này.

           I.      Sơ luợc về SAX:

Simple API for XMLSAX, được phát minh vào cuối năm 1998 khi Peter, Murray-Rust và một số tác giả phân tích cú pháp XML được viết bằng Java nhận ra rằng sẽ không hợp lý khi dùng quá nhiều các bộ API khác nhau cho chung 1 mục đích là đọc XML . Murray-Rust là người đầu tiên đề xuất những gì ông gọi là "YAXPAPI". Lý do Murray-Rust muốn đặt tên là Yet Another XML Parser API đã vì  ông đã hoàn toàn bị mệt mỏi vì phải dùng nhiều hàm API phân tích cú pháp XML cho ứng dụng JUMBO. Thay vào đó, ông muốn có một API chuẩn tất cả mọi người có thể đồng ý. Sau một thời gian ngắn beta SAX 1.0 được phát hành vào ngày 11 tháng năm 1998.

      II.      Ưu điểm của SAX:

-         Đơn giản

-         Sử dụng ít bộ nhớ

-         Tốc độ xử lý nhanh

-         Tập trung vào dữ liệu hiện hành

-         Dễ sử dụng để lọc dữ liệu

-         Tuy nhiên SAX có các nhược điểm sau:

-         Không thể tác động lên dữ liệu XML

-         Chế độ lưu trữ trạng thái phức tạp

-         Khó khăn khi phân tích cấu trúc XML lớn

  III.      Các khái niệm dùng trong SAX

1.     Parsing:

Parsing là quá trình đọc file XML và lấy dữ liệu của XML đưa vào chương trình đồng thời check lỗi cú pháp của XML

2.     Callback Interface:

SAX sử dụng các đối tượng Observer để đọc dữ liệu trong file XML. Lập trình viên JAVA đã quen thuộc với kiến trúc lập trình theo sự kiện của AWT và Swing. Ví dụ như khi chúng ta viết 1 class thực thi từ interfaceMouseListener, class này sẽ mặc nhiên có các sự kiện của interface này. Sau đó chúng ta đăng ký class này vào cho 1 object ví dụ như là button, button này có thể nhận các sự kiện liên quan đến thao tác của con trỏ. SAX cũng hoạt động theo cấu trúc đó. Tuy nhiên điểm khác biệt lớn nhất giữa Swing và SAX là SAXkhông cho phép gắn nhiều hơn 1 sự kiện cho cùng 1 object

 


3.     Các hàm được định nghĩa trong interface ContentHandler:
public interface ContentHandler {
 
  public void setDocumentLocator(Locator locator);
  public void startDocument() throws SAXException;
  public void endDocument() throws SAXException;
  public void startPrefixMapping(String prefix, String uri)
   throws SAXException;
  public void endPrefixMapping(String prefix)
   throws SAXException;
  public void startElement(String namespaceURI, String localName,
   String qualifiedName, Attributes atts) throws SAXException;
  public void endElement(String namespaceURI, String localName,
   String qualifiedName) throws SAXException;
  public void characters(char[] text, int start, int length)
   throws SAXException;
  public void ignorableWhitespace(char[] text, int start,
   int length) throws SAXException;
  public void processingInstruction(String target, String data)
   throws SAXException;
  public void skippedEntity(String name)
   throws SAXException;
 
}

    IV.      Ví dụ về SAX:

Trong ví dụ bài này tôi sẽ trình bày các đọc thông tin từ file XML đưa vào JavaBean và hiển thị theo danh sách

Trước hết chúng ta có file XML có nội dung sau:

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

<thuVien>

    <sach>

        <tenSach>Jindo</tenSach>

        <NXB>NXB tre</NXB>

        <gia>14000</gia>

    </sach>

    <sach>

        <tenSach>Conan</tenSach>

        <NXB>NXB Kim Dong</NXB>

        <gia>14000</gia>

    </sach>

    <sach>

        <tenSach>7 vien ngoc rong</tenSach>

        <NXB>NXB Kim Dong</NXB>

        <gia>10000</gia>

    </sach>

</thuVien>

- Tạo Myelement:

import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
*
* @author Administrator
*/
class MyElement {
private String qname;//ID
private String value;//giá trị vủa node
private ArrayList<String>attributes;//lưu giữ các thuộc tính của node
private String uri;
private String localName;
private Attributes attribute;

MyElement(String uri, String localName, String qName, Attributes attributes) {
super();
this.uri = uri;
this.localName = localName;
this.qname = qName;
this.attribute = attributes;
}

public String getqName() {
return qname;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {

}
}

Để lưu dữ liệu chúng ta xây dựng 1 JavaBean Sach.java với nội dung sau:

public class Sach {

    private String tenSach;

    private String nxb;

    private int gia;

    public Sach() {

    }

    public Sach(String tenSach, String nxb, int gia) {

        this.tenSach= tenSach;

        this.nxb=nxb;

        this.gia=gia;

    }

    /**

     * @return the tenSach

     */

    public String getTenSach() {

        return tenSach;

    }

    /**

     * @param tenSach the tenSach to set

     */

    public void setTenSach(String tenSach) {

        this.tenSach = tenSach;

    }

    /**

     * @return the nxb

     */

    public String getNxb() {

        return nxb;

    }

    /**

     * @param nxb the nxb to set

     */

    public void setNxb(String nxb) {

        this.nxb = nxb;

    }

    /**

     * @return the gia

     */

    public int getGia() {

        return gia;

    }

    /**

     * @param gia the gia to set

     */

    public void setGia(int gia) {

        this.gia = gia;

    }

}

Class này có công dụng tạo 1 Object lưu trữ thông tin của 1 thẻ trong XML. Bước tiếp theo chúng ta tạo 1 class, class này sẽ tạo 1 SAX đọc file XML, từng 1 thẻ trong XML sẽ được lưu trữ vào 1 object MyElement và add vào list:

import BeanThongTin.MyElement;

import BeanThongTin.Sach;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.util.ArrayList;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;

import org.xml.sax.InputSource;

import org.xml.sax.SAXException;

import org.xml.sax.XMLReader;

import org.xml.sax.helpers.DefaultHandler;

public class docXMLBangSax extends DefaultHandler{

    public static ArrayList<MyElement> listElement= new ArrayList<MyElement>();

    public static ArrayList<Sach> listSach= new ArrayList<Sach>();

    public static void main(String[] args) throws ParserConfigurationException, SAXException, FileNotFoundException, IOException {

        // Tạo SAX Factory

        SAXParserFactory spf = SAXParserFactory.newInstance();

        // Không validate file XML

        spf.setValidating(false);

        // Tạo SAX Parser

        SAXParser saxParser = spf.newSAXParser();

        // Tạo XML reader

        XMLReader reader = saxParser.getXMLReader();

        FileReader file = new FileReader("thuVien.xml");

        // Gắn handle của lớp hiện hành vào reader

        reader.setContentHandler(new docXMLBangSax());

        // đọc XML

        reader.parse(new InputSource(file));

        // Sau khi đọc file XML chúng ta sẽ có listElement cùng với giá trị

        // Sau đó chúng ta sẽ lọc listElement tạo ra các object Sach

        Sach sach= new Sach();

        for (MyElement e: listElement) {

            // nếu là element sach thi tạo object Sach mới

            if (e.getqName().equalsIgnoreCase("sach")) sach= new Sach();

            else if (e.getqName().equalsIgnoreCase("tensach")) sach.setTenSach(e.getValue());

            else if (e.getqName().equalsIgnoreCase("nxb")) sach.setNxb(e.getValue());

            else if (e.getqName().equalsIgnoreCase("gia")) {

                sach.setGia(Integer.parseInt(e.getValue()));

                listSach.add(sach);

            }

        }

        // Vòng lặp in listSach để kiểm tra

        for (Sach s : listSach) {

            System.out.println("Ten sach:"+s.getTenSach()+"; NXB:"+s.getNxb()+"; Gia:"+s.getGia());

        }

    }

    @Override

    public void startElement(String uri, String localName,

            String qName, Attributes attributes) throws SAXException {

        MyElement e= new MyElement(uri, localName, qName, attributes);

        listElement.add(e);

    }

    @Override

    public void characters(char[] ch, int start, int length) throws SAXException {

        String s= new String(ch, start, length);

        s.trim();

        if (s.startsWith("\n") || s.startsWith("\t")) return;

        listElement.get(listElement.size()-1).setValue(s);

    }

}

Kết quả thu được:

 

0 nhận xét:

Đăng nhận xét