Drew
Drew

Reputation: 159

How can I create an XML file that is a list of files in a target directory using only Ant and XSLT?

Using only Ant and XSLT, I'd like to create an XML file that is a list of XML files in a specific directory.

Ant's concat task doesn't do the job as I end up with a list that's not XML -- ie. it doesn't have a single root element.

I have an XSLT file that I apply, using the XSLT Ant task, that uses the collection() function. This produces exactly the result I want, but it tries to do so for each file in the target directory -- I want just one list. My XSLT is operating on every file in the target directory (collection) -- how can I limit the number of tims the XSLT is applied?

Here's what I have so far:

XML files are in the target directory c:\tmp

This is the XSL file that I apply to the files in the target directory (using the Ant XSLT task);

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

And this is the resulting XML list:

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

Thanks.

Drew

Adding the Ant XSLT task that I'm using:

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

Upvotes: 1

Views: 5602

Answers (2)

Chad Nouis
Chad Nouis

Reputation: 7051

XSLT really isn't the appropriate tool for your needs. XSLT is best for transforming XML into new XML. In this case, however, the source isn't XML; it's a filesystem directory.

Given this, it's fine to just generate the XML directly. The following Ant script uses the third-party Ant-Contrib library's <for> task:

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

Outputs:

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

Upvotes: 3

Ian Roberts
Ian Roberts

Reputation: 122394

Since the XSLT itself takes care of enumerating the file names you just need to run it once, i.e. give it just one file to use as input and one file to use as output. The stylesheet doesn't use anything from the input document so any input file will do as long as it's XML, you could use the stylesheet itself as its own input.

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

and remove the <xsl:result-document> from the stylesheet so it just outputs to the default result document (the one specified by out="..." in build.xml).

Upvotes: 1

Related Questions