Concatenating xml files

依然范特西╮ 提交于 2019-12-19 03:37:04

问题


I have several xml files, the names of which are stored in another xml file.

I want to use xsl to produce a summary of the combination of the xml files. I remember there was a way to do this with the msxml extensions (I'm using msxml).

I know I can get the content of each file using select="document(filename)" but I'm not sure how to combine all these documents into one.

21-Oct-08 I should have mentioned that I want to do further processing on the combined xml, so it is not sufficient to just output it from the transform, I need to store it as a node set in a variable.


回答1:


Here is just a small example of what you could do:

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>

Applying the stylesheet to index.xml gives you:

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

The trick is to load the different documents with the document function (extension function supported by almost all XSLT 1.0 processors), to output the contents as part of a variable body and then to convert the variable to a node-set for further processing.




回答2:


Assume that you have the filenames listed in a file like this:

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

Then you could use a stylesheet like this on the above file:

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



回答3:


Have a look at the document() function documentation.

You can use document() to load further XML documents during the transformation process. They are loaded as node sets. That means you would initially feed the XML that contains the file names to load to the XSLT, and take it from there:

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



回答4:


Thanks for all the answers. Here's the guts of the solution I'm using with 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>

Now I'm trying to improve performance as each file is around 8 MB and the transformation is taking a very long time, but that's another question.



来源:https://stackoverflow.com/questions/217591/concatenating-xml-files

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!