XML的JAVA 解析(一)(2) (轉)

gugu99發表於2008-04-26
XML的JAVA 解析(一)(2) (轉)[@more@]

Hello world
現在我們明白了基本的SAX原理,我們可以著手做一點稍微有用的:從我們的樣本文件中解析出值來,實現經典的hello world。microsoft-com::office" />

首先,將每個感興趣的元素印射到,我們在startElement 事件處重置我們的資料快取。然後,當startElement已經發生,而endElement事件還沒有時,我們把characters事件對應的所有字元收集起來。最後,到endElement事件出現時,我們將收集到的字元儲存到一個Java的對應屬性中。

以下是我們的hello world例子所用到的樣本資料:




  Bob
  New York

還有例子的XML解析程式碼清單:


import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.io.*;


public class Example2 extends DefaultHandler {

  // 用於儲存尋獲資料的本地變數
  public String name  = "";
  public String location  = "";

  // 用於收集來自”characters” SAX事件的資料的快取。
  private CharArrayWriter contents = new CharArrayWriter();



  // 過載DefaultHandler類以攔截SAX事件的方法。
  //
 // 頭於所有有效事件的詳細內容,參見org.xml.sax.ContentHandler。
  //

  public void startElement( String namespaceURI,
 String localName,
 String qName,
 Attributes attr ) throws SAXException {

 contents.reset();

  }

  public void endElement( String namespaceURI,
 String localName,
 String qName ) throws SAXException {

 if ( localName.equals( "name" ) ) {
  name = contents.toString();
 }

 if ( localName.equals( "location" ) ) {
  location = contents.toString();
 }

  }


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

 contents.write( ch, start, length );

  }



  public static void main( String[] argv ){

 System.out.println( "Example2:" );
 try {

  // 建立SAX 2解析器...
  XMLReader xr = XMLReaderFactory.createXMLReader();

  // ContentHandler...
  Example2 ex2 = new Example2();
  xr.setContentHandler( ex2 );

  // 解析...
  xr.parse( new Input(
  new FileReader( "Example2.xml" )) );

  // Say hello...
  System.out.println( "Hello World from " + ex2.name
 + " in " + ex2.location );

 }catch ( Exception e ) {
  e.printStackTrace();
 }


  }

}

我們的hello world例子輸出如下:


Example2:
Hello World from Bob in New York

這並非所有hello world程式中最簡單的一個。同樣,在這個例子程式碼中有幾處並不完美。

第一,這個程式碼顯示了事件的程式碼的一些不足。當事件驅動的程式不是要對一個事件而是要對一類事件做出響應時,事情就很棘手了。以上述程式碼為例,我們在尋找以名字及在XML樣本文件中出現的位置為標誌的一類事件。

標籤內的內容出現於characters SAX事件中;標籤本身則位於startElement和endElement事件之間。我利用在startElement中不斷清空的contents快取來處理它們。結束標籤的出現意味著資料以被收集,將它儲存到正確的本地變數中。這本身不錯,但是它卻假定了沒有兩個Java物件使用的是同樣的標籤——這個假設不總是對的。我們稍後要處理這個問題。

這個例程另一個有意思的特點是contents快取的使用——一個SAX小竅門。你也可以直接在characters SAX事件中建立一個字串以取代這種將字元複製進快取的辦法。但這也意味著忽視有關characters()的SAX文件中指出的XML解析器可能多次characters()方法這一事實。這可能導致收集資料時遇到兩個標籤之間資料過大或輸入到XML解析器的流快取在兩個標籤之間斷開而引起資料丟失。此外重用一個快取比起不斷建立新的物件要高效得多。

建立我們的第一個Java物件對映
現在我們以經做完了hello world,讓我們來試一個更加有用的將一個XML文件印射到Java物件的例子。這個例子與hello world相似,但是還要將資料對映到一個物件中並且有一個呼叫者——這是在以後的例子中很常用的模型。不向構造和Factory方法,在解析結束前SAX解析器中的物件都是無效的。對於這點異樣,一個乾淨利索的辦法是在進行對映物件的物件中為已被成功對映出來的物件建立一個訪問控制方法(譯註:亦即作為一個欄位)。如此,你就建立進行對映的類,賦給它一個XMLReader,解析XML,然後呼叫訪問控制方法獲取對映到的物件的引用。一個替代方案是提供一個set方法,在解析之前就將待解析的容納資料的物件賦給進行解析的物件。

先看一下例三的XML樣本文件:




  Bob
  Hustead
  abc.123

接下來,我們看一個將被來自我們的XML文件的資料對映出來的簡單類:


package common;

import java.io.*;

// Customer是一個包含一名虛擬顧客的屬性的簡單類。
// 它有一個簡單的方法把自已列印到一個列印流。

public class Customer {

  // Customer成員變數
  public String firstName = "";
  public String lastName = "";
  public String custId = "";

 public void print( PrintStream out ) {
 out.println( "Customer: " );
 out.println( " First Name -> " + firstName );
 out.println( " Last Name -> "  + lastName );
 out.println( " Customer Id -> " + custId );
  }

}

這是例三中進行解析的類的程式碼:


import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.io.*;
import common.*;

public class Example3 extends DefaultHandler {


  // 用於收集customer的XML資料的本地Customer變數
  private Customer cust = new Customer();

  // 用於從"characters" SAX事件中收集資料的快取。
  private CharArrayWriter contents = new CharArrayWriter();



 // 過載DefaultHandler類以攔截SAX事件的方法。
  //
 // 頭於所有有效事件的詳細內容,參見org.xml.sax.ContentHandler。
  //

  public void startElement( String namespaceURI,
 String localName,
 String qName,
 Attributes attr ) throws SAXException {


 contents.reset();

  }


  public void endElement( String namespaceURI,
 String localName,
 String qName ) throws SAXException {

  if ( localName.equals( "FirstName" ) ) {
 cust.firstName = contents.toString();
 }

 if ( localName.equals( "LastName" ) ) {
  cust.lastName = contents.toString();
 }

 if ( localName.equals( "CustId" ) ) {
  cust.custId = contents.toString();
 }


  }

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

 contents.write( ch, start, length );

  }


  public Customer getCustomer() {
  return cust;
  }



  public static void main( String[] argv ){

 System.out.println( "Example3:" );
 try {

  // 建立SAX 2解析器...
  XMLReader xr = XMLReaderFactory.createXMLReader();

  // 安裝ContentHandler...
  Example3 ex3 = new Example3();
  xr.setContentHandler( ex3 );

  // 解析檔案...
  xr.parse( new InputSource(
  new FileReader( "Example3.xml" )) );

  // 將customer顯示到標準輸出...
  Customer cust = ex3.getCustomer();
  cust.print( System.out );

 }catch ( Exception e ) {
  e.printStackTrace();
 }


  }

}

以下是我們的Customer物件產生的輸出,顯示出來自我們的XML文件的資料:


Example3:
Customer:
 First Name -> Bob
 Last Name -> Hustead
 Customer Id -> abc.123

 

(未完待續)


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1003022/,如需轉載,請註明出處,否則將追究法律責任。

相關文章