XML的JAVA 解析(一)(2) (轉)
Hello world
現在我們明白了基本的SAX原理,我們可以著手做一點稍微有用的:從我們的樣本文件中解析出值來,實現經典的hello world。microsoft-com::office" />
首先,將每個感興趣的元素印射到,我們在startElement 事件處重置我們的資料快取。然後,當startElement已經發生,而endElement事件還沒有時,我們把characters事件對應的所有字元收集起來。最後,到endElement事件出現時,我們將收集到的字元儲存到一個Java的對應屬性中。
以下是我們的hello world例子所用到的樣本資料:
還有例子的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樣本文件:
接下來,我們看一個將被來自我們的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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java解析XMLJavaXML
- 使用 Java 解析XML檔案JavaXML
- Java 將HTML轉為XMLJavaHTMLXML
- java的XML解析(DOM4J技術)JavaXML
- NPM酷庫051:xml2js,解析XML格式資料NPMXMLJS
- java 物件與xml相互轉換Java物件XML
- Xml解析XML
- Java學習--xml文字轉換成Java物件JavaXML物件
- java使用jaxb解析XML(含根據xml自動生成實體類)JavaXML
- go 解析xmlGoXML
- iOS – XML解析iOSXML
- DOM4J 解析 XML 之忽略轉義字元XML字元
- XML解析-最快的方式SAXXML
- Java設計模式模式 (包括工廠模式xml解析)Java設計模式XML
- java EE開發之Servlet第五課:xml解析JavaServletXML
- Java 解析xml報文放入Map,並判斷所有xml標籤是否為空JavaXML
- PHP xml 轉陣列 陣列轉 xml 操作PHPXML陣列
- python之XML解析PythonXML
- 175.XML解析XML
- C# XML解析C#XML
- Java XML和JSON:Java SE的文件處理 第2部分JavaXMLJSON
- Java中將XML轉換為PDF的兩種辦法JavaXML
- java bug2:settings.xml has syntax errorsJavaXMLError
- Spring原始碼分析(一)Spring的初始化和XML解析Spring原始碼XML
- Python XML解析之DOMPythonXML
- python XML 檔案解析PythonXML
- jdom解析xml檔案XML
- XML 檔案解析實踐 (DOM 解析)XML
- 【Java】Word題庫解析2Java
- Java Spring Beans.xml裡的Bean定義是如何被解析出來的JavaSpringBeanXML
- Android逆向(一) —— AndroidManifest.xml 二進位制解析AndroidXML
- Windows10 VS2017 C++ xml解析(tinyxml2庫)WindowsC++XML
- 使用DocumentBuilderFactory解析XML淺談UIXML
- XML DOM 解析器概述XML
- 基於 DOM 的 XML 檔案解析類XML
- xml字串轉JSON字串XML字串JSON
- C# 操作xml(轉)C#XML
- Java解析xml檔案遇到特殊符號&會出現異常的解決方案JavaXML符號
- namespace對axis解析xml請求的影響namespaceXML