2011-09-05 35 views
7

El problema es combinar y ordenar varias archivos XML con XSL y la salida HTML válido se puede leer con Firefox> = 3.5 y si es posible IE> = 7. La respuesta debe ser lo más simple posible (el rendimiento no es importante).Combinar y clasificar varios archivos XML con XSL

a.xml Archivo

<?xml version="1.0"?> 
<root> 
    <tag>cc</tag> 
    <tag>aa</tag> 
</root> 

b.xml Archivo

<?xml version="1.0"?> 
<root> 
    <tag>xx</tag> 
    <tag>bb</tag> 
</root> 

index.xml Archivo

<?xml version="1.0"?> 
<?xml-stylesheet type="text/xsl" href="merge.xslt"?> 
<list> 
    <entry>a.xml</entry> 
    <entry>b.xml</entry> 
</list> 

merge.xslt Archivo

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ph="http://ananas.org/2003/tips/photo"> 

    <xsl:output method="html"/> 

    <xsl:template match="list"> 
     <html> 
      <body> 
       <xsl:apply-templates/> 
      </body> 
     </html> 
    </xsl:template> 

    <xsl:template match="entry"> 
     <xsl:for-each select="document(.)/root/tag"> 
      <!-- This will only sort the values of a single file --> 
      <xsl:sort select="." data-type="text" order="ascending" /> 
      - <xsl:value-of select="."/> <br/> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

Salida de corriente:

  • aa

  • cc

  • bb

  • xx

Resultados previstos:

  • aa

  • bb

  • cc

  • xx

+1

Buena pregunta, +1. Vea mi respuesta para una solución completa, muy corta y fácil que no tiene las complejidades de ninguna de las otras respuestas: sin funciones de extensión, sin variables, sin 'xsl: for-each' ... –

+0

También se agregó una explicación extensa. –

Respuesta

8

La solución a esto es un tiempo muy corto y fácil transformación (absolutamente sin extensión funciones a re requerido):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/*"> 
    <html> 
    <ul> 
    <xsl:apply-templates 
     select="document(entry)/*/tag"> 
     <xsl:sort/> 
    </xsl:apply-templates> 
    </ul> 
    </html> 
</xsl:template> 

<xsl:template match="tag"> 
    <li><xsl:value-of select="."/></li> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica esta transformación en el índice proporcionado.xml archivo:

<list> 
    <entry>a.xml</entry> 
    <entry>b.xml</entry> 
</list> 

el resultado deseado, correcta se produce:

<html> 
    <ul> 
     <li>aa</li> 
     <li>bb</li> 
     <li>cc</li> 
     <li>xx</li> 
    </ul> 
</html> 

y se muestra en cualquier navegador como:

  • aa
  • bb
  • cc
  • xx

Explicación: Esta solución utiliza el poder de la función XSLT estándar document(). Como se define en el W3C XSLT 1,0 Recomendación:

Cuando la función de documento tiene exactamente un argumento y el argumento es un conjunto de nodos, entonces el resultado es la unión, para cada nodo en el argumento node- estableció, del resultado de llamar a la función de documento con el primer argumento es la cadena de valor del nodo

esto explica el efecto de este fragmento de nuestro código:

<xsl:apply-templates 
    select="document(entry)/*/tag"> 
    <xsl:sort/> 
</xsl:apply-templates> 

Lo que ocurre aquí es que el argumento de la función document() es el conjunto de nodos de todos los elementos entry del elemento superior de index.xml. El resultado es la unión de todos los nodos de documento.

Por lo tanto:

select="document(entry)/*/tag" 

selecciona todos los elementos en tag todos los documentos referenciados en index.xml. Luego se ordenan (por xsl:sort) y cada uno de los elementos de la lista de nodos ya ordenados se procesa mediante la plantilla que coincide con tag.

+0

Aceptado, porque la respuesta funciona y es fácil de entender. Muy buena explicación! – gaddomn

+1

No sé por qué me he complicado tanto. Necesito descansar. +1 para el mejor y más fácil enfoque. –

+0

@gaddomn: De nada. @_empo: Tú también. –