Reputation: 159
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
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
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