圖 1. 加載清單 2 之後的浏覽器顯示
單擊鏈接,就立刻獲得最新的顯示,如 圖 2 所示。
圖2. 加載清單 2 並單擊鏈接之後的浏覽器顯示
對 XML 主文檔使用腳本
在本系列的第一部分中,我介紹了如何在 Firefox 中浏覽 XML 文件。要在這種情況下使用 Javascript,需要在腳本文件中嵌套一個引用。清單 3(designers.xml)顯示的示例 XML 文件是一個設計師列表。XML 引用獨立的 CSS 文件來顯示 XML,引用獨立的 JavaScript 文件來創建鏈接元素。
清單 3.(designers.xml)表示時裝設計師鏈接的 XML 格式
<?XML version='1.0' encoding='utf-8'?>
<?XML-stylesheet type="text/css" href="designers.CSS"?>
<designers>
<blurb>
<designer homepage="http://doria.co.uk">Doria Ltd.</designer>
of London
</blurb>
<blurb>
<designer homepage="http://samsara.biz">Samsara Saris</designer>
of Mumbai
</blurb>
<blurb>
<designer homepage="http://pcp.co.uk">Pikeman Camouflage, Plc.</designer>
of London
</blurb>
<blurb>
<designer homepage="http://mandalay.co.jp">Mandalay</designer>
of Tokyo
</blurb>
<xhtml:script XMLns:xhtml="http://www.w3.org/1999/xHtml"
src="designers.JS"
type="application/Javascript"/>
</designers>
樣式表處理指令提供顯示 XML 的基本指令。清單 4(designers.css)顯示 CSS。
清單 4.(designers.css)修飾清單 3 中 XML 格式基本顯示的 CSS
* { display: inherit; }
designers { display: block; }
blurb {
margin: 1em;
width: 20em;
}
a {
display: inline;
text-decoration: none;
color: green;
border: thin blue solid;
}
script { display: none; }
樣式表通知浏覽器把 designers 和 blurb 作為塊區域,而忽略用於顯示的 script 元素。通過將鏈接(a 元素)和可見的提示一同顯示,可以更容易識別出鏈接。您將注意到在 XML 源文件中不存在 a 元素。因此,這裡要用到腳本。Javascript 代碼使用 XHTML 鏈接元素代替 designer 元素。XHTML 鏈接元素通過一個 XHtml 腳本元素提供,因此只要使用到 Firefox,就可以嵌入任何 XML(當然,您可能會遇到模式兼容性的問題)。Firefox 在載入的文檔中遇到腳本後就運行它們,因此要把腳本放在所有待處理的元素之後。清單 5(designers.JS)顯示了 JavaScript 代碼。
清單 5.(designers.JS)將 XML 元素從清單 3 轉換為 XHtml 鏈接的腳本
//Save the XHtml namespace for when you need it
var xhtmlns = "http://www.w3.org/1999/xHtml";
//get all elements named "blurb" in the document
//The first "" indicates no namespace for the element we're seeking
var blurbs = document.getElementsByTagNameNS("", "blurb");
//Loop over each element we found
for (var i=0; i < blurbs.length; i++)
{
//retrIEve the blurb element from the collection
var blurb = blurbs[i];
//Get the designer element within the blurb
//Assumes only one designer element per blurb
var designer = blurb.getElementsByTagNameNS("", "designer").item(0);
//In DOM the text in designer is actually a text node object child
//of blurb. The link title is the value of this text node
//Assumes the text node is normalized
var link_title = designer.firstChild.nodeValue;
//Link URL is the homepage attribute of designer, in no namespace
var link_url = designer.getAttributeNS("", "homepage");
//Create a new XHtml namespace link element
var xhtml_link = document.createElementNS(xHtmlns, "a");
//Create a new text node with the link title
var new_text_node = document.createTextNode(link_title);
//Set the href attribute to the link URL
xHtml_link.setAttributeNS("", "href", link_url);
//Attach the text node with the link title to the XHtml link
xHtml_link.appendChild(new_text_node);
//Replace the designer element with the new XHtml link element
blurb.replaceChild(xHtml_link, designer);
}
因為 清單 5 中的腳本可以支持名稱空間(尤其是其中的 XHtml 名稱空間),所以我使用支持名稱空間的 DOM 方法。圖 3 顯示查看 清單 3 的結果。可以看到,浏覽器立即應用 CSS 和腳本。
圖 3. 加載清單 3 的浏覽器顯示
調用 XSLT
使用 JavaScript 可以訪問大多數的浏覽器功能,其中包括 XSLT 引擎。清單 6 是一個執行 XSLT 轉換的腳本片段。
清單 6. 加載 XML 文檔和 XSLT 轉換並執行轉換的 JavaScript 代碼//Create an XSLT processor instance
var processor = new XSLTProcessor();
//Create an empty XML document for the XSLT transform
var transform = document.implementation.createDocument("", "", null);
//Load the XSLT
transform.onload = loadTransform;
transform.load("display.xslt");
//Triggered once the XSLT document is loaded
function loadTransform(){
//Attach the transform to the processor
processor.importStylesheet(transform);
source = document.implementation.createDocument("", "", null);
source.load("source.XML");
source.onload = runTransform;
}
//Triggered once the source document is loaded
function runTransform(){
//Run the transform, creating a fragment output subtree that
//can be inserted back into the main page document object (given
//in the second argument)
var frag = processor.transformToFragment(source, document);
//insert the result subtree into the document, using the target element ID
document.getElementById('updateTarget').appendChild(frag);
}
如果想創建整個輸出文檔,而不是創建插入到其他文檔的子樹,使用 transformToDocument 方法代替 transformToFragment 方法。
結束語
首先是一份重要的免責聲明:XML 的 Web 腳本語言還沒有完全標准化。文中涉及的很多內容並不是跨浏覽器標准化的。由於本系列主要關注 Firefox,文中沒有介紹其他浏覽器需要做的修改,但是您可以繼續了解如何修改以適合各種用戶界面。XML 甚至是 XSLT 的 JavaScript 操作都可使用跨浏覽器庫。如果不能專門針對基於 Mozila 的浏覽器進行開發,那麼可以使用跨浏覽器庫。處理 Web 腳本時,必須要考慮可訪問性。同時,要注意內容、處理和顯示的分離,避免在最後一刻才將引用嵌入到腳本中。另外,也可以保存和管理不包含這類引用的 XML,在將 XML 傳送給浏覽器之前,插入這些引用。
現在,您已經了解如何在 Web 腳本中加載和處理一個獨立的 XML 文件,如何從 XML 主文檔中調用腳本,以及如何從腳本中調用 XSLT 處理器。因為 Javascript 支持所有浏覽器特性,因此可以使用它進行更多 XML 處理。可以將學過的各種腳本編制技術,例如動態 HTML(DHtml),應用到 XML 處理中。ECMAScript for XML (E4X) 是一組對 Javascript 的語言增強(從技術上講,是 ECMAScript),使 JavaScript 的 XML 處理更容易。這個新標准為 XML 處理添加了專門的用法。Firefox 1.5 支持 E4X,我將在以後的文章中對它進行介紹。不用犧牲 XML 的強大的結構特性,適度和精心設計的腳本可以展現現代 Web 應用程序的全部魅力。