越來越多的應用程式使用XML交換訊息。譬如,以 CLDC 為基礎的應用程式 需要去處理 XML 文件,甚至連 HTML 網頁也將會很有可能轉換成為一個以 XML 為基礎的格式。而這意味著從一個網頁伺服器連結一張網頁而取出資料將會需要分析 XML 的技術。
安裝軟體
J2ME Wireless Toolkit 1.0.4 及中文化版本
Apache Tomcat
XML就是「可擴展標記語言」,是一種輕便的、以文字為基礎的方法去呈現結構化的資料。
越來越多的應用程式使用 XML 交換訊息,甚且,在一些情況下,您以 CLDC 為基礎的應用程式 (這些是指在以 CLDC 為基礎的架構上執行的,像是微小的手機裝置之類的) 需要去處理 XML 文件。之後,甚至連 HTML 網頁也將會很有可能轉換成為一個以 XML 為基礎的格式,稱為 XHTML。這意味著從一個網頁伺服器連結一張網頁而取出資料將會需要分析 XML 的技術。
A multi-tier architecture with XML
尋找一個以 JAVA 為基礎的 XML 分析器不難,尤其是自從有好幾個以 XML 為基礎的的提倡開始被定義為 Java 處理程序的一部分。然而,大部分的 XML 分析器並不支援在 CLDC 所提供的有限資源環境下運作。這些分析器不是使用了太多的記憶體就是使用在 CLDC 下不能運作的 J2SE 類別。
然而,在這有兩個能在 CLDC 環境下運作的開放原始碼 XML 分析器 ── kXML 和 NanoXML。他們二者的長處有些不同 ── 本文將會討論他們兩者,並且提供您如何去決定哪一個是最適合您的程式需求。然而,您也應該考慮是否選擇 XML,因為 XML 文件是非常冗長的。
如果一個以 Java 為基礎的客戶端與一個以 Java 為基礎的伺服器端相互溝通,這是相當容易的。在這個實例裡,使用 DataInputStream 和 DataOutputStream 類別,以輕便的方法讀寫取資料。
基本的 XML 分析器型態有兩種:確認性的和非確認性的。
一個確認性的分析器透過一個文件型別定義或概要 (schema) 確認一份 XML 文件,以確保這份文件的內容是程式所預期的。這個要求將會減低處理的速度。一個非確認性的分析器跳過這個步驟,只保證這個 XML 文件是合乎基本格式的 (well-formed),換而言之,它遵守一般 XML 文件必須遵守的規則。kXML 和 NanoXML 二者都是非確認性的分析器。
非確認性的分析器
XML 分析器也能以他們如何處理和呈現 XML 文件來區分。
1.modelparser: 將整份文件讀入記憶體進行處理. Model parsers會比其他Parser需要更多記憶體(DOM API )
2.pushparser : 讀取整份文件,當遇到特殊標籤時進行處理 ( SAX API )
3.pullparser :一次讀取部分文件進行解析. 這適合連線速度不快的環境 ( KXML API)
NanoXML屬於model 型態,是一個單一步驟 (single-step) 分析器。給定一份文件,NanoXML 以一個單一的運作分析它,並將這份文件以一個樹狀的結構傳回。kXML屬於pull型態,是一個多步驟的 (multi-step) 的分析器 ── 一次分析文件的一塊區域。
這兩種方法各有利弊,如果您正在處理一份龐大的文件,單一步驟的方法使用較多的記憶體,因為全部的文件都儲存在記憶體中。如果您需要穿越這份文件很多次,單一步驟的方法將較有效率。多步驟的方法能夠較輕易的處理龐大的文件,但是您必須做較多的簿記 (bookkeeping) 去追蹤您在文件的哪一個地方。
■ 該如何使用 kXML 呢?
從 http://www.kxml.org/ 下載 kXML 原始碼,並且將 kXML 類別包含進您的應用程式。並不是所有的類別都是需要的,所以只要下載包含最小 kXML 的 ZIP 檔。將ZIP或Jar檔放在J2MEWTK Project 的lib目錄下, 在安裝完這個檔案後,新增下面的引入陳述到您的程式中。
package xml; import java.io.*; import java.util.Vector;
import org.kxml2.io.*; import org.xmlpull.v1.*;
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import javax.microedition.io.*;
/** * J2ME:读取http://www.newsforge.com/newsforge.xml的新闻列表 */ public class Newsreader extends MIDlet implements CommandListener {
static final String URL = "http://www.newsforge.com/newsforge.xml"; static final String TITLE = "NewsForge";
Vector descriptions = new Vector(); List newsList = new List(TITLE, Choice.IMPLICIT); TextBox textBox = new TextBox("", "", 256, TextField.ANY); Display display;
Command backCmd = new Command("Back", Command.BACK, 0);
/** * 启动读取线程 */ class ReadThread extends Thread {
public void run() { try { HttpConnection httpConnection = (HttpConnection) Connector.open(URL);
KXmlParser parser = new KXmlParser();
parser.setInput(new InputStreamReader(httpConnection.openInputStream()));
// parser.relaxed = true;
parser.nextTag(); parser.require(XmlPullParser.START_TAG, null, "backslash");
while (parser.nextTag () != XmlPullParser.END_TAG) readStory(parser);
parser.require(XmlPullParser.END_TAG, null, "backslash"); parser.next();
parser.require(XmlPullParser.END_DOCUMENT, null, null); } catch (Exception e) { e.printStackTrace(); descriptions.addElement(e.toString()); newsList.append("Error", null); } }
/** * 读取故事并将其添加到列表中 * @param parser kxml解析器 */
void readStory(KXmlParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, null, "story");
String title = null; String description = null;
while (parser.nextTag() != XmlPullParser.END_TAG) {
parser.require(XmlPullParser.START_TAG, null, null); String name = parser.getName();
String text = parser.nextText();
System.out.println ("<"+name+">"+text);
if (name.equals("title")) title = text; else if (name.equals("description")) description = text;
parser.require(XmlPullParser.END_TAG, null, name); } parser.require(XmlPullParser.END_TAG, null, "story");
if (title != null) { descriptions.addElement(""+description); newsList.append(title, null); } } }
public void startApp() { display = Display.getDisplay(this); display.setCurrent(newsList); newsList.setCommandListener(this); textBox.setCommandListener(this); textBox.addCommand(backCmd); new ReadThread().start(); }
public void pauseApp() { }
public void commandAction(Command c, Displayable d) {
if (c == List.SELECT_COMMAND) {
String text = (String) descriptions.elementAt(newsList.getSelectedIndex());
if (textBox.getMaxSize() < text.length()) textBox.setMaxSize(text.length());
textBox.setString(text); display.setCurrent(textBox); } else if (c == backCmd) display.setCurrent(newsList); }
public void destroyApp(boolean really) { }
} |
文章摘自:www.ibm.com