How to use xsl variable in xsl if
xml, xslt
Solution
<xsl:variable name="coords" select="'lbi:GetCoordinates(PVAL)'"/>
<xsl:if test="not(string-length(coords) = 0)">
This is "almost" correct. The only problem is the quotes around `lbi:GetCoordinates(PVAL)`. These convert the return value from an extension function-- just to the string of the expression that invokes this function. As the length of this string is obviously greater than `0`, the test on the second line will allways be true.
From here on I suppose that the `lbi:GetCoordinates()` function returns a string or an atomic value (not a node or a node-set), because you haven't said anything about the return type of the function, but this is very important!
You want (note that the quotes are missing now!):
<xsl:variable name="coords" select="lbi:GetCoordinates(PVAL)"/>
<xsl:if test="not(string-length(coords) = 0)">
**But even this is a little bit clumsy.
Solution: Use the power of XSLT template match patterns and avoid the conditional logic inside the template altogether:
<xsl:template match="PROP[string-length(lbi:GetCoordinates(PVAL))]"
mode="Geocode">
<PROP NAME="Geocode">
<PVAL>
<xsl:value-of select="lbi:GetCoordinates(PVAL)"/>
</PVAL>
</PROP>
</xsl:template>
Don't worry that the `lbi:GetCoordinates(PVAL)` function is called twice because a good optimizing XSLT processor will only call it once. You may always conduct some tests and see if this is the case.
In the worst case, if the XSLT processor is dumb and calls the function twice, then use the clumsier code above.
Problem
I am trying to assign a value from an xsl variable to a new node in my xml file. This code works, but adds an empty PROP/PVAL node when the value of "lbi:GetCoordinates(PVAL)" is empty: ``` <xsl:template match="PROP" mode="Geocode"> <PROP NAME="Geocode"> <PVAL> <xsl:value-of select="lbi:GetCoordinates(PVAL)"/> </PVAL> </PROP> </xsl:template> ``` As I don't want any empty nodes, I am trying to only add the new node only when the value of "lbi:GetCoordinates(PVAL)" is not empty. The approach I am trying is to assign the value to a variable and test that variable, as below. Unfortunately, when I do this I get no new PROP nodes, even when lbi:GetCoordinates(PVAL) returns a non-empty value. ``` <xsl:template match="PROP" mode="Geocode"> <xsl:variable name="coords" select="'lbi:GetCoordinates(PVAL)'"/> <xsl:if test="not(string-length(coords) = 0)"> <PROP NAME="Geocode"> <PVAL> <xsl:value-of select="coords"/> </PVAL> </PROP> </xsl:if> </xsl:template> ``` Can anyone point me in the right direction, or suggest a better way of achieving this? The source xml is like this: ``` <RECORD> <PROP name="PostCode"> <PVAL>N11 1NN</PVAL> </PROP> </RECORD> ``` and the template is referenced thus: ``` <xsl:template match="RECORD"> <xsl:copy> <xsl:apply-templates select="PROP[@NAME='PostCode']" mode="Geocode"/> </xsl:copy> ``` The lbi:GetCoordinates() method is in an external .Net assembly added as an xml namespace. Using this approach works: ``` <xsl:template match="PROP[string-length(lbi:GetCoordinates(PVAL))>0]" mode="Geocode"> <PROP NAME="Geocode"> <PVAL> <xsl:value-of select="lbi:GetCoordinates(PVAL)"/> </PVAL> </PROP> ``` The problem now is that the lbi:GetCoordinates method is called twice when it only needs to be called once, the source xml can have 100,000+ elements that need geocoding so this is non-trivial. This suggests to me that the xsl:variable expression I used earlier is incorrect and the variable always ends up as empty.