2013-01-10 17 views
6

Sono bloccato con un piccolo problema.Riferimento a una variabile XSLT tramite un nome dinamico

Il XSL-File:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:fn="http://www.w3.org/2005/xpath-functions"> 
<xsl:template match="/"> 


<xsl:variable name="unumericValue" select="10" /> 
<xsl:variable name="uanotherValue" select="8" /> 



<xsl:for-each select="/root/try"> 
<xsl:value-of select="var" /> 
<xsl:variable name="min"><xsl:value-of select="@minimum" /></xsl:variable> 
<xsl:value-of select="@type" /> 
<xsl:variable name="referenceName"><xsl:value-of select='concat("u",var)' /></xsl:variable> 
<xsl:value-of select="$referenceName" /> 
<xsl:if test='$referenceName > $min'> 
<p>Do something.</p> 
</xsl:if> 
</xsl:for-each> 

</xsl:template> 
</xsl:stylesheet> 

file XML:

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="q1.xsl"?> 
<root> 
<try type="compare" minimum="9"> 
<var>numericValue</var> 
<something>...</something> 
</try> 

<try type="compare" minimum="10"> 
<var>anotherValue</var> 
<something>...</something> 
</try> 
</root> 

Come si può vedere il file XML ha due var-elementi che dovrebbero corrispondere alle variabili in XSLT-File . Tuttavia non so quale sintassi sia corretta. $ referenceName è solo il nome della variabile che voglio usare. Ma non so come fare riferimento al nome della variabile esistente.

risposta

11

$referenceName non è un riferimento alla variabile con il nome "unumericValue" o altro. È solo il valore stringa "unumericValue", ecc. In modo che non sarà mai maggiore di $min. Tuttavia, con un po 'di lavoro extra, c'è un trucco per trovare una variabile con il suo nome:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:variable name="numericValue" select="10" /> 
    <xsl:variable name="anotherValue" select="8" /> 
    <xsl:variable name="vars" select="document('')/*/xsl:variable" /> 

    <xsl:template match="/"> 
    <xsl:variable name="referenceName" select="'numericValue'" /> 
    <xsl:variable name="referenceValue" select="$vars[@name = $referenceName]/@select" /> 
    Reference value: <xsl:value-of select="$referenceValue" /> 
    </xsl:template> 
</xsl:stylesheet> 

Un grande limitazione da notare qui è che questo funziona solo per le variabili che sono un valore numerico costante.

Ecco un modo per simulare le variabili con valori di stringa costanti:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:v="variables-node" 
> 
    <v:variables> 
    <v:variable n="numericValue" value="10" /> 
    <v:variable n="nonNumericValue" value="Hello World" /> 
    </v:variables> 
    <xsl:variable name="vars" select="document('')//v:variables/v:variable" /> 

    <xsl:template match="/"> 
     <xsl:variable name="referenceName" select="'nonNumericValue'" /> 
     <xsl:variable name="referenceValue" select="$vars[@n = $referenceName]/@value" /> 
     <xsl:value-of select="concat('The variable with the name ', $referenceName, ' has the value ', $referenceValue)"/> 
    </xsl:template> 
</xsl:stylesheet> 

E, infine, un modo per simulare le variabili con valori calcolati:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:exslt="http://exslt.org/common" 
> 

    <xsl:variable name="varsRaw"> 
    <var n="computedValue" value="{concat('2 + 4 is ', 2 + 4)}" /> 
    <var n="computedNumber" value="{22 div 7}" /> 
    </xsl:variable> 
    <xsl:variable name="vars" select="exslt:node-set($varsRaw)/var" /> 

    <xsl:template match="/"> 
     <xsl:variable name="referenceName" select="'computedValue'" /> 
     <xsl:variable name="referenceValue" select="$vars[@n = $referenceName]/@value" /> 
     <xsl:value-of select="concat('The variable with the name ', $referenceName, ' has the value ', $referenceValue)"/> 

     <xsl:value-of select="'  '"/> 

     <xsl:variable name="referenceName2" select="'computedNumber'" /> 
     <xsl:variable name="referenceValue2" select="$vars[@n = $referenceName2]/@value" /> 
     <xsl:value-of select="concat('The variable with the name ', $referenceName2, ' has the value ', $referenceValue2)"/> 
    </xsl:template> 
</xsl:stylesheet> 

L'ultimo approccio è probabilmente in realtà il più ortodosso , ma richiede la funzione XSLT dipendente dal processore (almeno in XSLT 1.0) node-set().

+0

Grazie mille. Il primo suggerimento ha funzionato alla grande per me. – eadrax

1

Come per la maggior parte dei linguaggi di programmazione, i nomi delle variabili XSLT non sono accessibili in fase di esecuzione. La variabile potrebbe anche non esistere in fase di esecuzione: all'ottimizzatore è consentito eseguire tutti i tipi di trucchi, ad esempio l'inlining di tutti i riferimenti alla variabile nel punto in cui viene utilizzata la variabile.

L'approccio migliore consiste nell'avere una variabile con un nome standard e dargli contenuto XML. I nomi di elementi e attributi nell'XML sono accessibili in fase di esecuzione, diversamente dai nomi delle variabili.

5

A proposito, non fare questo:

<xsl:variable name="min"><xsl:value-of select="@minimum" /></xsl:variable> 

quando si potrebbe fare questo:

<xsl:variable name="min" select="@minimum" /> 

Non solo è prolisso, è anche inefficiente - non c'è bisogno di copiare i dati e costruisci un nuovo albero, che è un'operazione molto costosa, quando tutto ciò che vuoi è un riferimento a un nodo esistente.

+0

Certo che hai ragione. È anche molto più facile e più breve da scrivere :) – eadrax

Problemi correlati