熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Javascript >> 正文

JSP與XML的結合

2013-11-23 17:54:01  來源: Javascript 
綜述可擴展標注語言(eXtensible Markup LanguageXML)正被迅速的運用於業界它已作為與平台語言和協議無關的格式描述和交換數據的廣泛應用標准XML和它的輔助規范可用於描述數據的文檔表現描述XML文檔類型的限制描述XML文檔和資源之間的鏈接描述XML文檔的自動轉換和格式化

  如何開發自定義標簽庫?

  我使用JSP和ASP編程已經有一段頗長的時間了在兩種服務器端的編程方式中我越來越覺得JSP的功能要強大得多不提別的其中JSP的標簽庫就是我選擇JSP作為首選服務器端Web應用開發工具的原因為什麼?因為維護和開發的速度在一個單一的服務器頁面中你可以混合使用各種不同的腳本方法和對象就?quot;混凝土一樣這種混合可令服務器端的腳本變得強大並且讓服務器端的編程者設計出非常靈活和動態的Web頁面不過這種自由的混合也有其缺點那就是維護起來非常麻煩特別是當項目逐漸變大時由於最終的產品是經由一個傳統的Web設計者來維護的因此會帶來問題更糟糕的是隨著代碼的復雜性增加開發的速度就會變慢不利於開發中等和大型的Web應用一旦開發完站點還要找合格的編程者來維護這些頗為復雜的代碼
幸好JSP提供了一個很好解決的辦法標簽庫提供了一個簡單的方法來建立一個可重用的代碼塊一旦標簽庫設計好它就可以在許多項目中再次使用更方便的是與COM和JEE不同你無需學習任何其它的技巧就可以建立一個標簽庫!只要你懂得寫JSP你就可以建立一個標簽庫標簽庫還可以改善Web應用的維護這個是得益於JSP頁面自定義標簽的簡單XML接口這樣Web設計者甚至可以做到無需知道任何JSP的知識就可以建立JSP的Web應用這個開放式的Web開發對於團隊運作是非常有效的JSP編程者可以建立自定義的標簽和後台的代碼模塊而Web設計者可以使用自定義的標簽來建立Web應用並且將精力集中在Web設計上

   標簽庫的定義
  JSP標簽庫(也稱自定義庫)可看成是一套產生基於XML腳本的方法它經由JavaBeans來支持在概念上說標簽庫是非常簡單和可以重用的代碼構造
  執行XML/XSL轉換的標簽范例和HTML頁面

<%@ taglib uri=/jspkit/JAXP prefix=JAXP%>
c:/xml/examplexml
c:/xml/examplexsl
  在這個例子中通過使用簡單的標簽來訪問後台更為強大的代碼一個XML被裝載並且通過一個XSL文件來產生一個結果並發送給客戶端全部通過使用一個簡單的標簽調用就做到了
  自定義標簽為在JSP項目中創建易於重用的代碼打開了一扇大門你所需要的只是標簽庫和它的文檔說明

   標簽的組件
  雖然標簽庫非常易於使用不過要建立一個內裡的設計來支持標簽庫是頗復雜的起碼要比建立一個簡單的JavaBean復雜這個復雜是來自於標簽庫是由幾部分構成的不過你只需要知道Java和JSP的知識就夠了
一個簡單的標簽由下面的元素構成
  ⑴ JavaBeans為了得到Java與生具來的面向對象的好處可重用的代碼應該放到一個獨立的代碼容器中這些JavaBeans並不是標簽庫的一部分不過它是你的代碼庫用來執行相關任務的基本代碼塊
  ⑵ 標簽處理這是標簽庫的真正核心一個標簽處理器將引用它需要的任何資源(你的JavaBeans)和訪問你的JSP頁面的全部信息(pageContext對象)JSP頁面也會將所有已經被設置的標簽屬性和JSP頁面上的標簽體中的內容傳送給標簽處理器在標簽處理器處理完畢後它將發回輸出到你的JSP頁面進行處理
  ⑶ 標簽庫的描述(tld文件)這是一個簡單的XML文件它記錄著標簽處理器的屬性信息和位置JSP容器通過這個文件來得知從哪裡及如何調用一個標簽庫
  ⑷ 網站的webxml文件這是你網站的初始化文件在這個文件中你定義了網站中用到的自定義標簽以及哪個tld文件用來描述每個自定義的標簽
  ⑸ 分發文件(一個WAR或者JAR文件)如果你想重用自定義標簽的話你需要一個方法來將它由一個項目轉移到另一個項目中將標簽庫打包為一個JAR文件是一個簡單而且有效的方式
  ⑹ 在你的JSP文件中作標簽庫聲明很簡單如果要用到該標簽的話只要在頁面聲明一下就可以其後你就可以在該JSP頁面的任何地方使用它
  看來要做的工作很多不過其實並不是很難它的要點並不在於編碼而是在於如何將各部分正確地組織起來不過這樣的分層是很重要的它可令標簽的使用靈活和更容易轉移更重要的是這些層的存在可讓處理建立標簽的工程通過一個JSP IDE(JSP的集成開發環境)自動完成期望將來的JSP IDE可自動完成創建一個自定義標簽的大部分工作這樣你只需要寫代碼和標簽處理就可以了
  注意一個標簽處理僅定義一個自定義標簽一個標簽庫是幾個處理相同任務的標簽處理器的集合

   建立自己的標簽
  以下將一步一步地教你如何建立自定義的標簽具體的例子是擴展JSP令它擁有自己的HTML編碼功能這個功能將所有的<和>字符用HTML代碼來代替它可以很容易地擴展為做其它的編碼處理為了簡化這個例子只解釋了建立自定義標簽的基本要素
  ⑴ 創建一個JavaBean
  你代碼中任何可重新使用的部分都應該放到一個JavaBean中這個很重要因為你要經常在項目的其它地方用到這些代碼放在標簽處理器中的任何代碼在標簽外都是不可以重新使用的因此將可重用的代碼部分獨立開來是很重要的在這個例子總為HTML編碼的邏輯是常用的因此放到JavaBean中
  ⑵ HTML編碼JavaBean

/* HTML_FormatJava */
public class HTML_Format extends Object implements JavaioSerializable {
/** 創建新的HTML_Format */
public HTML_Format() {}
/** 將一個字符串中所有的所有 < 和 > 字符用響應的HTML編碼代替 */
public String HTML_Encode(String as_data)
{
int li_len = as_datalength();
/*string buffer的長度要比原來的字符串長*/
StringBuffer lsb_encode = new StringBuffer(li_len + (li_len/));
/* 循環替換全部的< 和 > 字符 */
for( int li_count = ; li_count < li_len ; li_count++)
{ String ls_next = StringvalueOf(as_datacharAt(li_count));
if (ls_nextequals()) ls_next = ;
if (ls_nextequals()) ls_next = ;
lsb_encodeappend( ls_next );
}
return( lsb_encodetoString() );
}
}
  ⑶ 創建一個標簽處理器
  標簽處理器使用以下的代碼

HTML編碼標簽處理器
import JavaioIOException;
import Javaxservletjsp*;
import Javaxservletjsptagext*;
public class HTML_FormatTag extends BodyTagSupport
{
/* } 在標簽末將會調用這個函數 */
public int doEndTag() throws JspTagException
{
try
{ /* }得到標簽中的文本 */
BodyContent l_tagbody = getBodyContent();
String ls_output = ;
/* }如果標簽體有文本就處理它 */
if(l_tagbody != null)
{ HTML_Format l_format = new HTML_Format();
/* a} 將標簽體的內容轉換為一個字符串 */
String ls_html_text = l_tagbodygetString();
ls_output = l_formatHTML_Encode(ls_html_text);
}
/* }將結果寫回到數據流中 */
pageContextgetOut()write(ls_outputtrim());
}
catch (IOException e)
{ throw new JspTagException(Tag Error: + etoString());
}
/* 讓JSP繼續處理以下頁面的內容 */
return EVAL_PAGE;
}
}
  這個處理很簡單它包括有
  o 讀入標簽開始和結束間的文本
  o 調用html編碼函數
  o 返回結果到JSP頁面
  ⑷ 創建一個標簽描述器
  需要描述自定義標簽以讓系統知道如何處理該描述文件的後綴為tld通常它的名字和標簽處理器相同並存放在/WEBINF/目錄

HTML編碼標簽描述器
<?xml version= encoding=UTF ?>
<!DOCTYPE taglib
PUBLIC //Sun Microsystems Inc//DTD JSP Tag Library //EN
jsptaglibrary__dtd
<TAGLIB>
<TLIBVERSION></TLIBVERSION>
<JSPVERSION></JSPVERSION>
<SHORTNAME>HTML_FormatTag</SHORTNAME>
<URI></URI>
<INFO>HTML Encoding Tag </INFO>
<TAG>
<NAME>HTMLEncode</NAME>
<TAGCLASS>HTML_FormatTag</TAGCLASS>
<INFO>Encode HTML</INFO>
</TAG>
</TAGLIB>
  ⑸ 更新Web XML文件
  現在可告訴JSP容器使用標簽庫為此要修改webxml文件具體說來是要在其中加入一個taglib的項目來注冊該標簽庫最重要的是要為tag分配一個URIURI是一個唯一的引用只應用在該網站的這個特別的標簽上使用全長的URL或者包名是一個好的習慣它可以確保唯一性因為該標簽可以在不同的網站使用這個例子是簡化了

修改webxml文件
<?xml version= encoding=ISO?>

<!DOCTYPE webapp
PUBLIC //Sun Microsystems Inc//DTD Web Application //EN
app_dtd
<WEBAPP>
<TAGLIB>
<TAGLIBURI>
HTMLEncode
</TAGLIBURI>
<TAGLIBLOCATION>
/WEBINF/HTML_FormatTagtld
</TAGLIBLOCATION>
</TAGLIB>
</WEBAPP>
  ⑹ 使用新的標簽
  自定義的標簽已經設置好可以用在一個JSP頁面上要做到這一點只需在該頁面使用taglib指示命令聲明一下該標簽就可以了該標簽通過它唯一的URI被引用並且會被分配一個名字空間前綴前綴可以任意只要它不與其它的名字空間沖突便可
  在一個JSP頁面上使用HTML編碼標簽

<%@ taglib uri=HTMLEncode prefix=Examples %>
<PRE>
<?XML:NAMESPACE PREFIX = Examples /><Examples:HTMLEncode>
< Hello Simple sample >
</Examples:HTMLEncode>
</PRE>
范例代碼的輸出
< Hello Simple sample >
which displays as:
< Hello Simple sample >

  通過這個標簽我就將該頁面的所有代碼編碼了有趣的是所有的自定義標簽都是在服務器上處理的這意味著你將不會在輸出的頁面上看到自定義的標簽
  建立一個標簽不是很難吧最困難的部分是要學習標簽處理的所有細節這是一個很強大的功能我們只是提到了最基本的地方由於這個處理需要幾步新的JSP編程者在創建標簽時將會感到迷惑


如何利用JSP開發DOM應用?

  DOM是Document Object Model的縮寫即文檔對象模型XML將數據組織為一顆樹所以DOM就是對這顆樹的一個對象描敘通俗的說就是通過解析XML文檔為XML文檔在邏輯上建立一個樹模型樹的節點是一個個對象我們通過存取這些對象就能夠存取XML文檔的內容
  下面我們來看一個簡單的例子看看在DOM中我們是如何來操作一個XML文檔的這是一個XML文檔也是我們要操作的對象

   <?xml version= encoding=UTF?>
<messages>
<message>Goodbye serialization hello Java!</message>
</messages>

  下面我們需要把這個文檔的內容解析到一個個的Java對象中去供程序使用利用JAXP我們只需幾行代碼就能做到這一點首先我們需要建立一個解析器工廠以利用這個工廠來獲得一個具體的解析器對象
  DocumentBuilderFactory dbf = DocumentBuilderFactorynewInstance();
  我們在這裡使用DocumentBuilderFacotry的目的是為了創建與具體解析器無關的程序當DocumentBuilderFactory類的靜態方法newInstance()被調用時它根據一個系統變量來決定具體使用哪一個解析器又因為所有的解析器都服從於JAXP所定義的接口所以無論具體使用哪一個解析器代碼都是一樣的所以當在不同的解析器之間進行切換時只需要更改系統變量的值而不用更改任何代碼這就是工廠所帶來的好處
  DocumentBuilder db = dbfnewDocumentBuilder();
  當獲得一個工廠對象後使用它的靜態方法newDocumentBuilder()方法可以獲得一個DocumentBuilder對象這個對象代表了具體的DOM解析器但具體是哪一種解析器微軟的或者IBM的對於程序而言並不重要
  然後我們就可以利用這個解析器來對XML文檔進行解析了
  Document doc = dbparse(c:/xml/messagexml);
  DocumentBuilder的parse()方法接受一個XML文檔名作為輸入參數返回一個Document對象這個Document對象就代表了一個XML文檔的樹模型以後所有的對XML文檔的操作都與解析器無關直接在這個Document對象上進行操作就可以了而具體對Document操作的方法就是由DOM所定義的了
  從得到的Document對象開始我們就可以開始我們的DOM之旅了使用Document對象的getElementsByTagName()方法我們可以得到一個NodeList對象一個Node對象代表了一個XML文檔中的一個標簽元素而NodeList對象觀其名而知其意所代表的是一個Node對象的列表
  NodeList nl = docgetElementsByTagName(message);
  我們通過這樣一條語句所得到的是XML文檔中所有<message>標簽對應的Node對象的
  一個列表然後我們可以使用NodeList對象的item()方法來得到列表中的每一個Node對象
  Node my_node = em();
  當一個Node對象被建立之後保存在XML文檔中的數據就被提取出來並封裝在這個Node中了在這個例子中要提取Message標簽內的內容我們通常會使用Node對象的getNodeValue()方法
String message = my_nodegetFirstChild()getNodeValue();
  請注意這裡還使用了一個getFirstChild()方法來獲得message下面的第一個子Node對象雖然在message標簽下面除了文本外並沒有其它子標簽或者屬性但是我們堅持在這裡使用getFirseChild()方法這主要和WC對DOM的定義有關WC把標簽內的文本部分也定義成一個Node所以先要得到代表文本的那個Node我們才能夠使用getNodeValue()來獲取文本的內容現在既然我們已經能夠從XML文件中提取出數據了我們就可以把這些數據用在合適的地方來構築應用程序

  DOM實例

  先說說這個例子到底要做的是什麼吧我們在一個名為linkxml文件中保存了一些URL地址我們希望可以通過DOM把這些URL讀出並顯示出來也可以反過來向這個XML文件中寫入加入的URL地址很簡單卻很實用也足夠來例示DOM的絕大部分用法了
  第一個程序我們稱為xmldisplayJava主要的功能就是讀取這個XML文件中各個節點的內容然後在格式化輸出在Systemout上我們來看看這個程序

   import Javaxxmlparsers*;
import orgwcdom*;

  這是引入必要的類因為在這裡使用的是Sun所提供的XML解析器因而需要引入Javaxmlparsers包其中包含了有DOM解析器和SAX解析器的具體實現orgwcdom包中定義了wc所制定的DOM接口

DocumentBuilderFactory factory = DocumentBuilderFactorynewInstance();
DocumentBuilder builder=factorynewDocumentBuilder();
Document doc=builderparse(linksxml);
docnormalize();

    

  除了上面講到的還有一個小技巧對Document對象調用normalize()可以去掉XML文檔中作為格式化內容的空白而映射在DOM樹中的不必要的Text Node對象否則你得到的DOM樹可能並不如你所想象的那樣特別是在輸出的時候這個normalize()更為有用

     NodeList links =docgetElementsByTagName(link);

  剛才說過XML文檔中的空白符也會被作為對象映射在DOM樹中因而直接調用Node方法的getChildNodes方法有時候會有些問題有時不能夠返回所期望的NodeList對象解決的辦法是使用Element的getElementByTagName(String)返回的NodeLise就是所期待的對象了然後可以用item()方法提取想要的元素

   for (int i=;i<linksgetLength();i++){
Element link=(Element) em(i);
Systemoutprint(Content: );
Systemoutprintln(linkgetElementsByTagName(textem()getFirstChild();
getNodeValue());
……

  上面的代碼片斷就完成了對XML文檔內容的格式化輸出只要注意到一些細節的問題比如getFirstChile()方法和getElementsByTagName()方法的使用這些還是比較容易的
  下面的內容就是在修改了DOM樹後重新寫入到XML文檔中去的問題了這個程序名為xmlwriteJava在JAXP版本中並沒有直接的類和方法能夠處理XML文檔的寫入問題需要借助其它包中的一些輔助類而在JAXP版本中引入了對XSLT的支持所謂XSLT就是對XML文檔進行變換(Translation)後得到一個新的文檔結構利用這個新加入的功能我們就能夠很方便的把新生成或者修改後的DOM樹從新寫回到XML文件中去了下面我們來看看代碼的實現這段代碼的主要功能是向linksxml文件中加入一個新的link節點

   import Javaxxmlparsers*;
import Javaxxmltransform*;
import JavaxxmltransformdomDOMSource;
import JavaxxmltransformstreamStreamResult;
import orgwcdom*;

  新引入的Javaxmltransform包中的幾個類就是用來處理XSLT變換的
我們希望在上面的XML文件中加入一個新的link節點因而首先還是要讀入linksxml文件構建一個DOM樹然後再對這個DOM樹進行修改(添加節點)最後把修改後的DOM寫回到linksxml文件中

   DocumentBuilderFactory factory = DocumentBuilderFactorynewInstance();
DocumentBuilder builder=factorynewDocumentBuilder();
Document doc=builderparse(linksxml);
docnormalize();
//取得變量
String text=Hanzhongs Homepage;
String url=;
String author=Hzliu Liu;
String discription=A site from Hanzhong Liu give u lots of suprise!!!;

  為了看清重點簡化程序我們把要加入的內容硬編碼到記憶String對象中而實際操作中往往利用一個界面來提取用戶輸入或者通過JDBC從數據庫中提取想要的內容

   Text textseg;
Element link=doccreateElement(link);

  首先應該明了的是無論什麼類型的NodeText型的也好Attr型的也好Element型的也好它們的創建都是通過Document對象中的createXXX()方法來創建的(XXX代表具體要創建的類型)因此我們要向XML文檔中添加一個link項目首先要創建一個link對象

   Element linktext=doccreateElement(text);
textseg=doccreateTextNode(text);
linktextappendChild(textseg);
linkappendChild(linktext);
……

  創建節點的過程可能有些千篇一律但需要注意的地方是對Element中所包含的text(在DOM中這些text也是代表了一個Node的因此也必須為它們創建相應的node)不能直接用Element對象的setNodeValue()方法來設置這些text的內容而需要用創建的Text對象的setNodeValue()方法來設置文本這樣才能夠把創建的Element和其文本內容添加到DOM樹中看看前面的代碼你會更好的理解這一點
docgetDocumentElement()appendChild(link);
  最後不要忘記把創建好的節點添加到DOM樹中Document類的getDocumentElement()方法返回代表文檔根節點的Element對象在XML文檔中根節點一定是唯一的

   TransformerFactory tFactory =TransformerFactorynewInstance();
Transformer transformer = tFactorynewTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new JavaioFile(linksxml));
transformertransform(source result);

  然後就是用XSLT把DOM樹輸出了這裡的TransformerFactory也同樣應用了工廠模式使得具體的代碼同具體的變換器無關實現的方法和DocumentBuilderFactory相同這兒就不贅述了Transformer類的transfrom方法接受兩個參數一個數據源Source和一個輸出目標Result這裡分別使用的是DOMSource和StreamResult這樣就能夠把DOM的內容輸出到一個輸出流中當這個輸出流是一個文件的時候DOM的內容就被寫入到文件中去了


如何利用JSP開發SAX應用?

  SAX是Simple API for XML的縮寫它並不是由WC官方所提出的標准可以說是民間的事實標准實際上它是一種社區性質的討論產物雖然如此在XML中對SAX的應用絲毫不比DOM少幾乎所有的XML解析器都會支持它
  與DOM比較而言SAX是一種輕量型的方法我們知道在處理DOM的時候我們需要讀入整個的XML文檔然後在內存中創建DOM樹生成DOM樹上的每個Node對象當文檔比較小的時候這不會造成什麼問題但是一旦文檔大起來處理DOM就會變得相當費時費力特別是其對於內存的需求也將是成倍的增長以至於在某些應用中使用DOM是一件很不劃算的事(比如在applet中)這時候一個較好的替代解決方法就是SAX
  SAX在概念上與DOM完全不同首先不同於DOM的文檔驅動它是事件驅動的也就是說它並不需要讀入整個文檔而文檔的讀入過程也就是SAX的解析過程所謂事件驅動是指一種基於回調(callback)機制的程序運行方法(如果你對Java新的代理事件模型比較清楚的話就會很容易理解這種機制了)在XMLReader接受XML文檔在讀入XML文檔的過程中就進行解析也就是說讀入文檔的過程和解析的過程是同時進行的這和DOM區別很大解析開始之前需要向XMLReader注冊一個ContentHandler也就是相當於一個事件監聽器在ContentHandler中定義了很多方法比如startDocument()它定制了當在解析過程中遇到文檔開始時應該處理的事情當XMLReader讀到合適的內容就會拋出相應的事件並把這個事件的處理權代理給ContentHandler調用其相應的方法進行響應
  這樣泛泛的說來或許有些不容易理解別急後面的例子會讓你明白SAX的解析過程看看這個簡單XML文件

<POEM>
<AUTHOR>Ogden Nash</AUTHOR>
<TITLE>Fleas</TITLE>
<LINE>Adam</LINE>
</POEM>
  當XMLReader讀到<POEM>標簽時就會調用ContentHandlerstartElement()方法並把標簽名POEM作為參數傳遞過去在你實現的startElement()方法中需要做相應的動作以處理當<POEM>出現時應該做的事情各個事件隨著解析的過程(也就是文檔讀入的過程)一個個順序的被拋出相應的方法也會被順序的調用最後當解析完成方法都被調用後對文檔的處理也就完成了下面的這個表列出了在解析上面的那個XML文件的時候順序被調用的方法

  遇到的項目 方法回調

{文檔開始} startDocument()
<POEM> startElement(nullPOEMnull{Attributes})
\n characters(<POEM>\n )
<AUTHOR> startElement(nullAUTHORnull{Attributes})
Ogden Nash characters(<POEM>\n )
</AUTHOR> endElement(nullAUTHORnull)
\n characters(<POEM>\n )
<TITLE> startElement(nullTITLEnull{Attributes})
Fleas characters(<POEM>\n )
</TITLE> endElement(nullTITLEnull)
\n characters(<POEM>\n )
<LINE> startElement(nullLINEnull{Attributes})
Adam characters(<POEM>\n )
</LINE> endElement(nullLINEnull)
\n characters(<POEM>\n )
</POEM> endElement(nullPOEMnull)
{文檔結束} endDocument()
  ContentHandler實際上是一個接口當處理特定的XML文件的時候就需要為其創建一個實現了ContentHandler的類來處理特定的事件可以說這個實際上就是SAX處理XML文件的核心下面我們來看看定義在其中的一些方法
  void characters(char[] ch int start int length)這個方法用來處理在XML文件中讀到字符串它的參數是一個字符數組以及讀到的這個字符串在這個數組中的起始位置和長度我們可以很容易的用String類的一個構造方法來獲得這個字符串的String類String charEncontered=new String(chstartlength)
  void startDocument()當遇到文檔的開頭的時候調用這個方法可以在其中做一些預處理的工作
  void endDocument()和上面的方法相對應當文檔結束的時候調用這個方法可以在其中做一些善後的工作
  void startElement(String namespaceURI String localName String qName Attributes atts)當讀到一個開始標簽的時候會觸發這個方法在SAX版本中並不支持名域而在新的版本中提供了對名域的支持這兒參數中的namespaceURI就是名域localName是標簽名qName是標簽的修飾前綴當沒有使用名域的時候這兩個參數都未null而atts是這個標簽所包含的屬性列表通過atts可以得到所有的屬性名和相應的值要注意的是SAX中一個重要的特點就是它的流式處理在遇到一個標簽的時候它並不會紀錄下以前所碰到的標簽也就是說在startElement()方法中所有你所知道的信息就是標簽的名字和屬性至於標簽的嵌套結構上層標簽的名字是否有子元屬等等其它與結構相關的信息都是不得而知的都需要你的程序來完成這使得SAX在編程處理上沒有DOM來得那麼方便
  void endElement(String namespaceURI String localName String qName)這個方法和上面的方法相對應在遇到結束標簽的時候調用這個方法
  我們還是沿用講DOM的時候使用的那個文檔例子但首先我們先看一個簡單一些的應用我們希望能夠統計一下XML文件中各個標簽出現的次數這個例子很簡單但是足以闡述SAX編程的基本思路了一開始當然還是import語句了

import orgxmlsaxhelpersDefaultHandler;
import Javaxxmlparsers*;
import orgxmlsax*;
import orgxmlsaxhelpers*;
import Javautil*;
import Javaio*;
  然後我們創建一個繼承於DefaultHandler的類具體的程序邏輯在這兒可以暫且放在一邊要注意的是程序的結構

public class SAXCounter extends DefaultHandler {
private Hashtable tags; //這個Hashtable用來記錄tag出現的次數
// 處理文檔前的工作
public void startDocument() throws SAXException {
tags = new Hashtable();//初始化Hashtable
}
//對每一個開始元屬進行處理
public void startElement(String namespaceURI String localName
String rawName Attributes atts)
throws SAXException
{
String key = localName;
……
  我們來看看這段程序作了些什麼在main()方法中主要做的就是創建解析器然後解析文檔實際上在這兒創建SAXParser對象的時候為了使程序代碼於具體的解析器無關使用了同DOM中一樣的設計技巧通過一個SAXParserFactory類來創建具體的SAXParser對象這樣當需要使用不同的解析器的時候要改變的只是一個環境變量的值而程序的代碼可以保持不變這就是FactoryMethod模式的思想在這兒不再具體講了如果還有不明白的可以參看上面DOM中的解釋原理是一樣的
  不過在這兒還有一點點要注意的地方就是SAXParser類和XMLReader類之間的關系你可能有些迷糊了吧實際上SAXParser是JAXP中對XMLReader的一個封裝類而XMLReader是定義在SAX種的一個用來解析文檔的接口你可以同樣的調用SAXParser或者XMLReader中的parser()方法來解析文檔效果是完全一樣的不過在SAXParser中的parser()方法接受更多的參數可以對不同的XML文檔數據源進行解析因而使用起來要比XMLReader要方便一些
  這個例子僅僅涉及了SAX的一點皮毛而下面的這個可就要高級一些了下面我們要實現的功能在DOM的例子中已經有實現了就是從XML文檔中讀出內容並格式化輸出雖然程序邏輯看起來還是很簡單但是SAX可不比DOM哦看著吧
  前面說過當遇到一個開始標簽的時候在startElement()方法中我們並不能夠得到這個標簽在XML文檔中所處的位置這在處理XML文檔的時候是個大麻煩因為在XML中標簽的語義有一部分是由其所處的位置所決定的而且在一些需要驗證文檔結構的程序中這更是一個問題當然沒有解決不了的問題了我們可以使用一個棧來實現對文檔結構的紀錄
  棧的特點是先進先出我們現在的想法是在startElemnt()方法中用push將這個標簽的名字添加到棧中在endElement()方法中在把它pop出來我們知道對一個結構良好的XML而言其嵌套結構是完備的每一個開始標簽總會對應一個結束標簽而且不會出現標簽嵌套之間的錯位因而每一次startElement()方法的調用必然會對應一個endElement()方法的調用這樣push和pop也是成對出現的我們只需要分析棧的結構就可以很容易的知道當前標簽所處在文檔結構中的位置了

public class SAXReader extends DefaultHandler {
JavautilStack tags=new JavautilStack();
……
  在這兒雖然沒有使用到棧的分析但實際上棧的分析是一件很容易的事情應為JavautilStack繼承了JavautilVector類而且Stack中的元素是按棧的結構由底至上排列的因個我們可以使用Vector類的size()方法來得到Stack的元素個數還可以使用Vector的get(int)方法來得到具體的每一個元屬實際上如果把Stack的元素從底向上逐一排列出來我們就得到了從XML根節點到當前節點的一條唯一的路徑有了這條路徑的信息文檔的結構就在清楚不過了
  到目前為止我們已經掌握了對於XML編程的兩大利器DOM和SAX也知道了該如何在一個Java程序中使用它們DOM編程相對簡單但是速度比較慢占用內存多而S AX編程復雜一些但是速度快占用內存少所以我們應該根據不同的環境選擇使用不同的方法大部分的XML應用基本都可以用它們來解決需要特別說明的是DOM和SAX其實都是語言無關的並非Java所獨有也就是說只要有相應的語言實現DOM和SAX可以應用在任何面向對象的語言中


From:http://tw.wingwit.com/Article/program/Java/Javascript/201311/25312.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.