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

developerWorks 中国  >  XML | Open source  >

技巧:在 XSLT 2.0 中创建多个文件

使用单个 XSLT 模板创建多个文件

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

Jack Herrington (jack_d_herrington@codegeneration.net), 主编, Code Generation Network

2005 年 4 月 01 日

对于比较复杂的数据集,需要从多角度地观察它。比方说一个 QA 测试系统;它有一组试题和答案,您可能需要按照日期、测试类型或者自测等方式来观察数据。每个视图都要有自己的 HTML 文件。那么在 XSLT 2.0 中,能不能用一个模板从输入数据集中生成多个 HTML 文件呢?

XSLT 的第一个版本有很大的局限性,只能有一个输入和一个输出(虽然可以有多个模板文件)。该标准的第 2 版仍然要求一个输入,但是输出系统更加灵活了。现在可以使用 xsl:result-document 指令产生多个输出文件。这一新的标签有两个重要属性,如表 1 所示。

表 1. xsl:result-document 属性

属性 说明
href 输出文件的文件名或者完全限定的 URL
format 使用的格式名,如对应 xsl:output 指令中所定义的

为了试验该指令,我设计了一个输入 XML 文件,包括一组测试结果(参见清单 1)。


清单 1. 输入 XML 文件
				
<?xml version="1.0" encoding="UTF-8"?>
<tests>
    <testrun run="test1">
        <test name="foo" pass="true" />
        <test name="bar" pass="true" />
        <test name="baz" pass="true" />
    </testrun>
    <testrun run="test2">
        <test name="foo" pass="true" />
        <test name="bar" pass="false" />
        <test name="baz" pass="false" />
    </testrun>
    <testrun run="test3">
        <test name="foo" pass="false" />
        <test name="bar" pass="true" />
        <test name="baz" pass="false" />
    </testrun>
</tests>

这段 XML 非常简单。每个测试运行中都有一组带有 pass 标记的指定测试,用以说明测试是否成功。





回页首


为每个测试创建一个文件

首先为每个测试结果创建一个文件,XSL 模板如清单 2 所示。


清单 2. 为每个测试创建文件的代码
				
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  version="2.0">
<xsl:output method="text"/>
<xsl:output method="html" indent="yes" name="html"/>
<xsl:template match="/">
<xsl:for-each select="//testrun">
<xsl:variable name="filename"
  select="concat('output1/',@run,'.html')" />
<xsl:value-of select="$filename" />  <!-- Creating  -->
<xsl:result-document href="{$filename}" format="html">
    <html><body>
        <xsl:value-of select="@run"/>
    </body></html>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

有几个地方值得注意,从文件头开始说起。stylesheet 标签的 version 属性被设为 2.0,这样就能够使用 xsl:result-document 标签了。接下来,样式表本身设置 text 作为输出类型。这意味着如果希望让这个文件具有 HTML 格式,那么还需要定义类型 html 的第二个指定格式。我在 xsl:result-document 标签中使用这种格式。

然后使用 xsl:for-each 循环遍历 testrun 标签。在每个标签中使用 variable 标签创建一个新的 $filename 变量,将输出目录名(output1)、 运行名和扩展名 .html 合成一个路径。

然后我使用 value-of 标签和 $filename 变量告诉用户正在创建的文件。再用 xsl:result-document 标签打开新文档输出 HTML。清单 3 显示了运行上述数据文件时的结果。


清单 3. 运行示例数据文件的结果(使用 Saxon)
				
Creating output1/test1.html
Creating output1/test2.html
Creating output1/test3.html    





回页首


获得更好的结果

xsl:result-document 标签的内容按照与模板其他部分相同的方式计算似乎有点不可思议,但确实如此。模板上下文中的所有变量都可以使用。

作为一个例子,我修改了 xsl:result-document 标签中的代码,以便提供关于测试结果的更多信息(参见清单 4)。


清单 4. 更好的 HTML 输出
				
<xsl:result-document href="{$filename}" format="html">
    <html><head>
        <title>Test results - <xsl:value-of select="@run"/></title>
        </head><body>
        <xsl:value-of select="@run"/>  <!-- Run -->
        <table>
            <tr><td>Test</td><td>Pass</td></tr>
        <xsl:for-each select="test">
            <tr><td>
                <xsl:value-of select="@name" />
            </td><td>
                <xsl:value-of select="@pass" />
            </td></tr>
        </xsl:for-each>
        </table>
    </body></html>
</xsl:result-document>

输出结果如清单 5 所示。


清单 5. 改进的 HTML 输出结果
				
<html>
   <head>
      <meta http-equiv="Content-Type" 
            content="text/html; charset=UTF-8">
   
      <title>Test results - test1</title>
   </head>
   <body>
      <!-- Run: test1-->
      <table>
         <tr>
            <td>Test</td>
            <td>Pass</td>
         </tr>
         <tr>
            <td>foo</td>
            <td>true</td>
         </tr>
         <tr>
            <td>bar</td>
            <td>true</td>
         </tr>
         <tr>
            <td>baz</td>
            <td>true</td>
         </tr>
      </table>
   </body>
</html>





回页首


创建索引

最后还需要增加一个索引文件指向输出的所有测试结果。为此,我使用了另一个 xsl:result-document 标签,并将输出硬编码到索引文件中(参见清单 6)。


清单 6. 创建索引文件的代码
				
<!-- Creating the index -->
<xsl:result-document href="output3/index.html" 
  format="html">
 <html><head><title>Test Index</title></head>
  <body>
   <xsl:for-each select="//testrun">
   <a href="{@run}.html"><xsl:value-of select="@run" />
   </a><br/>
   </xsl:for-each>
  </body>
 </html>
</xsl:result-document>

这一段放在为每个测试案例建立 HTML 文件的 xsl:for-each 循环之后。清单 7 显示了得到的索引文件。


清单 7. 索引文件
				
<html>
   <head>
      <meta http-equiv="Content-Type"
        content="text/html; charset=UTF-8">
   
      <title>Test Index</title>
   </head>
   <body><a href="test1.html">test1</a><br>
<a href="test2.html">test2</a><br>
<a href="test3.html">test3</a><br></body>
</html>





回页首


结束语

使用 xsl:result-document 指令可以将一个 XSL 模板从单个数据源输出到多个文件中。这种功能在 XSLT 1.x 属于非标准扩展,为 XSLT 模板创造者打开了新的机会之窗。



参考资料



关于作者

Jack Herrington 是一名有着 20 多年工作经验的杰出工程师,现任 Code Generation Network 公司的主编。他同时也是 Code Generation in Action 一书的作者。您可以通过电子邮件 jack_d_herrington@codegeneration.net 与他联系。




对本文的评价










回页首


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