2013-01-10 35 views
6

我遇到了一個小問題。通過動態名稱引用XSLT變量

的XSL-文件:

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

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

正如你所看到的XML文件有兩個變種,元素應該相匹配的變量在XSLT的文件。但是我不知道哪個語法是正確的。 $ referenceName只是我想要使用的變量的名稱。但我不知道如何將名稱引用到現有變量中。

回答

11

$referenceName不是對名稱爲「unumericValue」或其他名稱的變量的引用。它只是字符串值「unumericValue」等,因此永遠不會大於$min。然而,隨着一些額外的工作,有一個小竅門通過名稱找到一個變量:

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

一個很大的限制,這裏要注意的是,這將只用於在一個恆定的數值變量的工作。

這裏的模擬變量與常量字符串值的方法:

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

最後,一種方法來模擬變量與計算值:

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

最後一種方法可能是實際上最正統,但需要依賴於XSLT處理器(至少在XSLT 1.0中)node-set()函數。

+0

非常感謝。第一個建議對我很有幫助。 – eadrax

1

與大多數編程語言一樣,XSLT變量名在運行時不可訪問。該變量在運行時可能不存在 - 優化程序可以播放各種技巧,如在變量使用點處引用對變量的所有引用。

最好的方法是使用標準名稱的變量,併爲其提供XML內容。與變量名稱不同,XML中的元素和屬性名稱可以在運行時訪問。

5

順便說,不這樣做:

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

時,你可以這樣做:

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

它不僅冗長,這也是低效率的 - 有沒有需要複製的數據並構建一個新的樹,這是一個非常昂貴的操作,當你想要的只是一個現有節點的引用。

+0

當然你是對的。寫起來也很容易和簡短:) – eadrax