2010-09-09 22 views
5

Todo,Aplicar XSLT Transformar a un XML ya transformado

Tengo un archivo XML que lo transformo utilizando un documento XSLT en otro XML.

¿Puedo definir otro conjunto de transformaciones en el mismo archivo XSLT que se aplicará en el XML resultante de la primera transformación?

Gracias,

MK

+0

¿Desea que las dos transformaciones se realicen en una sola pasada? Y si es así, ¿por qué no cortar al intermediario y simplemente transformar directamente a su producción prevista? – recursive

+0

¿Por qué necesita que esto suceda con un solo XSLT? ¿Por qué no tener dos archivos separados? –

+0

Tengo una aplicación que solo acepta un archivo XSLT pero quiero aplicar la segunda transformación al archivo recién transformado. – koumides

Respuesta

9

Sí.

I. Esta transformación XSLT 1.0:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" 
xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vrtfPass1"> 
    <xsl:apply-templates/> 
</xsl:variable> 

<xsl:template match="node()|@*" name="identity"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="node()|@*" mode="pass2"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*" mode="pass2"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="num/text()"> 
    <xsl:value-of select="2*."/> 
</xsl:template> 

<xsl:template match="num/text()" mode="pass2"> 
    <xsl:value-of select="1+."/> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:apply-templates select="ext:node-set($vrtfPass1)/*" mode="pass2"/> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica en este documento XML:

<t> 
<num>1</num> 
<num>2</num> 
<num>3</num> 
<num>4</num> 
<num>5</num> 
</t> 

produce:

<t> 
    <num>3</num> 
    <num>5</num> 
    <num>7</num> 
    <num>9</num> 
    <num>11</num> 
</t> 

hacer la nota:

  1. dos transformaciones se llevan a cabo en realidad, la segunda se realiza en el resultado de la primera.

  2. El resultado de la primera transformación es el contenido de la variable $vrtfPass1.

  3. En XSLT 1.0 del tipo de variables que contienen dinámicamente generado árboles (temporal) XML (documento XML o fragmento XML) es RTF (resultado-Tree-Fragmento). No es posible realizar operaciones XPath en un RTF; debe convertirse a un conjunto de nodos normal mediante la función de extensión xxx:node-set(), que es proporcionada por la gran mayoría de los proveedores de procesadores XSLT 1.0. En este ejemplo se usa exslt: node-set(), porque EXSLT es implementado por muchos proveedores diferentes.

  4. La segunda transformación se aplica al resultado del primer: <xsl:apply-templates select="ext:node-set($vrtfPass1)/*" mode="pass2"/>. Se usa un mode por separado para separar limpiamente el código de las dos transformaciones.

  5. La primera transformación multiplica cada num/text() por 2. La segunda transformación incrementa cada num/text(). El resultado es 2*.+1

II. Esta transformación XSLT 2.0:

<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:strip-space elements="*"/> 

<xsl:variable name="vPass1"> 
    <xsl:apply-templates mode="pass1"/> 
</xsl:variable> 

<xsl:template match="node()|@*" mode="pass1"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*" mode="pass1"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="node()|@*" mode="pass2"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*" mode="pass2"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="num/text()" mode="pass1"> 
    <xsl:value-of select="2*xs:integer(.)"/> 
</xsl:template> 

<xsl:template match="num/text()" mode="pass2"> 
    <xsl:value-of select="1+."/> 
</xsl:template> 

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

cuando se aplica en el mismo documento XML, produce el mismo resultado deseado y correcta.

Nota: En XSLT 2.0/XPath 2.0, se ha eliminado el tipo de RTF. No es necesaria la función de extensión xxx:node-set().

+0

+1 Buena respuesta. Esto muestra por qué RTF fue una mala elección de diseño de WG ... Además, ¿no tenemos que mostrar el uso de 'fn: function-available' cuando usamos funciones de extensión? –

+0

@Alejandro: Tal vez usar 'fn: function-available' sería útil para determinar cuál de las muchas extensiones' xxx: node-set() 'implementa el procesador XSLT, pero esto generalmente se conoce. –

+0

Genial. Muchas gracias Dimitre. – koumides

Cuestiones relacionadas