自從我的文章 “Firefox 1.5 中的 XML,第 1 部分:XML 特性概述” 於 2005 年 10 月首次發表以來,在 Firefox 中出現了一些重要的情況。其中主要的是 Firefox 1.5 正式發布了,當前的 Firefox 版本是 1.5.0.2,這是一個次要的 bug 補丁。在這篇文章中,我將詳細討論一下 Firefox 中的基本 XML 處理。這裡提供的 Firefox 屏幕圖是使用 UbuntuLinux 上的 Firefox 1.5.0.1 生成的,配置文件沒有修改過(即沒有擴展,保持了安裝時的默認選項)。
解析基礎知識
用 Firefox 和 XML 所做的最基本的操作是按照未知的詞匯表裝載 XML 文件,沒有相關聯的樣式表。清單 1 就是這樣一個文件。
清單 1(listing1.xml). 簡單 XML 文件示例
<memo>
<date form="iso-8601">2002-08-14</date>
This is just to <strong>say</strong>:
I ate the eggs you left in the fridge
And were probably saving for breakfast.
Do you know? They were <emph>quite</emph> rotten.
</memo>
用 Firefox 查看這個文件會產生 圖 1 所示的顯示。
圖 1. 在 Firefox 中查看清單 1
仔細看看浏覽器區域頂部的消息,即 “The document tree is shown below.”。這說明不應該把它看成 XML 的源代碼視圖。它只是 Firefox 認識到的文檔部分的邏輯布局。它可能會忽略對您有意義但是對 Firefox 沒有意義的一些細節,而且會在某些地方歪曲文檔。作為歪曲的一個示例,注意 Firefox 讓每個元素占一個新行,即使在源代碼文檔中並不是這樣的。對於使用混合內容的文檔,這會顯著改變內容的布局。作為 Firefox 忽略細節的示例,請在浏覽器中查看 清單 2。
清單 2(listing2.xml). 具有名稱空間等的簡單 XML 文件示例
<?XML version="1.0" encoding="utf-8"?>
<!DOCTYPE memo>
<memo XMLns='http://example.com'>
<date form="iso-8601">2002-08-14</date>
This is just to <strong>say</strong>:
I ate the eggs you left in the fridge
And were probably saving for breakfast.
Do you know? They were <emph>quite</emph> rotten.
</memo>
清單 2 的顯示與 清單 1 的顯示完全一樣,所以顯示中忽略了 XML 聲明、文檔類型聲明和名稱空間聲明。如果想看到原樣的 XML 文檔,那麼應該使用 view-source 功能。在菜單條上,選擇 VIEw,然後選擇 Page Source。常用的快捷鍵是 Ctrl+U。還可以使用右擊主浏覽器區域所顯示的上下文菜單。vIEw-source 顯示見 圖 2,其內容與源代碼清單完全一致。
圖 2. 清單 2 在 Firefox 中的 vIEw-source 顯示
再看一下 圖 1,注意 memo 元素的開始標記旁邊的減號。每個容器元素都有這樣的標志,可以點擊它將這個元素折疊起來。這在調試時很有用,如果對 XML 文件的某些部分不感興趣,就可以將它們折疊起來。
解析錯誤
為了演示 Firefox 對非良構文檔的處理,我在 清單 2 中 date 元素的前面添加一個偽造的字符實體 (一些字符即使表示為實體,在 XML 中也是非法的),然後在 Firefox 中查看它。圖 3 顯示 Firefox 輸出,這裡報告了錯誤以及探測到這個錯誤的位置。
圖 3. Firefox 對非良構 XML 的顯示
注意,這裡顯示了源代碼文件的一部分,足以幫助您確定錯誤的位置。而且,仍然可以使用 vIEw-source 特性來查看完整的源代碼文檔。
XML 的類型
XML 只是一種基本格式,可以用它構建更特定的格式,Firefox 對它支持的特殊 XML 格式進行特殊的處理和顯示。我在前一篇文章中涉及了其中一些格式,包括 XHtml、Scalable Vector Graphics(SVG)和 XSLT。對於判斷浏覽的源代碼是一般的 XML,還是 XML 的某種特殊形式,Firefox 采用的主要方法是互聯網媒體類型(常常稱為 MIME 類型)。對於提交給浏覽器的每個資源,Web 服務器會發送 MIME 類型信息。對於在本地文件系統上打開的文件,浏覽器根據文件的擴展名來猜測 MIME 類型。表 1 總結了未修改過的 Firefox 安裝可以識別的與 XML 相關的 MIME 類型。
表 1. Firefox 處理的 XML MIME 類型
一些 Firefox 擴展使 Firefox 能夠識別其他媒體類型。還可以為某些 XML 格式添加應用程序處理器。例如,如果希望用語音浏覽器處理 VoiceXML,可以為 MIME 類型 application/voicexml+XML 注冊這個應用程序。
在 Firefox 裝載頁面時,您可以檢查 Firefox 將哪種 MIME 類型與這個頁面關聯起來。右擊頁面並從上下文菜單中選擇 VIEw page info。Firefox 對於具有 .xml 擴展名的文件使用 text/xml,盡管按照當前的最佳實踐,它應該使用 application/XML。
一些不幸的限制
Firefox 不支持你可能需要的一些 XML 設施。在為 Firefox 設計頁面時,您應該知道它在基本 XML 處理方面的限制。在 bug 報告和改進請求(“bugzilla”)中提到了其中的許多限制。您可以對 bug 或改進請求投票,以便讓 Mozilla 開發人員給予這個問題更高的優先級,所以如果這些限制影響了您,就請考慮獲得一個 Mozilla bug 跟蹤者帳號(很容易獲得)並對解決方案投票。
要注意的第一個限制是,當 Firefox 解析 XML 文件時,它會長時間地掛起進行處理的線程,直到完成解析。這意味著,如果向 Firefox 發送一個非常大的 XML 文件,您的用戶必須等待很長時間才能看到內容顯示。如果向 Firefox 發送一個大型的 HTML 文件,它會采用遞增式顯示,在讀取文件的同時顯示 Html。如果對於 XML 有相同的功能就好了,但是目前沒有,所以應該考慮控制發送給浏覽器的 XML 文件的大小。
Firefox 不支持 DTD 檢驗。它不讀取外部文件中的 DTD,也不使用文檔中的任何聲明(稱為內部子集)來進行檢驗。在讀取外部文件時,Firefox 根本不讀取任何外部實體,無論是參數實體(比如 DTD 和 DTD 片段)還是一般實體(外部的良構的 XML 片段)。這意味著,無論 extFile.ent 的內容是什麼,Firefox 處理 清單 3 和 清單 4 的方式在邏輯上是相同的。
清單 3. 使用外部解析實體的 XML 文件 <!DOCTYPE myXML[
<!ENTITY extFile SYSTEM "extFile.ent">
]>
<myXML>&extFile;</myXML>
清單 4. 沒有實體的 XML,但是 Firefox 在邏輯上按照與清單 3 相同的方式處理它 <myXML></myXML>
對外部實體的支持可能會導致安全問題,還可能會有性能影響,但是在這兩方面都有解決方案,我希望 Firefox 不久就能解決這些限制。
如果使用 RDF/XML,那麼要意識到 Firefox 在解析 RDF 時不進行良構性檢查。因此,Firefox 在處理 RSS 1.0 Web feeds(這是 RDF)時不考慮良構性,這是不幸的,因為 Web 社區正在試圖增加良構 Web feeds 的強制性。
元素的樣式
讓 Firefox 以非一般方式顯示任意 XML 最容易的方法是使用樣式表。Firefox 支持級聯樣式表和 XSLT。我不打算過多地討論這些技術在 Firefox 中的使用,因為 IBM developerWorks 已經為這個主題提供了一組深入的教程。我在這裡要提到的一件事是,必須確保任何樣式表都是從與源代碼 XML 文檔相同的互聯網域裝載的,否則 Firefox 就不會裝載和應用樣式表。這個安全限制是為了避免跨站點腳本攻擊(XSS)。
Firefox 特定的 XSLT
即使在 XSLT 這樣的已經建立的標准中,在引擎之間行為還是有差異的。如果需要指定一部分 XSLT 只在 Mozilla 和 Firefox 下執行,也就是說只在任何形式的 Transformiix(與 Mozilla 綁定的 XSLT 引擎)下執行,那麼使用 清單 5 這樣的條件塊。
清單 5. XSLT 中 Mozilla 特定的代碼塊示例<xsl:if test="system-property('xsl:vendor')='Transformiix'">
<xsl:text>This will only be output by
Firefox/Mozilla/Transformiix</xsl:text>
</xsl:if>
每種 XSLT 引擎對於 system-property 都有不同的值,如果需要,可以使用 xsl:choose 來提供每種引擎特定的部分。
結束語
關於實體的混淆
XML 有許多類型的實體,“實體” 這個術語產生了許多混淆。不幸的是,這些混淆影響了 Firefox 的文檔和討論。我在 Mozilla FAQ 和一些 bugzilla 條目中找到了這樣的混淆。
下面是一些重要的實體類型,以及 Mozilla 和 Firefox 中提供的支持。
字符實體:完全支持。
內部一般實體(聲明為字面的良構的 XML 片段):只要在內部 DTD 子集中定義,就完全支持。
外部解析的一般實體(聲明為對外部資源的引用):不支持(忽略)。
參數實體(DTD 片段):不支持(忽略)。
未解析的實體:不支持(忽略)。
可以看到,Firefox 有許多功能。可以在簡化的邏輯視圖中或以原始的源代碼形式查看 XML。Firefox 會報告任何良構性錯誤。可以使用 CSS 或 XSLT 來調整顯示。Firefox 可以根據 MIME 類型識別出幾種重要的 XML 詞匯表並進行相應的處理。Firefox 在處理 XML 方面有一些限制。所有主流浏覽器在 XML 支持方面都還需要改進,理解它們的能力和限制是很重要的。隨著基於 XML 的技術(比如 Web feeds、SVG 和 XSLT)日益重要,可以期待浏覽器中的 XML 支持會越來越好。目前已經可以在 Firefox 中對 XML 進行許多處理。IBM developerWorks 上這個系列中以後的文章會介紹更多內容。
總的來說,Firefox 對 DTD 的內部子集進行檢查來識別內部一般實體,從而正確地處理它們。所有其他非字符實體類型都被忽略,而且不進行檢驗,即使對於內部子集中的聲明。