Carles said:
I want to calculate the value of an attribute. For
example <rect x="2+3" y="12"> and be <rect x="5" y="12">.
Is it possible using XSLT?
It sure is, BUT. It's really not what XSLT is for: you'd
have to write your own expression evaluator, and XSLT is
ill-suited for that. If you need that type of processing,
you'd better use something else, or wait for XSLT 2.0 to
become Recommendation -- I believe it's much easier to do
something like that with XSLT2. EXSLT is probably an
option, too, but that's something I'd try to avoid if at
all possible.
Just for the heck of it, simple arithmetics-only:
<xsl:stylesheet version="1.0"
xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
xmlns
ps="
http://www.example.org/Operators">
<ops
ps>
<ops
p name="+"/><ops
p name="-"/>
<ops
p name="*"/><ops
p name="/"/>
</ops
ps>
<xsl
utput method="xml"/>
<xsl:template match="ops
p[@name='+']" mode="eval">
<xsl
aram name="l"/><xsl
aram name="r"/>
<xsl:value-of select="$l+$r"/>
</xsl:template>
<xsl:template match="ops
p[@name='-']" mode="eval">
<xsl
aram name="l"/><xsl
aram name="r"/>
<xsl:value-of select="$l - $r"/>
</xsl:template>
<xsl:template match="ops
p[@name='*']" mode="eval">
<xsl
aram name="l"/><xsl
aram name="r"/>
<xsl:value-of select="$l*$r"/>
</xsl:template>
<xsl:template match="ops
p[@name='/']" mode="eval">
<xsl
aram name="l"/><xsl
aram name="r"/>
<xsl:value-of select="$l div $r"/>
</xsl:template>
<xsl:template name="eval">
<xsl
aram name="l"/>
<xsl
aram name="x"/>
<xsl:variable name="car" select="substring($x,1,1)"/>
<xsl:variable name="cdr" select="substring($x,2)"/>
<xsl:choose>
<xsl:when test="document('')//ops
p[@name=$car]">
<xsl:apply-templates
select="document('')//ops
p[@name=$car]"
mode="eval">
<xsl:with-param name="l" select="$l"/>
<xsl:with-param name="r">
<xsl:call-template name="eval">
<xsl:with-param name="l" select="''"/>
<xsl:with-param name="x" select="$cdr"/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:when>
<xsl:when test="$car">
<xsl:call-template name="eval">
<xsl:with-param name="l"
select="concat($l,$car)"/>
<xsl:with-param name="x"
select="$cdr"/>
</xsl:call-template>
</xsl:when>
<xsl
therwise>
<xsl:value-of select="$l"/>
</xsl
therwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{name()}">
<xsl:call-template name="eval">
<xsl:with-param name="l" select="''"/>
<xsl:with-param name="x" select="."/>
</xsl:call-template>
</xsl:attribute>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note that it's totally unaware of precedence. (It actually
calculates the right-most expression first. D'oh.) It can
recurse itself unto death really fast, too. And I don't
even mention precision problems it seems to be suffering
from (well, I suppose that's processor-dependent).