有了新外觀,但是……
在上一篇文章的末尾, GentooLinux 網站有了一副全新的面孔,但是還有一些工作沒有完成。在本文(也是本系列的最後一部分)中,我最終對這個站點進行最後一番潤色,結果產生一個功能完備、考究和模塊化且便於日後修改的基於 XML 的站點。這是接上一篇文章中關於站點未討論完的部分:
尚需處理的問題
首先,雖然該站點有了一個全新外觀,但只有站點的文檔部分是基於 XML 的。主“類別”頁面仍然是原始的 Html 格式,需要將其轉換成 XML/XSLT 方案,以使它們更便於維護和擴充。
另外,我的開發人員還發現幾個原始 Html 本身的問題。當用 Netscape 4.77 浏覽時,站點看起來特別難看 ― 顯然,這是個問題。另外,在更多現代浏覽器中還有其它一些較小的顯示問題,其中最討厭的是有一條細豎線沒有完全向下延展到整個頁面,從而破壞了我們的飛碟好手正在講述主內容區這樣一個感覺。另外,我們的文檔頁與具有更考究外觀的新主類別頁沒有完全配合好 ― 很明顯需要更新一些東西。
目標
這是 Gentoo Linux 站點的最後修改計劃。首先,我們將完全修改主頁 Html,保持總體外觀不變,但使該頁面與浏覽器更兼容。同時,還會做幾項訪問者所建議的、與顯示有關的改進,並且還會修復現有“guide”文檔系統的浏覽器兼容性問題。
下一步,將把站點完全轉變為 XML 和 XSLT。在本文最後,對站點所做的的任何更改都將通過修改 XML 和 XSLT 而不是直接編輯 Html 來完成,現在,這可以在 xsltproc的幫助下自動生成。這將極大簡化站點的維護工作。因為 Gentoo Linux 是一個由社區開發的項目,所以,反過來這將允許我們的開發人員(和我)按照需要維護和改進站點。我確實對此感到興奮,因為它將節省我一些時間,並確保以最新內容歡迎我們的訪問者。
兼容性問題
雖然 Netscape 4.x 仍然是一個使用非常廣泛的浏覽器,但我很難確定:為了使站點在這種浏覽器中顯示得好一些,究竟需要克服多少困難。我應該只確保站點可讀(沒有任何重大錯誤)呢?還是應該盡我所能以使該站點在 Netscape 4.x 中看起來絕對完美 ― 即使那樣做需要少使用或不使用 CSS 並向現有 Html 中添加奇怪的兼容性方法?
最後,我決定對 HTML 做幾項重大更改,以便站點在 Netscape 4.x 中看起來仍然很好,而不是過於關注與表間距和字體顯示問題相關的較小錯誤。這裡是對該站點的 Html 所作的一些更改,以使所有內容都與 4.x 兼容。(Gentoo Linux 開發小組已經提交了幾個這樣的修正。)
首先,Netscape 4.x 有一個錯誤,可導致塊元素的 CSS 背景色被錯誤顯示。例如,下面是指南文檔的某個特定部分 期望的顯示效果:
圖 1. IE5 中的一個樣本指南文檔
查看原圖(大圖)
下面是使用 CSS 指定了背景色時,用 Netscape 4.x 顯示同一部分的效果:
圖 2. Netscape 4.7 中的一個樣本指南文檔;需要一些修正
查看原圖(大圖)
這很難看。要修復它,將現有塊級的元素(例如這個……)
清單 1.
<p class="note">This paragraph doesn't look so good in 4.x</p>
……用下面的表來替換:
清單 2.
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td bgcolor="#ddffff"><p class="note">
This looks a whole lot better in 4.x</p></td>
</tr>
</table>
這種方法修復背景顯示問題。然而,這種“修復”還需要在 Html 中包括顏色信息,這首先就破壞了使用 CSS 的好處。這是一種不幸的情況,特別是對於象我這樣的 CSS 愛好者,但是 Netscape 4.x 兼容性需要這樣做。
重建 Html
現在該處理那條不總是一直延伸到屏幕底部的黑色豎線的問題了。我無法找到一個方案來解決這個問題,使之既能在 4.x 又在 5.x 浏覽器中工作;每一個 5.x 版本都會觸發 Netscape 4.x 中的錯誤,而每一個與 4.x 兼容的版本在 5.x 浏覽器中看起來都很糟糕。因此,我決定簡單地除去整條黑線:最後,該站點可以在很多浏覽器中工作。下一步,我將創建一個類似於 guide 的語法以創建主頁。
著手 XML
我沒有為主頁實現全新標記集,相反,我認為使用盡可能多的“guide”XML 文檔標記是個好主意(有關 guide XML 格式的詳細信息,請參閱本系列的第 2 部分)。因此,我除去了一些新的 XSL,而使用我的 guide XSL 作為我的工作模板。一兩個小時之後,我就得到了一個功能齊備的、用於將類似於 guide 的語法變成 Html 主頁的 XSL 變換集。新主頁的修訂版 2 看起來類似於:
圖 3. 新主頁修訂版
查看原圖(大圖)
既然主頁使用一個新的 XML/XSLT 後端,我就將我的注意力轉移到“guide”系統的 HTML 輸出。我不僅需要修復很多 Netscape 4.7 兼容性錯誤,而且還要進一步更新生成的 HTML 和圖形,以便它們能與那些新修改的主頁很好地配合。這時我想到了一個主意:為什麼不簡單地對我的新主頁 XML/XSL 進行略微調整,以便它 還可以為我的文檔生成 Html?畢竟,我剛剛添加了對幾乎每一個“guide”XML 標記的支持,以便它們可用於主頁內容。
結果這個解決方案確實很容易實現。我僅僅調整了新的 XSLT 文件,以便它可以除去左邊的“鏈接欄”並在處理文檔頁面時對輸出 Html 作其它幾點較小的更改。既然大多數 XSLT 仍然相同,我可以對 guide 文檔和類別頁面使用一個主 XSLT 模板集。
圖 4. 新 XSL 的工作原理
現在,我不僅只維護一個 XSLT 模板集,而且因為兩種輸出 HTML 風格都基於同一主文檔,它們現在還共享同一 CSS 樣式表。這意味者無需在兩個截然不同的樣式表和輸出 HTML 集之間“同步外觀”。並且您可以看到,新的文檔 Html 與新主頁配合得很完美。
圖 5. 新文檔頁面與新主頁完美配合
查看原圖(大圖)
XML 實現
實際的實現相當簡單;我現有的 guide XML 語法要求每個文檔都是單一主 <guide> 元素的一部分。為添加對主類別頁面的支持,我創建了一個新的主元素: <mainpage> 。為創建主類別頁面,我將所有內容都放在 <mainpage> 元素中、而不是 <guide> 元素中,並且 XSLT 對輸出作了適當更改。除此之外,唯一需要的重大更改是添加可選的 <sidebar> 元素,該元素用於指定主類別頁面上浮動表的內容。現有的 <guide> XSLT 模板看起來類似於:
清單 3. XSLT 模板
<xsl:template match="/guide">
<Html>
<head>
guide header goes here
</head>
<body>
top part of guide body Html content goes here
<!--next, we insert our content-->
<xsl:apply-templates select="chapter" />
bottom part of guide body Html content goes here
</body>
</Html>
</xsl:template>
如果您不是很熟悉 XSLT,則這個模板告訴 XSLT 處理程序用 HTML 文檔的外殼替換 <guide></guide> 標記,並且將模板重復應用到 <guide> 元素內的任何 <chapter> 元素(開始/結束標記對)並將產生的結果輸出插入到 Html 外殼中間。
這樣,為了添加對主類別頁面的支持,我需要指定:如果所有內容都恰巧包括在單一 <mainpage> 元素中,應該使用一個不同的 Html 外殼。要做到這點,我添加了一個新的模板,如下所示:
清單 4. 新模板
<xsl:template match="/mainpage">
<Html>
<head>
mainpage header goes here
</head>
<body>
top part of mainpage body Html content goes here
<!--next, we insert our content-->
<xsl:apply-templates select="chapter" />
bottom part of mainpage body Html content goes here
</body>
</Html>
</xsl:template>
因為幾乎每一個其它的 XML 元素(從 <chapter> 開始之後的所有元素)都為 guide 和主類別頁面產生相同的 HTML 輸出,所以幾乎每一個其它的 XSLT 模板都可以為這兩種類型的頁面所共享。因此,我們只需使用一個指定兩種“HTML 外殼”的 XSLT 文件和一個從 XML 轉換到 Html 的公用 XSLT 模板集就可以很好地完成任務。象往常一樣,代碼重用無疑是個好東西。
“更改日志”頁面
您可能記得,在本系列的“第 2 部分”中,我提到過 cvs2cl.pl “CVS 更改日志”生成腳本可以產生 XML 輸出,並且我最終要使用這個特性作為每天都會出現在新網站上的“CVS 更改日志”頁面的基礎。現在,有了新的 XML 後端的支持,添加新的“更改日志”不過是小菜一碟。這是 cvslog.sh 腳本的增強版本,它還負責處理從 XML 到 Html 的轉換:
清單 5. cvslog.sh
#!/bin/bash
#various paths
HOMEDIR=/home/drobbins
CVSDIR=${HOMEDIR}/gentoo/gentoo-x86
OUTLOG=${HOMEDIR}/gentoo/XMLcvslog.txt
OUTMAIL=${HOMEDIR}/gentoo/cvslog.txt
WEBDIR=/usr/local/httpd/htdocs
XSLTP=/opt/gnome/bin/xsltproc
TMPFILE=${HOMEDIR}/gentoo/XMLcvslog.tmp
USER=drobbins
#if $CVSMAIL is undefined, set it to "yes"
if [ -z "$CVSMAIL" ]
then
export CVSMAIL="yes"
fi
#the main script
cd $CVSDIR
cvs -q update -dP
yesterday=`date -d "1 day ago 00:00" -R`
today=`date -d "00:00" -R`
cvsdate=-d\'${yesterday}\<${today}\'
nicedate=`date -d yesterday +"%d %b %Y %Z (%z)"`
#generate cvs2cl.pl XML output
/usr/bin/cvs2cl.pl --XML -f $OUTLOG -l "${cvsdate}"
#use sed to remove "XMLns=" from cvs2cl.pl output
/usr/bin/sed -e 's/XMLns=".*"//' $OUTLOG > ${OUTLOG}.2
#convert cvs2cl.pl XML output to guide format using $XLSTP
$XSLTP ${WEBDIR}/xsl/cvs.xsl ${OUTLOG}.2 > $TMPFILE
#convert guide XML output to Html format using $XLSTP
$XSLTP ${WEBDIR}/xsl/guide-main.xsl
$TMPFILE > ${WEBDIR}/index-changelog.Html
#fix perms
chmod 0644 ${WEBDIR}/index-changelog.Html
#automatically send cvs mail if $CVSMAIL is set to "yes"
if [ "$CVSMAIL" = "yes" ]
then
/usr/bin/cvs2cl.pl -f ${OUTMAIL} -l "${cvsdate}"
mutt -x gentoo-cvs -s "cvs log for $nicedate" > ${OUTMAIL}
fi
雖然該腳本看起來比以前的版本復雜得多,但它實際上只添加了四個或五個關鍵行;其余添加的行不是注釋就是環境變量定義。
以下是 cvslog.sh 腳本中與 XML 相關的新部分的工作原理。首先,我們調用 cvs2cl.pl,然後指使它生成一個基於 XML、並包含昨天修改過的所有文件的“更改日志”。然後,通過 sed 運行這個 XML 輸出,以從 XML 中除去一個不需要的 xmlns= 屬性。下一步,我們將這個作過輕微改動的 XML 傳遞給 xsltproc ,並告訴它應用在 cvs.xsl 中發現的處理指令;這些指令將來自 cvs2cl.pl 的 XML 輸出變換成正確的 guide XML 文檔。最後,我們再次使用 xsltproc 將這個 guide XML 文檔轉換成可在 Web 上發布的 HTML,該 Html 被管道輸出至 Web 服務器的 htdocs 目錄。生成的“Html 更改日志”是完整的,這就是結果:
圖 6. 自動生成的“更改日志”頁面
查看原圖(大圖)
您可能對包含在 cvs.xsl 中的 XSLT 的簡單性感到驚訝。其中,我們為 <changelog> 、 <entry> 和 <file> 指定了三個模板。我們還引用了源 XML 中的其它幾個標記,包括 <date> 、 <author> 和 <msg> (cvs2cl.pl 使用它們來指定提交者的注釋)。考慮到它大約只有 35 行,cvs.xsl 做得已經相當多了。
Listing 6. cvs.xsl
<?XML version='1.0' encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" XMLns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="iso-8859-1" method="XML" indent="yes"/>
<xsl:template match="/changelog">
<mainpage id="changelog">
<title>Gentoo Linux Development Changelog for <xsl:value-of select="entry/date"/></title>
<author title="script">cvs-XML.xsl</author>
<standout>
<title>About the Development Changelog</title>
<body>
This page contains a daily Changelog, listing all modifications made to our
CVS tree on <xsl:value-of select="entry/date"/> (yesterday).
</body>
</standout>
<version>1.0.0</version>
<date><xsl:value-of select="entry/date"/></date>
<chapter>
<xsl:apply-templates select="entry"/>
</chapter>
</mainpage>
</xsl:template>
<xsl:template match="entry">
<section>
<title>Files modifIEd by <xsl:value-of select="author"/> at
<xsl:value-of select="time"/>
</title>
<body>
<note><xsl:value-of select="msg"/></note>
<ul>
<xsl:apply-templates select="file"/>
</ul>
</body>
</section>
</xsl:template>
<xsl:template match="file">
<li><path><xsl:value-of select="name"/></path>, <xsl:value-of select="revision"/></li>
</xsl:template>
</xsl:stylesheet>
項目完成!
從開始重新設計 Gentoo Linux 網站,我們就創建了一個以用戶為中心的行動計劃,設計了一個新的基於 XML 的文檔系統,一個新的徽標,一個新的站點外觀,將所有剩余部分轉換成 XML,並添加了新的基於 XML 的“更改日志”頁面。唷!我希望您在隨我進行的過程中得到歡樂,並從中發現很多好主意和靈感。我已經收到了幾個關於對更多信息和與重新設計相關的代碼的請求,因此,我建立了一個特殊的 “Gentoo Linux XML 項目”頁面,該頁面包含 www.gentoo.org 所使用的最新的 XML、XSLT、腳本和文檔。除了訪問“項目”頁面之外,請務必查看以下所列的有價值資源。