2010-12-31 10 views
9

Tengo una situación en la que creo que necesito conectar en cadena mi transformación xslt (es decir, la salida de una transformación xslt que se ingresa en otra). La primera transformación es bastante compleja con muchos xsl: elección y ancestro xpaths. Mi idea es transformar el xml en xml que luego se puede transformar fácilmente en html.¿Es una práctica aceptada la conexión en cadena xslt?

Mi pregunta es '¿Es esta práctica estándar o me falta algo?'

Gracias de antemano.

Stephen

+0

Buena pregunta, +1. Ver mi respuesta para una explicación y un ejemplo de código completo. :) –

+1

Sí, es aceptado, pero no siempre es necesario. Si está utilizando Java, el Transformerfactory puede configurarse para barrer transformaciones sucesivas y evitar operaciones de análisis innecesarias. http://stackoverflow.com/questions/1312406/efficient-xslt-pipeline-in-java-or-redirecting-results-to-sources/1319774#1319774 –

Respuesta

0

Yo no creo que haya sido estándar de la práctica, en particular, ya que se puede transformar un dialecto XML directamente a otro.

Sin embargo, si el procesamiento es complejo, dividirlo en varios pasos (aplicar una transformación diferente en cada paso) puede simplificar cada paso y tener sentido.

Realmente depende de la situación particular.

9

Realización de una cadena de transformaciones se utiliza muy a menudo en aplicaciones XSLT, aunque haciendo esto enteramente en XSLT 1.0 requiere el uso de la función específica del proveedor xxx:node-set(). En XSLT 2.0 no se necesita dicha extensión ya que el infame tipo de datos RTF se elimina allí.

Aquí es un ejemplo (demasiado simple para ser significativo, pero que ilustra completamente cómo se hace esto):

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

<xsl:template match="/"> 
    <xsl:variable name="vrtfPass1"> 
    <xsl:apply-templates select="/*/*"/> 
    </xsl:variable> 

    <xsl:variable name="vPass1" 
     select="ext:node-set($vrtfPass1)"/> 

    <xsl:apply-templates mode="pass2" 
     select="$vPass1/*"/> 
</xsl:template> 

<xsl:template match="num[. mod 2 = 1]"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

<xsl:template match="num" mode="pass2"> 
    <xsl:copy> 
    <xsl:value-of select=". *2"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica esta transformación en el siguiente documento XML:

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 

el resultado deseado, correcto se produce:

<num>2</num> 
<num>6</num> 
<num>10</num> 
<num>14</num> 
<num>18</num> 

Explicación:

  1. En el primer paso el documento XML se transforma y el resultado se define como el valor de la variable $vrtfPass1. Esto copia solo los elementos num que tienen un valor impar (ni siquiera).

  2. La variable $vrtfPass1, siendo de tipo RTF, no es directamente utilizable para XPath expresiones por lo que la convierten en un árbol normal, utilizando el EXSLT (implementado por la mayoría de XSLT 1.0 procesadores) de función ext:node-set y la definición de una variable - - $vPass1 cuyo valor es este árbol.

  3. ahora realizamos la segunda transformación en nuestra cadena de transformaciones - en el resultado de la primera transformación, que se mantiene como el valor de la variable $vPass1. Para no meterse con la plantilla de primer paso, especificamos que el nuevo procesamiento debe estar en un modo con nombre, llamado "pass2". En este modo, el valor de cualquier elemento num se multiplica por dos.

XSLT 2.0 solución (no hay RTF):

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

<xsl:template match="/"> 
    <xsl:variable name="vPass1" > 
    <xsl:apply-templates select="/*/*"/> 
    </xsl:variable> 
    <xsl:apply-templates mode="pass2" 
     select="$vPass1/*"/> 
</xsl:template> 

<xsl:template match="num[. mod 2 = 1]"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

<xsl:template match="num" mode="pass2"> 
    <xsl:copy> 
    <xsl:value-of select=". *2"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 
1

Si esta es su situación (o puede convertirse en su situación):

  1. Transform xml inicial a xml mediario.
  2. Tal vez transformar mediary xml en final1_html.
  3. Tal vez transformar mediary xml en final2_html (para nada como final1_html).

o

  1. Transform xml inicial en xml mediario. Es razonablemente probable que esto cambie con el tiempo.
  2. Transformar mediary xml en final_html. Esto no es probable que cambie con el tiempo.

Entonces tiene sentido utilizar una transformación de dos pasos.

Si esta es su situación:

  1. Transform XML inicial para XML mediario.
  2. Transformar mediary xml en final_html.

Considere no dos pasos. En su lugar solo realiza una transformación.

Cuestiones relacionadas