博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

在客户端进行xslt对xml的xuan渲染

Posted on 2007-04-19 12:42  daniel-shen  阅读(726)  评论(0编辑  收藏  举报

链接样式表与脚本转换

如果使用 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
            <?xml version="1.0" encoding="utf-8"?>
            <catalog>
            >cd>
            <title>Empire Burlesque</title>
            <artist>Bob Dylan</artist>
            <country>USA</country>
            <company>Columbia</company>
            <price>10.90</price>
            <year>1985</year>
            </cd>
            <cd>
            <ttitle>Hide your heart</title>
            <artist>Bonnie Tyler</artist>
            <country>UK</country>
            <company>CBS Records</company>
            <price>9.90</price>
            <year>1988</year>
            </cd>
            <cd>
            . . .
            <catalog>
            

然后再从 W3Schools 下载 cdcatalog.xsl,如 清单 2 所示。该样式表生成一个 HTML 文件表格,按照在文档中存在的顺序(如果需要也可以在转换中增加排序)列出了收藏的 CD。


清单 2. cdcatalog.xsl
            <?xml version="1.0" encoding="ISO-8859-1"?>
            <xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:template match="/">
            <html>
            <body>
            <h2>My CD Collection</h2>
            <table border="1">
            <tr bgcolor="#9acd32">
            <th align="left">Title</th>
            <th align="left">Artist</th>
            </tr>
            <xsl:for-each select="catalog/cd">
            <tr>
            <td><xsl:value-of select="title" /></td>
            <td><xsl:value-of select="artist" /></td>
            </tr>
            </xsl:for-each>
            </table>
            </body>
            </html>
            </xsl:template>
            </xsl:stylesheet>
            

然后建立 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
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
            <html>
            <body>
            <script type="text/javascript" src="ajax.js"> </script>
            <script type="text/javascript">
            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);
            }
            </script>
            <div id="example"/>
            </body>
            <script  type="text/javascript">
            render("example")
            </script>
            </html>
            

图 1 显示了在 Firefox 浏览器中的执行结果。在 Opera 上应该也能正常运行。但是在 Internet Explorer 6.0 或更低版本中不能工作,因为缺少 XSLTProcessor 对象。


图 1. W3Schools 脚本例子在 Firefox 中的运行结果
W3Schools 脚本例子在 Firefox 中的运行结果

清单 5 显示的 catalogIE.html 按照 Internet Explorer 的方式执行同样的转换。该页面只能在 Internet Explorer 中打开,而不能用于 Firefox 或 Opera。如何将两个 JavaScript 控制的转换结合起来留给读者作为练习。如果使用 JavaScript 执行客户端转换,应小心地处理和测试浏览器的依赖问题。


清单 5. catalogIE.html
            <html>
            <body>
            <script type="text/javascript">
            // 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))
            </script>
            </body>
            </html>