I have a folder of XML files. I'd like to copy some lines from each file into one XML file that I can then use as a lookup. I have an xslt file and an ANT build file but I'm sure there has to be a simple way to do this.
Input files look likes this:
<engine_config>
<eng_family>RK2-1020</eng_family>
<eng_model>RK2-1020</eng_model>
<cd_gek>gek1000</cd_gek>
<version_no>1000</version_no>
<version_name>all</version_name>
<display_name>RK2 1000</display_name>
...lots of other info I don't need
</engine_config>
Desired result:
<gek-lookup>
<engine_config>
<eng_family>RK2-1020</eng_family>
<eng_model>RK2-1020</eng_model>
<display_name>RK2 1000</display_name>
<cd_gek>gek1000</cd_gek>
</engine_config>
<engine_config>
<eng_family>RK2-1021</eng_family>
<display_name>RK2 1001</display_name>
<cd_gek>gek1001</cd_gek>
</engine_config>
etc...
</gek-lookup>
XSLT:
<xsl:template match="/">
<gek-lookup>
<xsl:apply-templates />
</gek-lookup>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="engine_model | eng_family"/>
<xsl:copy-of select="display_name"/>
<xsl:copy-of select="cd_gek"/>
</xsl:copy>
</xsl:template>
This task is creating an XML output file for each input file, but I want all the results to be written to one output file:
<target name="GenerateFileIndex">
<xslt
basedir="configuration-files"
destdir="configuration-files\working"
classpath="${saxon.jar}"
includes="*.xml,*.XML"
excludes="configurations*"
style="build_lookup_file.xsl"
extension=".xml"
out="configuration-files\working\configurations.xml"
force="true">
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
</xslt>
</target>
I created this fileset
but I don't know how to properly use the fileset
with the xslt
task when there is only one output file.
<fileset id="xmlfileset" dir="${config.dir}" casesensitive="no">
<include name="*.XML" />
<exclude name="configurations.xml"/>
</fileset>
This almost works, but it's very slow and it overwrites the previous entry in the output file:
<target name="GenerateFileIndex">
<mkdir dir="${output.dir}"/>
<apply executable="java" failonerror="true">
<arg value="-cp"/>
<arg value="${saxon.jar}"/>
<arg value="net.sf.saxon.Transform"/>
<srcfile/>
<fileset refid="xmlfileset"/>
<arg value="-xsl:${xslt}"/>
<arg value="-o:${output.dir}${file.separator}${gek.index}"/>
</apply>
</target>
Any suggestions are appreciated.
EDIT
I passed the files as a string per Dr. Kay's suggestion. The only issue, I needed to put something for the in
parameter so I hardcoded a file that was in the folder:
<target name="GenerateFileIndex">
<pathconvert pathsep="," property="xmlflist" refid="xmlfileset"/>
<mkdir dir="${output.dir}"/>
<xslt in="${config.dir}/gek108729.xml" extension=".xml"
includes="*.xml,*.XML"
excludes="configuration*"
destdir="${output.dir}" style="${xslt}" out="${output.dir}\${gek.index}">
<param name="xml-config-files" expression="${xmlflist}"/>
</xslt>
</target>
Stylesheet:
<xsl:param name="xml-config-files" as="xs:string*"/>
<xsl:template match="/">
<gek-lookup>
<xsl:for-each select="tokenize($xml-config-files,',')">
<xsl:apply-templates select="doc(concat('file:///', translate(., '\', '/')))/*"/>
</xsl:for-each>
</gek-lookup>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:copy-of select="eng_family"/>
<xsl:copy-of select="engine_model"/>
<xsl:copy-of select="cd_gek"/>
<xsl:copy-of select="version_no"/>
<xsl:copy-of select="display_name"/>
</xsl:copy>
</xsl:template>
I'm not aware of any way of passing an Ant fileset
directly into a Saxon transformation, but you can certainly pass the name of a directory as a stylesheet parameter, and use this as an argument to the collection()
function. Saxon's handling of collections is described at https://www.saxonica.com/documentation12/index.html#!sourcedocs/collections