Конкатенация XML-файлов - PullRequest
       29

Конкатенация XML-файлов

5 голосов
/ 20 октября 2008

У меня есть несколько XML-файлов, имена которых хранятся в другом XML-файле.

Я хочу использовать xsl для получения сводной информации о комбинации файлов xml. Я помню, что был способ сделать это с помощью расширений msxml (я использую msxml).

Я знаю, что могу получить содержимое каждого файла, используя select="document(filename)", но я не уверен, как объединить все эти документы в один.

21-Oct-08 Я должен был упомянуть, что я хочу выполнить дополнительную обработку объединенного xml, поэтому недостаточно просто вывести его из преобразования, мне нужно сохранить его как набор узлов в переменной.

Ответы [ 4 ]

3 голосов
/ 20 октября 2008

Вот лишь небольшой пример того, что вы могли бы сделать:

file1.xml:

<foo>
<bar>Text from file1</bar>
</foo>

file2.xml:

<foo>
<bar>Text from file2</bar>
</foo>

index.xml:

<index>
<filename>file1.xml</filename>
<filename>file2.xml</filename>

summarize.xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="exsl">

  <xsl:variable name="big-doc-rtf">
      <xsl:for-each select="/index/filename">
        <xsl:copy-of select="document(.)"/>
      </xsl:for-each>
  </xsl:variable>

  <xsl:variable name="big-doc" select="exsl:node-set($big-doc-rtf)"/>

  <xsl:template match="/">
    <xsl:element name="summary">
      <xsl:apply-templates select="$big-doc/foo"/>
    </xsl:element>  
  </xsl:template>

  <xsl:template match="foo">
    <xsl:element name="text">
      <xsl:value-of select="bar"/>
    </xsl:element>  
  </xsl:template>

</xsl:stylesheet>

Применение таблицы стилей к index.xml дает вам:

<?xml version="1.0" encoding="UTF-8"?><summary><text>Text from file1</text><text>Text from file2</text></summary>

Хитрость заключается в том, чтобы загружать различные документы с помощью функции документа (функции расширения, поддерживаемой почти всеми процессорами XSLT 1.0), выводить содержимое как часть тела переменной, а затем преобразовывать переменную в набор узлов для дальнейшего обработка.

2 голосов
/ 20 октября 2008

Предположим, что у вас есть имена файлов, перечисленные в таком файле:

<files>
    <file>a.xml</file>
    <file>b.xml</file>
</files>

Тогда вы можете использовать такую ​​таблицу стилей в приведенном выше файле:

<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="/">
        <root>
            <xsl:apply-templates select="files/file"/>                          
        </root>
    </xsl:template>

    <xsl:template match="file">
        <xsl:copy-of select="document(.)"/>
    </xsl:template>
</xsl:stylesheet>
0 голосов
/ 21 октября 2008

Спасибо за все ответы. Вот суть решения, которое я использую с msxml.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt">
  <xsl:output method="xml"/>
  <xsl:template match="/">
    <xsl:variable name="combined">
      <xsl:apply-templates select="files"/>
    </xsl:variable>
    <xsl:copy-of select="ms:node-set($combined)"/>
  </xsl:template>
  <xsl:template match="files">
    <multifile>
      <xsl:apply-templates select="file"/>
    </multifile>
  </xsl:template>
  <xsl:template match="file">
    <xsl:copy-of select="document(@name)"/>
  </xsl:template>
</xsl:stylesheet>

Сейчас я пытаюсь улучшить производительность, поскольку каждый файл занимает около 8 МБ, а преобразование занимает очень много времени, но это другой вопрос.

0 голосов
/ 20 октября 2008

Ознакомьтесь с документацией к функциям document() .

Вы можете использовать document() для загрузки других документов XML в процессе преобразования. Они загружаются как наборы узлов. Это означает, что вы сначала передадите XML, содержащий имена файлов для загрузки в XSLT, и получите его оттуда:

<xsl:copy-of select="document(@href)/"/>
...