IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  XML  >

技巧: XSL 样式表和特定于处理器的特性

测试所运行的平台并据此调整代码

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 中级

Benoit Marchal (bmarchal@pineapplesoft.com), 顾问, Pineapplesoft

2003 年 11 月 01 日

这篇技巧介绍了如何编写这样的样式表,它在利用特定于处理器的特性的同时又能保持可移植性。

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()



参考资料



关于作者

Author photo

Benoit Marchal是一位比利时籍顾问。他是 XML by Example, Second Edition 和其他 XML 书籍的作者。可以向 Benoit 寻求有关 XML 项目的帮助——可以通过 bmarchal@pineapplesoft.com 或他的个人站点 marchal.com 与他联系。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款