第一節:理解XSL?
有一天晚上我做了一個夢。這個夢真嚇人。但如我告訴我的釋夢師的,如果你沒有讀過寫使用XML和我媽媽的菜譜賺錢的計劃,這個夢就沒什么意義。
不管怎么說,這個夢......
那是在公元2001年,我用我媽媽的菜譜建立了一個網站,而且行得不錯。網站的節讀數很高,得到的反饋也很多。后來就到了電話,是Michael?Ovitz打來的。他告訴我他回來做生意,想把這些菜譜作為事業的起點。他認為其潛力不僅僅在于它一份菜譜,而是Sally?Field領銜出演的一系列關于與恐怖份做斗爭的身懷絕藝的技藝精湛的廚師的電影。他所要的是一250個菜譜的標題和它們組成成分的清單。而且他希望在15分內得到它們。我狂喜,我顫栗,然后我意識到我用的是HTML。
我從尖叫中醒來?-?冷汗順著我的臉往下淌。
為什么是個噩夢呢?夢中的是發生在將來,一個XML和它的同伴XSL(擴展樣式表?-?eXtensible?Stylesheet?Languange)被廣泛使用的時代。即使這樣,我用HTML建立我的整個菜譜網站,不是XML。而且,HTML就是HTML?-?我沒有辦法從中通過拷貝粘貼提取想要的信息。CSS此時也毫無用處。但是如果我在夢用了XSL,我就會很快產生那份清單,然后快樂地從別人的天和努力中榨取利益。
然而現在,XSL的允諾只是一個夢。關鍵在于從W3C的第一份草稿到發布第一份推薦稿至少要八個月(或至少一年)的時間。在完成之前,其規范可能要做根本性的改變。
盡管這樣,微軟還是正在打算在其IE?5的第二個beta版中支持XSL現有草稿的功能。坦率地說,我不知道為什么它會在這上面耗費資源。因為這件事對每個人來說,誰都不愿意花費時間在學習一種在其實現之前就過時的語言。
雖然如此,但理解XSL的要點還是很重要的?-?它會使Web開發者的生活更容易些。如果對XSL一無所知,對被經常吹捧的XML的一些優點的理解就會有困難。
那么就讓我們看看其中的一些基本概念?-?不太可能改變的東西。
第二節:攀登結果樹
你從本文中學到的最重要的一點是XSL不僅僅是應用樣式。當使用XML處理器時,XSL源文檔中的信息將被評價、重新安排,然后重新組裝。我們最終得到的不只是XML數據的可愛的版本?-?而是可以被容易地添加、修改和重新排序的靈活的源信息。這個最終產品叫做結果樹(Result?Tree)。
這通過一系列測試產生。下面是一個簡單的例子:
???<xsl:template?match="recipe_name">
?????<P>
???????<xsl:process-children/>
?????</P>
???</xsl:template>
最先要解釋的是以"/"?結束的標記符是空的。即此種類型的標記符的起始和結束標記符之前什么也不發生。在HTML中類似的例子是<img>標記符。因為一個圖像所需的所有信息都包含在一個標記符中,所以就沒有必要存在結束標記符</img>。組織良好的XML文檔可以接受空標記符,同時XSL樣式表必須是組織良好的XML。
讓我們再回到例子,它告訴XSL處理器如果發現一套<recipe_name>標記符,就應該分離出內容然后用<p>和</p>包圍起來。或者,如果你想炫耀你的XSL的知識,你可以說“添加到結果樹中?!?/p>
這是一個相當簡單的測試,而且很典型。XML元素的內容被表現信息所包圍。
現在讓我們看看書寫菜譜的XSL樣式表的完整例子。
在我講述更多的XSL標記之前,我要解釋一個可能被問到的問題。誰都知道在HTML中<p>本身就足夠了,那么我為什么要使用結束的</p>標記符呢?
有人能回答嗎?答案是:沒有對應的結束標記符,那部分就不是組織良好的XML,于是會產生一個致命的錯誤。
第三節:一個XSL樣式表
下面是一個完整的樣式表。
<xsl:stylesheet>
???<xsl:template?match?=?"/">
?????<HTML>
?????<BODY>
?????????<xsl:process-children/>
?????</BODY>
?????</HTML>
???</xsl:template>
???<xsl:template?match?=?"author">
?????????<H1>
?????????<xsl:process-children/>'s?fabulous
?????????</H1>
???</xsl:template>
???<xsl:template?match?=?"recipe_name">
??????<H2>
??????<xsl:process-children/>
??????</H2>
???</xsl:template>
???<xsl:template?match?=?"meal">
??????<TABLE><TR><TD><H3>EAT?FOR:</H3></TD>
??????<TD><H3><xsl:process-children/></H3></TD>
??????</TR></TABLE>
???</xsl:template>
???<xsl:template?match?=?"directions">
??????<H4>DIRECTIONS</H4>
??????<P>
??????<xsl:process-children/>
??????</P>
???</xsl:template>
???<xsl:template?match?=?"ingredients">
???????<B>INGREDIENTS</B><BR></BR>
???????<xsl:process-children/>
???</xsl:template>
???<xsl:template?match?=?"item">
???????<BR>
??????<xsl:process-children/>
??????</BR>
???</xsl:template>
</xsl:stylesheet>
其結果不會使我得到任何設計獎,但是它是一個能起作用的XSL。這里可能只有下面的命令需要解釋:
??<xsl:template?match?=?"/">
????<HTML>
?????<BODY>
?????????<xsl:process-children/>
?????</BODY>
?????</HTML>
?</xsl:template>
第一行的"/"告訴處理器這個節點應用到XML文檔的根上。于是,這部分中的命令是結果樹的基礎。處理器被告之把<HTML>和<BODY>標記符放在文檔的開始和結尾處,然后處理或打印所有的子元素。因為它是根元素,所以意味著“打印所有的東西?!?/p>
現在,如果你考慮幾秒鐘,就會覺得有點古怪。如果根層的process-children命令把源代碼傳遞給結果樹,那么所有與模板匹配的節點都可以與已經經過處理的源碼一起工作。
然而,出現的問題是:XSL有一套確定哪些內容被傳遞給結果樹的規則,其中最重要的規則是,最特定的匹配將會贏。顯然,元素名的模板匹配比根層的匹配更特定。因此,所有模板匹配的節點將超越根層的規則。
注意用XML數據添加HTML標記符是多么的容易。當XSL處理器看到那些不在XSL詞匯表中的標記符時,就會把他們傳遞給結果樹。如果你花些時間,就可能發現其中巨大的潛力。XSL可以被用做一種轉換語言。存儲在一個XML文件中的數據可以用完全不同的標記符轉換到另一個文件中。還有,信息可以被修改成與可以對應一套不同的標記符集的XML應用程序一起工作的形式。
而且還不只這些,如人們所期望的,樣式表可以用匹配的標記符打開和關閉,其中是一套組織良好的單元。?很好,但是還有限制。
第四節:選擇XSL
簡單的<xsl:template?match>還不能完全滿足我們的要求。比如,我希望當<course>標記符出現時取消<meal>標記符的內容。這樣的話我就不用擔心節面上同時顯示"dinner"和"appetizer"。我可能還希望通過在最后的ingredient后面插入大量的空白來調整版面。
如同某個廣告部的人說的:所有這些都是可能的?-?還要更多。SL有一套用來把元素與其父成員或子成員匹配的工具。它也允許位置上的匹配。例如,可以在第一個和最后一個某個特定元素上應用特定的格式,等等。
現在讓我們考慮一些更復雜的事,比如令我在夢中出汗的任務。我需要菜譜名和它們的成分的清單。現在,如果我的網頁與數據庫沒有聯系,我就不得不寫一個查詢語句。因為我對SQL不太熟,所以需要得到的DBA幫助。但是如果知道XSL,我就會擺脫這些麻煩。
<xsl:style?sheet>
???<xsl:template?match?=?"/">
??????<xsl:for-each?select?="list/recipe">
?????????<TABLE>
?????????<TR><TD>
?????????<xsl:process?select?=?"recipe_name"/></TD>
?????????<TD>
????????????<xsl:for-each?select?=?"ingredients/item">
???????????????<BR><xsl:process-children/></BR>
????????????</xsl:for-each>
?????????</TD></TR>
?????????</TABLE>
??????</xsl:for-each>
???</xsl:template>
</xsl:stylesheet>
結果并不神奇。但是在table標記符中加些花樣將沒問題。顯然,我在XML中存儲了信息,但是我認為最好還是仔細看看。
???<xsl:template?match?=?"/">
??????<xsl:for-each?select?="list/recipe">
第一行很熟悉,只是簡單地與模板相匹配。但是第二行卻有些不同?-?在元素清單中出現的每個菜譜元素做每件事,直到</xsl:for-each>標記符。然后我開始HTML表格,用<xsl:process?select="recipe_name"/>標記符把recipe_name元素中的內容輸出到表格單元中。在關閉第一個表格單元后,事情開始變酷。下一行(<xsl:for-each?select="ingredient/item">)開始一個附加的嵌套循環,允許我把全部ingredient輸出到合適的顯示信息中。樣式表的其余部分應該很好理解。
但是等等,我知道你在想:“他說過酷了嗎?什么這么酷?”
for-each函數是XSL的幾個程序化的特征之一。還有if-then和選擇函數。這些特征允許任何人都可以以任何能想到的方式(或至少是可行的方式)容易地操縱XML內容。如果你能實現這些特征,就很酷。
第五節:從規范到實現
既然你已經看到XML的一些功能,那么我想提出一個問題:通過把內容分離到組織良好和有效的XML文件中,XML對這些內容有哪些不能做的呢?如我前面顯示的,數據可以被操縱然后放入你選擇的版面中?;蛘邤祿梢员惶幚沓煽梢员黄渌鼞贸绦蚴褂玫男问健D敲?,還有其它的嗎?
我們再一次面對擴展性的核心。一旦定義了數據,我們可以做任何想做的事。如果我們來到一個有能處理XML的字處理、電子表格和表現程序的時代,同一套數據幾乎可以被用在任何用途上。
但是,哎!這依然是個夢。
我們只能希望瀏覽器能實現這些功能,但是我們沒有理由樂觀。即使Tim?Bray,XML的教父,也說過對XSL的嘗試只能在CSS標準完全實現之后才能實現。誰知道什么時候才能實現呢?而且這也不是唯一的問題。
XSL要排除另一個障礙。XSL規范有兩個截然不同的部分。第一部分,是我們這里討論的,處理數據結構。另一部分是一套用來應用樣式的有格式的對象。這部分需要做大量工作。在我看來,現在需要很多人去做很多事。例如,應該有既適合屏幕又適合打印輸出的命令。如果規范的制定者繼續這種“無所不包”的嘗試,此規范將最終很難實現,而且最終用戶用起來也困難。但是現在,我們做不了什么?-?只能過我們自己快樂的小日子,同時盼望負責的同志們別把事情弄糟。
在這期間,做了甜夢吧!
---
轉載自 http://bbs.xml.org.cn/dispbbs.asp?boardID=8&ID=7632