5

问题

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

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

不幸的是,我能找到实现这一目标的唯一方法是有点破解。它是这样工作的,

  1. 使用我从互联网上偷来的随机蚂蚁任务将目录列表写入 xml 文件。
  2. 将 xml 文件输入 xslt 转换,然后可以加载其他目录列表引用的 xml 文件并将它们连接起来。
  3. 删除包含目录列表的临时 xml 文件。

这是蚂蚁脚本

<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 文件更简单的方法来传递文件名列表。

已实施的解决方案

一旦我对 ant 脚本进行了一些额外的调整,Dimitre 的解决方案就非常有效,

<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 加载并使用参数设置目录。

4

1 回答 1

6

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

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

有关详细信息,请参阅我对这个问题的回答

所以,如果 ANT 可以使用合适的 XSLT 2.0 处理器,(我会推荐使用Saxon),那么问题就有了完整的解决方案,使用标准collection()函数。

于 2009-02-01T20:44:05.420 回答