用XML和XSL來生(shēng)成動態頁麵
xml(可擴展標記語言)看起來可能像(xiàng)某種w3c標準——現在沒有什麽實際影響,即使以後能派上用場,也是很久以後(hòu)的事。但實際上,它現在已(yǐ)經得到了應用。所(suǒ)以,不要等到xml已被加進了你(nǐ)最喜(xǐ)愛的html編輯器中才開始使用它。它現在就可以解(jiě)決各種(zhǒng)內部問題和b2b係統問題。
在sparks.com,我們使用xml來(lái)標準化從java對象到html數據顯示等(děng)不同係統之間的數(shù)據表示。
特別需要指出的是,我們發(fā)現,隻要以非常(cháng)基本的xml結構來(lái)實(shí)現標準化,就(jiù)可以更容易地共享和操作數據。在這一過程中,我(wǒ)們發現了使用xml的很多有效(xiào)方法。下麵詳細介紹我們現在的應用情況。
標準化
在使用xml之(zhī)前,建立與你要使用的信息不同的xml數據格式。
生成動態xml
從數據庫中生成html並不新鮮,但(dàn)生成xml卻很新鮮。這裏(lǐ)我們介紹具體的生成步驟。
用xsl作為模板語言
xsl(可擴展樣式表語言)是定義xml數據顯示格式的好方法(fǎ),如果寫成幾個靜態模板會更有效。
生成html
xml加(jiā)上xsl就等(děng)於html。這聽起來似乎不對,但用戶所(suǒ)見的我們(men)的html頁麵其實就是xml和xsl共同(tóng)產生的效果。
一、標準化
xml的能力(lì)來自於它的靈活性。但不幸的(de)是,它有時太靈活(huó)了,以至於你會麵對(duì)一個空白的頁麵,發愁該怎麽解決問題(tí)。
在任何xml的(de)項目中,第一步工作都是創建標準的數據格式。為此你要作出以下決定:
• 要涉及哪些數據
• 是(shì)否要使(shǐ)用dtd(文件(jiàn)類型定(dìng)義)
• 是否要使用dom(文檔對象(xiàng)模型)或sax(xml的簡化api)解(jiě)析
確定數據:
因為沒有標準(zhǔn)的xml格(gé)式,開(kāi)發(fā)者可以自由地開發自己的格(gé)式。然而,如果你的格式隻能被一(yī)個應用程序(xù)識別,那麽你(nǐ)隻能運行這個程序來使用該格式。如果還(hái)有其(qí)他程序也能讀懂你的xml格式(shì),那顯然會更有幫助。如果某個xml格式被(bèi)修改,則(zé)使用它的係統可(kě)能也需要被修改,所以你應該建(jiàn)立盡可能完整的格式(shì)。因為(wéi)大多數係統忽(hū)略它們(men)無法識別的標簽,所以改變一個xml格式的(de)最安全的方(fāng)法是(shì)添加標簽,而不是修改標簽。
單擊此處(chù)查看xml數據格式實例
在sparks.com,我們查看了不同的產品展示需要的所有產品數據。盡管並不是(shì)所有(yǒu)的頁麵都使用全部(bù)數據,但我們還是由此開發出適用於所有數據的非常完整的xml數(shù)據格式。例如,我(wǒ)們的產(chǎn)品明細信息頁麵顯示的數據要比產品瀏覽頁麵(miàn)多。然而,我們在這兩(liǎng)種情況下仍(réng)然使用(yòng)相同的數據格式,因為每個頁麵的xsl模板都隻使用(yòng)它(tā)所需要(yào)的字段。
是否使用dtd
在sparks.com,我們使用組織(zhī)良好(hǎo)的(de)xml,而不使用(yòng)僅僅是正確的xml,因為前者不需要(yào)dtd。dtd在用戶點(diǎn)擊和看到頁麵(miàn)之間加入了一個處理層。我們發現這一層需要太多的處理。當然,在以xml格式與其他公司通信時,使用dtd還(hái)是很不(bú)錯的(de)。因為dtd能在發送和(hé)接受時能保證數據結構正確。
選擇(zé)解析引擎
現在,可以使用的解(jiě)析引擎(qíng)有好幾個(gè)。選擇哪(nǎ)一個幾乎完全取決(jué)於你的應用需要。如果(guǒ)你決定使用(yòng)dtd,那麽這個解析引擎必須能使你的xml被dtd驗證。你(nǐ)可(kě)以將驗證另放到一個進程中,但那樣會影響性能。
sax和dom是兩個基本的解析模型。sax基於事(shì)件,所以在xml被解析時,事件被發(fā)送給引(yǐn)擎。接下來(lái),事件(jiàn)與輸出文件同步(bù)。dom解析引擎為動態(tài)xml數據和xsl樣式表建立層次樹狀結構。通(tōng)過隨機訪問dom樹,可以提供xml數據,就象由xsl樣式表來決定(dìng)一樣。sax模型(xíng)上的爭論(lùn)主要集中於對dom結構的內存降低過度(dù)和加快xsl樣式表解析時間縮(suō)短方麵。
然而,我們(men)發現使(shǐ)用sax的很多係統並沒有充分發揮(huī)它的能力。這些係統用它來建立(lì)dom結構並通過(guò)dom結構來發送事件。用這種方法,在任何xml處理之前必須從樣式表中(zhōng)建(jiàn)立dom,所以性能會下降。
二、生成動態xml
一旦建立了xml格式,我們需要一種能夠將其從數據庫中動態移植的方法。
生成xml文檔相對來(lái)說比較簡單,因(yīn)為它隻需(xū)要一個可以處理字符串的係統。我(wǒ)們(men)建立了一個使用java servlet、enterprise javabean server、jdbc和rdbms(關係型數據庫管理係統(tǒng))的係(xì)統。
• servlet通(tōng)過把生成xml文檔的任務交給enterprise javabean (ejb)來處理產品信息請求。
• ejb使用jdbc從數據庫(kù)裏查詢所需的產品詳細信息。
• ejb生成xml文件並把它傳遞給servlet。
• servlet調用解析引擎,從xml文件和靜態的xsl樣式表中創建html輸出。
(有關xsl應用的其(qí)他信息,請(qǐng)參閱用xsl作為模板語言(yán)。)
生成xml的(de)例子
在java中創建xml文(wén)檔(dàng)字符串(chuàn)的(de)真正代碼可以分(fèn)成幾個方法和(hé)類(lèi)。
啟動xml生成過程的代碼放在ejb方法裏(lǐ)。這一實例會立即創建(jiàn)一個stringbuffer,以(yǐ)便存儲生成的xml字符串。
stringbuffer xml = new stringbuffer();
xml.append(xmlutils.begindocument("/browse_find/browse.xsl", "browse", request));
xml.append(product.toxml());
xml.append(xmlutils.enddocument("browse");
out.print(xml.tostring());
後麵的三個xml.append()變元本身就(jiù)是對其他方法的調用。
產(chǎn)生文件頭
第一個附加方法調用(yòng)xmlutils類來產生xml文件頭。我們的java servlet中的代碼如下:
public static string begindocument(string stylesheet, string page)
{
stringbuffer xml = new stringbuffer();
xml.append("\n")
.append(" .append(stylesheet).append("\"")
.append(" type =\"text/xsl\"?>\n");
xml.append("<").append(page).append(">\n");
return xml.tostring();
}
這段代碼(mǎ)生成了xml文件頭。標簽把(bǎ)本文件定義為(wéi)支持1.0版本的xml文件。第二行代碼指向用以顯示數據的正確樣式表的位置。最後(hòu)包括進去的是項級(jí)標簽(本實例中為
)。在文件末(mò)尾,隻有
標簽需(xū)要被關閉。
填入產品信息
完成(chéng)了文件頭後,控製方法會調用java對象來(lái)產生它的xml。本(běn)例中(zhōng)調用(yòng)的是product對(duì)象。product對象使用兩個方(fāng)法來(lái)產生它的xml表示。第一個方法toxml()通過產(chǎn)生<product>和</product>標簽來建(jiàn)立product節點。然(rán)後它會調用internalxml(),這樣就能提供產品xml所需的內容。internalxml()是一係(xì)列的stringbuffer.append()調(diào)用。stringbuffer也被轉換成字符串並返回給控製方法。
public string toxml()
{
stringbuffer xml = new stringbuffer("<product>\n");
xml.append(internalxml());
xml.append("</product>\n");
return xml.tostring();
}
public string internalxml()
{
stringbuffer xml = new
stringbuffer("\t")
.append(producttype).append("\n");
xml.append("\t").append(idvalue.trim())
.append("\n");
xml.append("\t").append(idname.trim())
.append("\n");
xml.append("\t").append(page.trim())
.append("\n");
厖?
xml.append("\t").append(amount).append("\n");
xml.append("\t").append(vendor).append("\n");
xml.append("\t\n");
xml.append("\t").append(pubdesc).append("\n");
xml.append("\t").append(vendesc).append("\n";
厖?
return xml.tostring();
}
關閉文件
最後,xmlutils.enddocument()方法(fǎ)被調用。這個(gè)調用關(guān)閉xml標簽(本例中為),並最終完(wán)成架構好的xml文件。來自(zì)控製方法的整(zhěng)個stringbuffer也轉換(huàn)成字符(fú)串,並(bìng)返回給處理最初http請(qǐng)求的servlet。
三、用xsl作為模板(bǎn)語言(yán)
為了得到html輸出(chū),我們把生成的xml文件和控(kòng)製xml數據如何表示的(de)xsl模(mó)板相結合。我們的xsl模板由精心組織的xsl和html標簽組成。
開始建模板
我們的xsl模板開始部分與下麵這(zhè)段代碼類似。第一行代碼為必需代碼,將本文件定義為xsl樣式表。xmlns:xsl=屬性引(yǐn)用本文件所使用的xml名(míng)稱空間(jiān),而version=屬性則定義名稱空間的版本號。在文(wén)件的末尾,我們關閉標簽。
由<xsl:template>開始的第二行代(dài)碼確定了xsl模(mó)板的(de)模式(shì)。match屬性(xìng)是必需(xū)的,在這裏指向xml標簽<basketpage>。在我們的係統裏,<basketpage>標簽裏包含<product> 標簽,這
關鍵詞:XML,XSL,動態頁麵
閱讀本文(wén)後您有什麽感想? 已有 人給(gěi)出評價(jià)!
- 1
- 1
- 1
- 1
- 1
- 1