Pregunta
Tenemos un gran número de archivos de configuración XML que queremos que se fusionaron en una versión maestra en tiempo de compilación. Los archivos de configuración más pequeños son más fáciles de mantener y un archivo grande se carga más rápido, por lo que me imaginé que se trataba de un proceso de transformación de compilación popular del que encontraría muchos buenos ejemplos en la red.dinámicamente concatenación de archivos XML y XSLT con la hormiga
Pude encontrar algunas buenas soluciones a una parte del problema here at StackOverflow pero todas confían en conocer los nombres de los archivos xml que necesitan fusionarse por adelantado. Esto parece una sobrecarga innecesaria para mí. Debería ser posible escribir un script de compilación que pueda calcular dinámicamente qué archivos xml de entrada se necesitan.
Lamentablemente, la única forma en que pude encontrar para lograr esto fue un poco hack. Funciona así,
- Use una tarea aleatoria que robé de Internet para escribir una lista de directorios en un archivo xml.
- Alimente el archivo xml en una transformación xslt que luego pueda cargar el otro directorio que enumera los archivos xml a los que se hace referencia y concatenarlos.
- Elimine el archivo xml temporal que contiene la lista del directorio.
Aquí está la secuencia de comandos Ant
<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>
Y aquí es la hoja de estilo,
<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>
Alguien ha encontrado una manera más sencilla de lograr este descubrimiento dinámico de lo que los archivos a fusionar en XSLT? No es sorprendente que XSLT no pueda leer directorios directamente, pero esperaba encontrar una forma más sencilla de pasar una lista de nombres de archivo que a través de otro archivo xml.
implementado la solución
Dimitre's solution funcionaba muy bien, una vez que había hecho algunos ajustes adicionales para el guión de hormigas,
<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>
y la hoja de estilo XSL (que moví)
<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>
Esos retoques estaban a punto de lograr que Saxon9 cargara y configurara el directorio con un parámetro.