2009-02-01 14 views
5

Question

Nous avons un grand nombre de fichiers de configuration XML que nous voulons en une seule version fusionné maître au moment de la construction. Les fichiers de configuration plus petits sont plus faciles à maintenir et un fichier volumineux se charge plus rapidement. J'ai donc imaginé que c'était un processus de transformation de build populaire que je trouverais beaucoup de bons exemples sur le net.concaténer dynamiquement les fichiers xml avec ant et xslt

J'ai été en mesure de trouver quelques bonnes solutions à une partie du problème here at StackOverflow, mais ils reposent tous sur la connaissance des noms des fichiers XML qui doivent être fusionnés à l'avance. Cela me semble être un surcoût inutile. Il devrait être possible d'écrire un script de construction qui peut calculer dynamiquement les fichiers XML d'entrée nécessaires. Malheureusement, la seule façon que j'ai pu trouver pour y parvenir était un peu un hack. Cela fonctionne comme ceci,

  1. Utilisez une tâche aléatoire que j'ai volée sur Internet pour écrire une liste de répertoires dans un fichier xml.
  2. Alimentez le fichier xml dans une transformation xslt qui peut ensuite charger l'autre répertoire listant les fichiers xml référencés et les concaténer.
  3. Supprimez le fichier xml temporaire contenant la liste de répertoires.

Voici le script 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> 

Et voici la feuille de style,

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

Quelqu'un at-il trouvé un moyen plus simple de réaliser cette découverte dynamique des fichiers à fusionner XSLT? Il n'est pas surprenant que XSLT ne puisse pas lire les répertoires directement, mais j'espérais trouver un moyen plus simple de transmettre une liste de noms de fichiers que par le biais d'un autre fichier xml.

Mis en œuvre Solution

Dimitre's solution fonctionnait très bien une fois que je l'avais fait quelques modifications supplémentaires au script fourmi,

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

et xsl: stylesheet (que j'ai déménagé)

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

Ces réglages consistaient simplement à charger Saxon9 et à définir le répertoire avec un paramètre.

Répondre

6

Quelqu'un at-il trouvé un moyen plus simple de réaliser cette découverte dynamique des fichiers à fusionner XSLT? Ce n'est pas étonnant que XSLT ne peut pas lire les répertoires directement, mais j'espérais de trouver un moyen plus simple de passer dans une liste de noms de fichiers que par l'intermédiaire de un autre fichier xml.

découverte dynamique et le traitement des fichiers XML peuvent être fait en utilisant XPath 2/0/XSLT 2.0. Plus spécifiquement, il faut utiliser la fonction XPath 2.0 collection().

Pour plus de détails, voir my answer to this question.

Donc, si ANT peut utiliser un processeur XSLT 2.0 adapté, (je vous recommande d'utiliser Saxon), le problème a une solution complète, en utilisant la fonction standard collection().