2009-02-01 9 views
5

Frage

Wir haben eine große Anzahl von XML-Konfigurationsdateien, die wir zur Build-Zeit in eine Master-Version zusammenführen möchten. Kleinere Konfigurationsdateien sind einfacher zu warten und eine große Datei lädt schneller. Daher stellte ich mir vor, dass dies ein beliebter Build-Transformationsprozess ist, für den ich viele gute Beispiele im Internet finden würde.XML-Dateien mit ant und xslt dynamisch verketten

Ich konnte einige gute Lösungen für einen Teil des Problems here at StackOverflow finden, aber sie alle verlassen sich darauf, die Namen der XML-Dateien zu kennen, die vorne verschmelzen müssen. Dies scheint für mich ein unnötiger Overhead zu sein. Es sollte möglich sein, ein Build-Skript zu schreiben, das dynamisch berechnet, welche Eingabe-XML-Dateien benötigt werden.

Leider war der einzige Weg, den ich finden konnte, um dies zu erreichen, ein bisschen wie ein Hack. Es funktioniert so,

  1. Verwenden Sie eine zufällige Ameisenaufgabe, die ich vom Internet geklaut habe, um eine Verzeichnisliste in eine xml-Datei zu schreiben.
  2. Führen Sie die XML-Datei in eine XSLT-Umwandlung ein, die dann das andere Verzeichnis mit den angegebenen XML-Dateien laden und verketten kann.
  3. Löschen Sie die temporäre XML-Datei mit der Verzeichnisliste.

Hier ist der Ant-Skript

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

Und hier ist das Stylesheet,

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

Hat jemand einen einfacheren Weg gefunden, diese dynamische Entdeckung zu erreichen, was in XSLT zu Zusammenführen von Dateien? Es ist nicht verwunderlich, dass XSLT Verzeichnisse nicht direkt lesen kann, aber ich hoffte, eine einfachere Möglichkeit zu finden, eine Liste von Dateinamen als durch eine andere XML-Datei zu übergeben.

-Lösung implementiert

Dimitre's solution funktionierte großartig, wenn ich ein paar zusätzliche kleine Änderungen an dem Ant-Skript gemacht hatte,

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

und das XSL-Stylesheet (die ich bewegte)

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

Diese Optimierungen waren nur dazu da, Saxon9 zu laden und das Verzeichnis mit einem Parameter zu setzen.

Antwort

6

Hat jemand eine einfachere Art und Weise erreichen diese dynamische Entdeckung dessen, was Dateien in XSLT zu fusionieren gefunden? Es ist nicht überraschend, dass XSLT Verzeichnisse nicht direkt lesen kann, aber ich hatte gehofft, eine einfachere Möglichkeit zu finden, in einer Liste der Dateinamen als durch eine andere XML-Datei zu übergeben.

Dynamische Erkennung und Verarbeitung von XML-Dateien können mit XPath 2/0/XSLT 2 durchgeführt werden.0. Genauer gesagt, muss man die XPath 2.0 collection() Funktion verwenden.

Weitere Informationen finden Sie unter my answer to this question. So

, wenn ANT einen geeigneten XSLT 2.0 Prozessor verwenden kann, (ich würde empfehlen Saxon verwenden), das Problem hat eine Komplettlösung, die Standard-collection() Funktion.