如果使用 XSLT 转换把数据呈现为 HTML 并决定在客户端执行 XSLT 转换,还需要做进一步的选择。XML 数据文档可以使用链接样式表。这种情况下,浏览器将尝试加载该样式表、执行转换并呈现结果。但 XML 文档是数据。不应该规定它的可视化呈现。实际上,它有可能在应用程序的不同地方呈现为不同的形式。比如,一个页面可能像 清单 1 那样显示整个 CD 目录,而下一个页面可能通过层层选择只显示 Bonnie Tyler 的 CD。
可以将视图和数据分开,通过客户机 JavaScript 执行转换。JavaScript 决定执行什么样的转换或者通过提供转换参数来控制它。
这里判断浏览器的类型非常重要。Internet Explorer 6.0 及以下版本通过私有的 ActiveX 控件执行 XSLT,而 Mozilla 和 Opera 使用内建的 XSLTProcessor 对象。Internet Explorer 7.0 将支持 XSLTProcessor,但是您不能指望整个公共 Web 社区都装上了新的浏览器。
另一方面,如果企业 WAN 指定了某种浏览器,就可以把内部应用程序设计成与这种浏览器捆绑在一起。当然,如果企业要发布新的指定,您可能会后悔引入了这种依赖性。这些是在设计应用程序时必须要考虑和权衡的。
我们用脚本来实现一个 XSLT 转换。可以从 W3Schools 获得 清单 1 所示的 cdcatalog.xml(详情参阅 参考资料)。
清单 1. cdcatalog.xml
>cd>
Empire BurlesqueBob Dylan
USA
Columbia
10.90
1985
Hide your heart
Bonnie Tyler
UK
CBS Records
9.90
1988
. . .
然后再从 W3Schools 下载 cdcatalog.xsl,如 清单 2 所示。该样式表生成一个 HTML 文件表格,按照在文档中存在的顺序(如果需要也可以在转换中增加排序)列出了收藏的 CD。
清单 2. cdcatalog.xsl
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
My CD Collection
Title | Artist |
---|---|
然后建立 ajax.js 脚本,如 清单 3 所示,保存在和 XML 文件与 XSL 文件相同的工作目录中。该脚本是独立于浏览器的。Mozilla 或 Opera 浏览器使用的 createRequest 函数返回一个 XMLHttpRequest 对象,通过 URL 请求一个文件。请注意,对于 Internet Explorer 浏览器,它返回一个 Microsoft ActiveX® 对象。
清单 3. ajax.js
function createRequest() {
var request = null;
try {
request = new XMLHttpRequest();
} catch (tryIE) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (otherIE) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = null;
}
}
}
if (request == null) {
alert("Could not create request object");
} else {
return request;
}
}
现在创建 清单 4 所示的 HTML 文件,其中的 JavaScript 代码创建了两个异步请求对象。它使用一个请求对象加载 XML 文件,另一个请求对象加载 XSL 文件。这些对象不能重用,因此需要两个。
脚本使用 XSLTProcessor 对象应用转换,然后创建 DOM 节点。它将该 DOM 节点插入 HTML div 节点,完成 CD 目录的呈现。要在文档加载过程中调用 render 函数,因此调用必须出现在文档快结束的时候,在 div 标签之后,以便能够访问这个标记。
清单 4. catalog.html
/p>
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
function render(insertionID){
var request1 = createRequest();
var request2 = createRequest();
// load the xslt file
request1.open("GET", "cdcatalog.xsl", false);
request1.send(null);
var xslStylesheet = request1.responseXML;
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xslStylesheet);
// load the xml file
request3.open("GET", "cdcatalog.xml", false);
request2.send(null);
var xmlDoc = request2.responseXML;
var fragment = xsltProcessor.transformToFragment(xmlDoc, document);
document.getElementById(insertionID).innerHTML = "";
document.getElementById(insertionID).appendChild(fragment);
}
render("example")
图 1 显示了在 Firefox 浏览器中的执行结果。在 Opera 上应该也能正常运行。但是在 Internet Explorer 6.0 或更低版本中不能工作,因为缺少 XSLTProcessor 对象。
图 1. W3Schools 脚本例子在 Firefox 中的运行结果
清单 5 显示的 catalogIE.html 按照 Internet Explorer 的方式执行同样的转换。该页面只能在 Internet Explorer 中打开,而不能用于 Firefox 或 Opera。如何将两个 JavaScript 控制的转换结合起来留给读者作为练习。如果使用 JavaScript 执行客户端转换,应小心地处理和测试浏览器的依赖问题。
清单 5. catalogIE.html
// Load XML into Internet Explorer 6.0
var xml = new ActiveXObject("Microsoft.XMLDOM")
xml.async = false
xml.load("cdcatalog.xml")
// Load XSL into Internet Explorer 6.0
var xsl = new ActiveXObject("Microsoft.XMLDOM")
xsl.async = false
xsl.load("cdcatalog.xsl")
// Transform within Internet Explorer 6.0
document.write(xml.transformNode(xsl))