使用ant和xslt动态连接xml文件

时间:2009-02-01 16:52:04

标签: xml xslt ant saxon

问题

我们需要在构建时将大量xml配置文件合并到一个主版本中。较小的配置文件更容易维护,一个大文件加载更快,所以我想这是一个流行的构建转换过程,我会在网上找到很多很好的例子。

我能够找到问题的一部分here at StackOverflow的一些好的解决方案,但它们都依赖于知道需要合并的xml文件的名称。这对我来说似乎是一种不必要的开销。应该可以编写一个构建脚本,它可以动态计算需要哪些输入xml文件。

不幸的是,我能找到实现这一目标的唯一方法就是有点黑客攻击。它的工作原理如下,

  1. 使用随机的ant任务我偷了互联网,将目录列表写入xml文件。
  2. 将xml文件导入xslt转换,然后加载另一个列出引用的xml文件的目录并将它们连接起来。
  3. 删除包含目录列表的临时xml文件。
  4. 这是蚂蚁脚本

    <taskdef name="xml-dir-list"
      classname="net.matthaynes.xml.dirlist.AntFileListing"
      classpath="antlib/xml-dir-listing.0.1.jar;
        antlib/jakarta-regexp-1.5.jar;antlib/log4j-1.2.14.jar"/>
    
    <macrodef name="build-plugin-xml" description="todo">
        <attribute name="pluginName"/>
    
        <xml-dir-list depth="0" verbose="false" 
          srcDir="${src.dir}/@{pluginName}/forms/" includesRegEx="\.xml$" 
          destFile="${src.dir}/@{pluginName}/forms/fileList.xml"/>
    
        <xslt in="${src.dir}/forms/fileList.xml"
          out="${src.dir}/@{pluginName}/@{pluginName}_extn.yuix
          style="${src.dir}/@{pluginName}/forms/extn.yuix.xsl" />
    
        <delete file="${src.dir}/@{pluginName}/forms/fileList.xml"/>
    </macrodef>
    

    这是样式表,

    <xsl:stylesheet version="1.0" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
        <xsl:template match="/">
            <Forms applicationId="YFSSYS00011">
                <GlobalExtensions>
                    <Tasks/>
                </GlobalExtensions> 
                <xsl:apply-templates select="directory/file"/>
            </Forms>
        </xsl:template>
    
        <xsl:template match="file">
            <xsl:copy-of select="document(@name)/Forms/Form"/>
        </xsl:template>
    </xsl:stylesheet>
    

    有没有人找到一种更简单的方法来实现在XSLT中合并哪些文件的动态发现? XSLT无法直接读取目录并不奇怪,但我希望找到一种更简单的方法来传递文件名列表,而不是通过另一个xml文件。

    已实施解决方案

    一旦我对蚂蚁脚本做了一些额外的调整,

    Dimitre's solution工作得很好,

    <taskdef name="saxon-xslt" classname="net.sf.saxon.ant.AntTransform"
      classpath="antlib/saxon9.jar;antlib/saxon9-ant.jar"/>
    

    [...]

    <macrodef name="build-plugin-xml" description="todo">
        <attribute name="pluginName"/>
    
        <saxon-xslt 
          in="build.xml"
          out="${compca.src.dir}/temp/@{pluginName}/@{pluginName}_extn.yuix"
          style="antscripts/extn.yuix.xsl">
        <param name="formsDir" 
          expression="${compca.src.dir}/@{pluginName}/forms/"/>
        </saxon-xslt>
    </macrodef>
    

    和xsl样式表(我移动了)

       <xsl:stylesheet version="1.0" 
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:param name="formsDir" />
            <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
            <xsl:template match="/">
                <Forms applicationId="YFSSYS00011">
                    <GlobalExtensions>
                        <Tasks/>
                    </GlobalExtensions>
                    <xsl:apply-templates select=
                      "collection(
                      concat('file:///',
                      $formsDir,
                      '?select=*.yuix;recurse=yes;on-error=ignore'
                      )
                      )/*
                    "/>
                </Forms>
    
            </xsl:template>
    
            <xsl:template match="file">
                <xsl:copy-of select="/Forms/Form"/>
            </xsl:template>
        </xsl:stylesheet>
    

    这些调整只是让Saxon9加载并使用参数设置目录。

1 个答案:

答案 0 :(得分:6)

  

有没有人找到更简单的方法   实现这种动态发现的东西   要在XSLT中合并的文件?不是   令人惊讶的是,XSLT无法读取   目录直接,但我希望   找到一种更简单的传递途径   文件名列表比通过   另一个xml文件。

使用XPath 2/0 / XSLT 2.0 可以动态发现和处理XML文件。更具体地说,必须使用XPath 2.0 collection()函数。

有关详细信息,请参阅my answer to this question

因此,如果ANT可以使用合适的XSLT 2.0处理器,(我建议使用Saxon),问题有一个完整的解决方案,使用标准collection()功能。