2013-01-10 10 views
6

Ich stecke mit einem kleinen Problem fest.Verweise auf eine XSLT-Variable über einen dynamischen Namen

Die XSL-Datei:

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

Die XML-Datei:

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

Wie Sie die XML-Datei hat zwei var-Elemente sehen, die auf die Variablen in der XSLT-Datei übereinstimmen sollten . Ich weiß jedoch nicht, welche Syntax korrekt ist. $ referenceName ist nur der Name der Variablen, die ich verwenden möchte. Aber ich weiß nicht, wie ich den Namen auf die vorhandene Variable beziehen soll.

Antwort

11

$referenceName ist kein Verweis auf die Variable mit dem Namen „unumericValue“ oder auf andere Weise. Es ist nur der String-Wert "unumericValue" usw. Also wird das niemals größer als $min sein. Doch mit einer wenig zusätzlichen Arbeit, gibt es einen Trick, um eine Variable, die durch ihren Namen zu finden:

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

Ein große Einschränkung zu beachten ist hier, dass dies nur für Variablen arbeiten, die ein konstanter numerischer Wert sind.

Hier ist eine Art und Weise Variablen mit konstanten Stringwerte zu simulieren:

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

Und schließlich eine Möglichkeit, Variablen mit den berechneten Werten zu simulieren:

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

Der letzte Ansatz wohl eigentlich die orthodox ist , benötigt aber die XSLT-Prozessor-abhängige (zumindest in XSLT 1.0) node-set() Funktion.

+0

Vielen Dank. Der erste Vorschlag hat mir gut getan. – eadrax

1

Wie bei den meisten Programmiersprachen sind XSLT Variablennamen zur Laufzeit nicht zugänglich. Die Variable existiert möglicherweise nicht einmal zur Laufzeit - der Optimierer kann alle Arten von Tricks spielen, wie z. B. alle Verweise auf die Variable an dem Punkt, an dem die Variable verwendet wird.

Der beste Ansatz ist eine Variable mit einem Standardnamen zu haben, und es XML-Inhalte geben. Auf die Element- und Attributnamen in der XML kann im Gegensatz zu den Variablennamen zur Laufzeit zugegriffen werden.

5

By the way, tun dies nicht:

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

, wenn Sie dies tun könnte:

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

Es ist nicht nur ausführlich, sondern auch ineffizient - es gibt keine Notwendigkeit, die Daten zu kopieren und konstruiere einen neuen Baum, was eine sehr teure Operation ist, wenn alles, was du willst, ein Verweis auf einen existierenden Knoten ist.

+0

Natürlich hast du recht. Es ist auch viel einfacher und kürzer zu schreiben :) – eadrax

Verwandte Themen