динамическое объединение XML-файлов с помощью ant и xslt - PullRequest
5 голосов
/ 01 февраля 2009

Вопрос

У нас есть большое количество файлов конфигурации xml, которые мы хотим объединить в одну основную версию во время сборки. Меньшие файлы конфигурации проще в обслуживании, и один большой файл загружается быстрее, поэтому я подумал, что это популярный процесс преобразования сборки, который я нашел бы в сети много хороших примеров.

Мне удалось найти несколько хороших решений одной части проблемы здесь, в StackOverflow , но все они основаны на знании имен файлов XML, которые необходимо объединить сразу. Это кажется ненужными накладными расходами для меня. Должна быть возможность написать сценарий сборки, который может динамически вычислять, какие входные XML-файлы необходимы.

К сожалению, единственный способ, который я смог найти, - это немного взломать. Это работает так,

  1. Используйте случайную задачу муравья, которую я украл в Интернете, чтобы записать список каталогов в XML-файл.
  2. Подайте файл xml в преобразование xslt, которое затем может загрузить другой список каталогов, на который ссылаются файлы xml, и объединить их.
  3. Удалить временный XML-файл, содержащий список каталогов.

Вот сценарий муравья

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

А вот таблица стилей,

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

Кто-нибудь нашел более простой способ добиться этого динамического открытия того, какие файлы объединить в XSLT? Неудивительно, что XSLT не может читать каталоги напрямую, но я надеялся найти более простой способ передачи списка имен файлов, чем через другой XML-файл.

Реализованное решение

Решение Димитра отлично заработало, как только я сделал несколько дополнительных настроек для скрипта ant,

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

и таблица стилей xsl (которую я переместил)

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

Эти хитрости были только для загрузки Saxon9 и установки каталога с параметром.

1 Ответ

6 голосов
/ 01 февраля 2009

Кто-нибудь нашел более простой способ достичь этого динамического открытия того, что файлы для слияния в XSLT? Это не удивительно, что XSLT не может читать каталоги напрямую, но я надеялся чтобы найти более простой способ пройти в список имен файлов, чем через другой XML-файл.

Динамическое обнаружение и обработка файлов XML можно выполнить с помощью XPath 2/0 / XSLT 2.0 . В частности, необходимо использовать функцию XPath 2.0 collection().

Подробнее см. мой ответ на этот вопрос .

Таким образом, если ANT может использовать подходящий процессор XSLT 2.0 , (я бы порекомендовал использовать Saxon ), , проблема имеет полное решение , используя стандартную функцию collection().

...