3.8 XSL转换
XSL转换(XSLT)机制可以指定将XML文档转换为其他格式的规则,例如,转换为纯文本、XHTML或任何其他的XML格式。XSLT通常用来将某种机器可读的XML格式转译为另一种机器可读的XML格式,或者将XML转译为适于人类阅读的表示格式。
你需要提供XSLT样式表,它描述了XML文档向某种其他格式转换的规则。XSLT处理器将读入XML文档和这个样式表,并产生所要的输出(参见图3-7)。
XSLT规范很复杂,已经有很多书描述了该主题。我们不可能讨论XSLT的全部特性,所以我们只能介绍一个有代表性的例子。你可以在Don Box等人合著的《Essential XML》一书中找到更多的信息。XSLT规范可以在http://www.w3.org/ TR/xslt获得。
假设我们想要把有雇员记录的XML文件转换成HTML文件。请看这个输入文件:
在我们的例子中,xsl:output元素将方法设定为HTML。而其他有效的方法设置是xml和text。
下面是一个典型的模板:
match属性的值是一个XPath表达式。该模板声明:每当看到XPath集/staff/ employee中的一个节点时,将做以下操作:
1)产生字符串
换句话说,该模板会生成围绕每条雇员记录的HTML表格的行标记。
XSLT处理器以检查根元素开始其处理过程。每当一个节点匹配某个模板时,就会应用该模板(如果匹配多个模板,就会使用最佳匹配的那个,详情请参见 http://www.w3.org/TR/xslt)。如果没有匹配的模板,处理器会执行默认操作。对于文本节点,默认操作是把它的内容囊括到输出中去。对于元素,默认操作是不产生任何输出,但会继续处理其子
节点。
下面是一个用来转换雇员记录文件中的name节点的模板:

正如你所见,模板产生定界符
...,并且让处理器递归访问name元素的子节点。它只有一个子节点,即文本节点。当处理器访问该节点时,它会提取出其中的文本内容(当然,前提是没有其他匹配的模板)。如果想要把属性值复制到输出中去,就不得不再做一些稍微复杂的操作了。下面是一个例子:

当处理hiredate节点时,该模板会产生:
1)字符串
2)year属性的值
3)一个连字符
4)month属性的值
5)一个连字符
6)day属性的值
7)字符串
xsl:value-of语句用于计算节点集的字符串值,其中,节点集由select属性的XPath值指定。在这个例子中,路径是相对于当前正在处理的节点的相对路径。节点集通过将各个节点的字符串值连接起来而被转换成一个字符串。属性节点的字符串值就是它的值,文本节点的字符串值是它的内容,元素节点的字符串值是它的所有子节点(而不是其属性)的字符串值的连接。
程序清单3-13包含了将带有雇员记录的XML文件转换成HTML表格的样式表。

程序清单3-14显示了一组不同的转换。其输入是相同的XML文件,其输出是我们熟悉的属性文件格式的纯文本。
程序清单3-14 transform/makeprop.xsl
该示例使用position()函数来产生以其父节点的角度来看的当前节点的位置。我们只要切换样式表就可以得到一个完全不同的输出。这样,就可以安全地使用XML来描述数据了,即便一些应用程序需要的是其他格式的数据,我们只要用XSLT来产生对应的可替代格式即可。
在Java平台下产生XML的转换极其简单,只需为每个样式表设置一个转换器工厂,然后得到一个转换器对象,并告诉它把一个源转换成结果。
你可以从一个文件、流、阅读器或URL中构建StreamSource对象,或者从DOM树节点中构建DOMSource对象。例如,在上一节中,我们调用了如下的标识转换:
在示例程序中,我们做了一些更有趣的事情。我们并不是从一个现有的XML文件开始工作,而是产生一个SAX XML阅读器,通过产生适合的SAX事件,给人以解析XML文件的错觉。实际上,XML阅读器读入的是一个如第2章所描述的扁平文件,输入文件看上去是这样的:
处理输入时,XML阅读器将产生SAX事件。下面是实现了XMLReader接口的EmployeeReader类的parse方法的一部分代码:
这是一个将非XML的遗留数据转换成XML的一个小技巧。当然,大多数XSLT应用程序都已经有了XML格式的输入数据,只需要在一个StreamSource对象上调用transform方法即可,例如:
程序清单3-15包含了完整的源代码。
程序清单3-15 transform/TransformTest.java
我们以该示例结束对Java库中的XML支持特性的讨论。现在,你应该对XML的强大功能有了很好的了解,尤其是它的自动解析、验证和强大的转换机制。当然,所有这些技术只有在你很好地设计了XML格式之后才能发挥作用。你必须确保那些格式足够丰富,能够表达全部业务需求,随着时间的推移也依旧稳定,你的业务伙伴也愿意接受你的XML文档。这些问题要远比处理解析器、DTD或转换更具挑战。
在下一章,我们将讨论在Java平台上的网络编程,从最基础的网络套接字开始,逐渐过渡到用于E-mail和万维网的更高层协议。