XSL 样式表和特定于处理器的特性
这篇技巧介绍了如何编写这样的样式表,它在利用特定于处理器的特性的同时又能保持可移植性。
XSLT 在保证跨平台和处理器的互操作性方面确实做得很好。把样式表移植到新的处理器通常只需要复制文件就可以了。但是有时候仍然需要针对给定的处理器放弃一些可移植性并调整样式表。这篇技巧说明如何测试所运行的平台并相应地调整代码。
需要什么样的可移植性?
为何要放弃可移植性呢?一个原因可能是由于需要使用 XSLT 1.0 不支持的函数——比如向多文档输出或者创建中间结果树的能力。对于给定的处理器,工作方式总是特殊的。
另外一个原因可能是由于需要做一些特定于平台的事情。比如,我最近编写了一个处理文件名的样式表。因为文件分隔符对于每种平台都是惟一的(所有的 UNIX 变体都使用 " / ",Windows 下是 " \ ",而 MacOS 标准是 " : "),所以样式表只能针对具体平台。
无论什么原因,最好是把特定于平台的代码隔离在一个模板、变量或者参数中,以便容易移植到其他的平台。理想的方案是测试样式表中使用的是何种处理器并切换到相应的代码段。测试平台需要使用 system-property() 函数。
顾名思义, system-property() 返回特定于系统的属性值。XSLT 标准定义了以下三个属性:
xsl:version :处理器所支持的 XSL 版本(目前是 1.0)
xsl:vendor :处理器的供应商
xsl:vendor-url :用于确定处理器供应商的 URL
处理器供应商完全可以识别更多的属性。多数 Java 处理器还返回 Java 系统属性,其中包括:
java.version :所使用的 JVM 版本
java.vendor :JVM 制造商
os.name :所使用的 OS
file.separator :依赖于系统的文件分隔符
还定义了许多其他的属性,完整的属性列表请参阅 参考资料。
system-property() 在工作
清单 1 给出了 system-property() 的一个应用程序。样式表通过查询 xsl:vendor 和其他属性试图猜测系统所用的文件分隔符。样式表在 file-separator 参数中保存结果。逻辑如下:
- 如果供应商是 Microsoft 或 Altova (二者都是众所周知的 Windows 处理器),则假定为 Windows 系统的分隔符(
/ )。
- 如果处理器接受 Java 属性,则查询
file.separator 属性。该属性对多数 Java 处理器都是有效的,如 Xalan 或 Saxon。
- 如果处理器是 XT,则使用所有权扩展机制检索
file.separator 属性的值。
- 如果所有的测试都失败,则停止。
清单 1. 测试环境的样式表
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xm="http://www.ananas.org/2001/XM/Walk/Directory"
version="1.0">
<xsl:output method="html"/>
<xsl:param name="file-separator">
<xsl:variable name="vendor"
select="system-property('xsl:vendor')"/>
<xsl:choose>
<!-- two well-known XSLT processors for Windows -->
<xsl:when test="contains($vendor,'Microsoft')
or contains($vendor,'Altova')">
<xsl:text>\</xsl:text>
</xsl:when>
<!-- the processor returns Java properties -->
<xsl:when
test="string-length(system-property('java.version')) != 0">
<xsl:value-of select="system-property('file.separator')"/>
</xsl:when>
<!-- the processor is XT, use an extension -->
<xsl:when test="contains($vendor,'James Clark') and
function-available('xt-sys:getProperty')"
xmlns:xt-sys="http://www.jclark.com/xt/java/java.lang.System">
<xsl:value-of select="xt-sys:getProperty('file.separator')"/>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">unknown file separator</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:param>
<xsl:template match="xm:Directory">
<html>
<head><title>File list</title></head>
<body><ul><xsl:apply-templates/></ul></body>
</html>
</xsl:template>
<xsl:template match="xm:File">
<li><a href="file:{.}">
<xsl:call-template name="extract-fname">
<xsl:with-param name="path" select="."/>
</xsl:call-template>
</a></li>
</xsl:template>
<xsl:template name="extract-fname">
<xsl:param name="path"/>
<xsl:choose>
<xsl:when test="contains($path,$file-separator)">
<xsl:call-template name="extract-fname">
<xsl:with-param name="path"
select="substring-after($path,$file-separator)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$path"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
|

 |

|
结束语
理想情况下永远不需要特定于处理器的代码,但我们不是生活在一个完美的世界。次佳的方案是把特定于处理器的代码隔离在一个变量、参数或者模板中。当把样式表移植到不同的处理器时使用 system-property() 。
原文地址:http://www.ibm.com/developerworks/cn/xml/x-tipproc/index.html
标题: XSL 样式表和特定于处理器的特性
关键字:处理器 样式 属性 system-property
|