请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。
几年前,许多开发人员很看好 XML、XSLT、Extensible HTML (XHTML)和其他一些基于标记的语言。现在,Asynchronous JavaScript and XML(AJAX)成了新的热点,人们又将目光转向了使用 JavaScript 代码的数据驱动的富 Internet 应用程序。但是开发人员是否已经消除了 XML 和这一新技术之间的鸿沟呢?
当然,您可以在 Web 客户机中使用 XML 解析器来读取数据,但这种做法会带来两个问题。第一,出于安全方面的原因,XML 数据只能从与此页面相同的那个域中读取。这虽然不是什么大的限制因素,但它的确会引起部署方面的问题,还会阻碍 DHTML 小部件的创建。第二,读取和解析 XML 会非常慢。
另一种做法是让服务器执行 XML 的解析工作,方法是设置服务器,使之向浏览器发送以 JavaScript 代码或时下流行的 JavaScript Object Notation(JSON)编码的数据。本文将展示如下三种使用 XSLT V2 语言和 Saxon XSLT V2 处理器从 XML 数据生成 JSON 的技巧:
JSON 简介要学习如何将数据编码成 JSON(它只是 JavaScript 的一个子集),最好的方法是从数据开始。 显示了书籍列表的一个示例 XML 数据集。
清单 1. 基本的图形化图书馆<?xml version="1.0" encoding="UTF-8"?> <books> <book> <title>Code Generation in Action</title> <author><first>Jack</first><last>Herrington</last></author> <publisher>Manning</publisher> </book> <book> <title>PHP Hacks</title> <author><first>Jack</first><last>Herrington</last></author> <publisher>O'Reilly</publisher> </book> <book> <title>Podcasting Hacks</title> <author><first>Jack</first><last>Herrington</last></author> <publisher>O'Reilly</publisher> </book> </books>
这个数据集很简单,只包含三本书,每本书都具有惟一的 ID、书名、作者姓名及出版商的名字。(没错,我只选择了我自己的书作为数据集,但能怨我吗?这些书实在是不可多得的节日和生日礼物。)
显示了这些数据在 JSON 中的效果。
清单 2. JSON 中的示例数据集[ { id: 1, title: 'Code Generation in Action', first: 'Jack', last: 'Herrington', publisher: 'Manning' }, ... ]
方括号 ([]) 表明这是一个数组。大括号 ({}) 则表明这是一个散列表,该散列表由一组名称和值对组成。在本例中,我创建了一个散列表的数组 —— 用来存储这类结构式数据的一种常见方法。
另外一点值得注意的是字符串是通过单引号或双引号被编码的。所以,如果我想用单引号编码 O'Reilly,我就必须使用反斜杠对它进行转义:'O\'Reilly'。 这让我编写的这个 XSLT 样式表更为有趣了一些。
我并未在本例中放上任何日期,但您也可以通过如下两种方法来编码日期。第一种方法是将日期作为字符串,该字符串必须在后面被解析。第二种方法是将日期作为一个对象,比如:
publishdate: new Date( 2006, 6, 16, 17, 45, 0 )
这段代码将 publishdate 的值设置为6/16/2006 5:45:00 p.m.。
简单编码接下来我将陆续介绍 JSON 编码的几种技巧。第一种也是其中最简单的一种,此样式表如 所示。
清单 3. simple.xsl 样式表<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:js="http://muttmansion.com"> <xsl:output method="text" /> <xsl:function> <xsl:param /> <xsl:value-of select='replace( $text, "'", "\\'" )' /> </xsl:function> <xsl:template match="/"> var g_books = [ <xsl:for-each select="books/book"> <xsl:if test="position() > 1">,</xsl:if> { id: <xsl:value-of select="@id" />, name: '<xsl:value-of select="js:escape(title)" />', first: '<xsl:value-of select="js:escape(author/first)" />', last: '<xsl:value-of select="js:escape(author/last)" />', publisher: '<xsl:value-of select="js:escape( publisher )" />' }</xsl:for-each> ]; </xsl:template> </xsl:stylesheet>
要理解此样式表,不妨先来看一下 所示的输出。
清单 4. simple.xsl 的输出var g_books = [ { id: 1, name: 'Code Generation in Action', first: 'Jack', last: 'Herrington', publisher: 'Manning' }, { id: 2, name: 'PHP Hacks', first: 'Jack', last: 'Herrington', publisher: 'O\'Reilly' }, { id: 3, name: 'Podcasting Hacks', first: 'Jack', last: 'Herrington', publisher: 'O\'Reilly' } ];
这里,我将名为 g_books 的变量设置为一个包含三个散列表的数组,每个散列表包含关于该书的信息。再回过头来看看 ,您会发现第一个模板匹配 "/" 路径,它也是首先应用到输入数据集的模板,该模板使用 for-each 循环来遍历每本书。之后,它使用 <value-of> 标记来将文本从该数据输出到 JavaScript 输出代码。
对于字符串,我使用名为 js:escape() 的定制函数,它在模板之前定义。该函数使用一个正则表达式将一个单引号标记更改为带有反斜杠的单引号标记。
最后一个重要的元素是 <xsl:output> 标记,它告知处理器要输出的是文本而不是 XML。要检验此过程是否可以正常工作,我加入了一个 simple .html 文件,该文件引用我在 simple.js 保存的 XSL 样式表的输出。这个 HTML 文件如 所示。
清单 5. simple.html 文件<html> <head> <title>Simple JS loader</title> <script src="simple.js"></script> </head> <body> <script> document.write( "Found "+g_books.length+" books" ); </script> </body> </html>