Concatenación de archivos xml
xslcompiledtransform (4)
Tengo varios archivos xml, cuyos nombres están almacenados en otro archivo xml.
Quiero usar xsl para producir un resumen de la combinación de los archivos xml. Recuerdo que había una manera de hacer esto con las extensiones de msxml (estoy usando msxml).
Sé que puedo obtener el contenido de cada archivo usando select="document(filename)"
pero no estoy seguro de cómo combinar todos estos documentos en uno solo.
21-Oct-08 Debería haber mencionado que quiero hacer más procesamientos en el xml combinado, por lo que no es suficiente simplemente sacarlo de la transformación, necesito almacenarlo como un conjunto de nodos en una variable.
Aquí hay solo un pequeño ejemplo de lo que podrías hacer:
archivo1.xml:
<foo>
<bar>Text from file1</bar>
</foo>
archivo2.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>
La aplicación de la hoja de estilo a index.xml le proporciona:
<?xml version="1.0" encoding="UTF-8"?><summary><text>Text from file1</text><text>Text from file2</text></summary>
El truco es cargar los diferentes documentos con la función de documento (función de extensión admitida por casi todos los procesadores XSLT 1.0), para generar los contenidos como parte de un cuerpo variable y luego convertir la variable en un conjunto de nodos para su posterior procesamiento.
Eche un vistazo a la document()
función document document()
.
Puede usar document()
para cargar documentos XML adicionales durante el proceso de transformación. Se cargan como conjuntos de nodos. Eso significa que inicialmente alimentaría el XML que contiene los nombres de archivo para cargarlo en el XSLT, y lo tomará desde allí:
<xsl:copy-of select="document(@href)/"/>
Suponga que tiene los nombres de archivo enumerados en un archivo como este:
<files>
<file>a.xml</file>
<file>b.xml</file>
</files>
Entonces podría usar una hoja de estilo como esta en el archivo anterior:
<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>
Gracias por todas las respuestas. Aquí están las agallas de la solución que estoy usando con 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>
Ahora trato de mejorar el rendimiento ya que cada archivo tiene alrededor de 8 MB y la transformación lleva mucho tiempo, pero esa es otra pregunta.