2010-09-09 12 views
5

Tutti,Applica trasformazione XSLT a un XML già trasformato

Ho un file XML che lo trasformo utilizzando un documento XSLT in un altro XML.

È possibile definire un altro set di trasformazioni nello stesso file XSLT da applicare nel risultato XML della prima trasformazione?

Grazie,

MK

+0

Vuoi che le due trasformazioni avvengano in un solo passaggio? E se è così, perché non tagliare l'uomo medio e semplicemente trasformarlo direttamente nella produzione desiderata? – recursive

+0

Perché è necessario che ciò accada con un singolo XSLT? Perché non hai due file separati? –

+0

Ho un'app che accetta solo un file XSLT ma voglio applicare la seconda trasformazione al file appena trasformato. – koumides

risposta

9

Sì.

I. Questo XSLT 1.0 trasformazione:

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

quando applicato su questo 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> 

Do atto:

  1. due trasformazioni sono in realtà eseguite, la seconda viene eseguita sul risultato della prima.

  2. Il risultato della prima trasformazione è il contenuto della variabile $vrtfPass1.

  3. in XSLT 1.0 il tipo di variabili che contengono dinamicamente generato alberi (temporanea) XML (documento XML o frammento XML) è RTF (Risultato-Tree-frammento). Non è possibile eseguire operazioni XPath su un RTF: è necessario convertirlo in un normale set di nodi utilizzando la funzione di estensione xxx:node-set(), fornita dalla maggior parte dei fornitori di processori XSLT 1.0. In questo esempio exslt: viene utilizzato node-set(), poiché EXSLT è implementato da molti fornitori diversi.

  4. La seconda trasformazione viene applicata sul risultato del primo: <xsl:apply-templates select="ext:node-set($vrtfPass1)/*" mode="pass2"/>. Viene utilizzato un codice mode separato per separare in modo pulito il codice delle due trasformazioni.

  5. La prima trasformazione moltiplica ogni num/text() per 2. La seconda trasformazione incrementa ogni num/text(). Il risultato è 2*.+1

II. Questa trasformazione 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> 

se applicato sullo stesso documento XML, produce lo stesso risultato voluto e corretta.

Nota: in XSLT 2.0/XPath 2.0 il tipo di RTF è stato abolito. Non è necessaria la funzione di estensione xxx:node-set().

+0

+1 buona risposta. Questo dimostra perché RTF era un cattivo design scelto da WG ... Inoltre, non dobbiamo mostrare l'uso di 'fn: function-available' quando usiamo le estensioni? –

+0

@Alejandro: Forse usare 'fn: function-available' potrebbe essere utile per determinare quale delle molte estensioni' xxx: node-set() 'del processore XSLT implementa, ma di solito è nota. –

+0

Grande. Grazie mille Dimitre. – koumides

Problemi correlati