【问题标题】:How can I create an XML file that is a list of files in a target directory using only Ant and XSLT?如何仅使用 Ant 和 XSLT 创建作为目标目录中文件列表的 XML 文件?
【发布时间】:2013-09-25 13:29:14
【问题描述】:

仅使用 Ant 和 XSLT,我想创建一个 XML 文件,它是特定目录中 XML 文件的列表。

Ant 的concat 任务没有完成这项工作,因为我最终得到了一个不是 XML 的列表——即。它没有单个根元素。

我有一个使用 XSLT Ant 任务应用的 XSLT 文件,该任务使用 collection() 函数。这会产生我想要的结果,但它会尝试对目标目录中的每个文件都这样做——我只想要一个列表。我的 XSLT 正在对目标目录(集合)中的每个文件进行操作——如何限制应用 XSLT 的次数?

这是我目前所拥有的:

XML 文件在目标目录c:\tmp

这是我应用于目标目录中文件的 XSL 文件(使用 Ant XSLT 任务);

 <xsl:template match="/">
    <xsl:call-template name="generatelist" />
</xsl:template>

<xsl:template name="generatelist">
    <xsl:result-document href="list.xml">
        <xsl:element name="list">
            <xsl:element name="dir">
                <xsl:for-each
                    select="collection('file:///C:/tmp?select=*.xml')">
                    <xsl:element name="file">
                        <xsl:attribute name="name">
                            <xsl:value-of select="tokenize(document-uri(.), '/')[last()]" />
                        </xsl:attribute>
                    </xsl:element>
                </xsl:for-each>
            </xsl:element>
        </xsl:element>
    </xsl:result-document>
</xsl:template>

这是生成的 XML 列表:

<list>
    <dir>
        <file name="filename_1.xml"/>
        <file name="filename_2.xml"/>
         . . .
        <file name="filename_n.xml"/>
    </dir>
</list>

谢谢。

画了

添加我正在使用的 Ant XSLT 任务:

<xslt basedir="${staging_2}"
      destdir="${staging_3}" extension=".xml" includes="**/*.xml"
      style="create_list.xsl">     
</xslt>

【问题讨论】:

  • 所以 XSLT 似乎没有任何问题,问题出在调用它的 Ant 代码中。你能发布你的build.xml的相关sn-p吗?
  • 感谢您的快速回复,Ian -- 我已添加 XSLT 任务。
  • 当 XML 文件位于相对路径(例如,在 ${BUILDDIR}/files 而不是 C:\Tmp 中)时,你到底是如何让它工作的?我试过类似collection(iri-to-uri('./files/?select=*.xml'),但不是这样。

标签: xml xslt ant


【解决方案1】:

XSLT 确实不是满足您需求的合适工具。 XSLT 最适合将 XML 转换为新的 XML。然而,在这种情况下,源不是 XML;而是这是一个文件系统目录。

鉴于此,直接生成 XML 就可以了。以下 Ant 脚本使用了第三方 Ant-Contrib 库的 &lt;for&gt; 任务:

<project name="ant-echo-xml" default="run" basedir=".">
    <taskdef resource="net/sf/antcontrib/antlib.xml" />

    <target name="run">
        <property name="dest-xml.file" value="list.xml"/>

        <echo file="${dest-xml.file}"
><![CDATA[<list>
    <dir>
]]></echo>

        <for param="src-xml.absolute-path">
            <fileset dir="my-dir" includes="*.xml"/>
            <sequential>
                <local name="src-xml.basename"/>
                <basename property="src-xml.basename" file="@{src-xml.absolute-path}"/>

                <echo file="${dest-xml.file}" append="yes"
>        <![CDATA[<file name="${src-xml.basename}"/>
]]></echo>
            </sequential>
        </for>

        <echo file="${dest-xml.file}" append="yes"
><![CDATA[    </dir>
</list>
]]></echo>
    </target>
</project>

输出:

<list>
    <dir>
        <file name="filename_1.xml"/>
        <file name="filename_2.xml"/>
    </dir>
</list>

【讨论】:

  • 感谢您的回答,Chad,以及完成这项工作的 Ant 代码。我对 XSLT 更满意,但我保留了您的代码副本以备将来使用。 -- 德鲁
  • 请注意,如果您使用的是 Ant pre-1.8,则需要将 &lt;local&gt; 更改为 &lt;var&gt;(由 ant-contrib 提供)。
【解决方案2】:

由于 XSLT 本身负责枚举文件名,因此您只需运行一次即可,即只给它一个文件用作输入,一个文件用作输出。样式表不使用输入文档中的任何内容,因此只要是 XML,任何输入文件都可以使用,您可以使用样式表本身作为自己的输入。

<xslt style="create_list.xsl" in="create_list.xsl" out="list.xsl" />

并从样式表中删除&lt;xsl:result-document&gt;,使其仅输出到默认结果文档(由out="..." 在build.xml 中指定的文档)。

【讨论】:

  • 太完美了——非常感谢伊恩。我曾考虑过使用某种“虚拟”文件,但我不知道如何将其放入“basedir”,而且我事先不知道“basedir”中文件的名称。使用 .xsl 文件作为虚拟输入是一个好主意。再次感谢。
猜你喜欢
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多