Calculate attributes with XSLT

Discussion in 'XML' started by Carles Company Soler, Oct 31, 2006.

  1. Hello,
    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?

    Thanks!
    Carles Company Soler, Oct 31, 2006
    #1
    1. Advertising

  2. Carles Company Soler wrote:

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


    <rect x="{2 + 3}" y="12">...</rect>
    The attribute value is interpreted as an attribute value template where
    {} contains an XPath expression, in that example simply one adding two
    numbers given as literals but of course you can have more complex XPath
    expressions as needed to compute the attribute value.

    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
    Martin Honnen, Oct 31, 2006
    #2
    1. Advertising

  3. Carles Company Soler wrote:
    > 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?


    Yes, but.

    XSLT can certainly perform math, since the XPath language can do so. So
    if the expression appears in the stylesheet, this is trivial.

    But XSLT doesn't normally have the ability to interpret expressions
    found in the input document rather than the stylesheet. Since that seems
    to be what you want, you'll have to do some more work -- essentially,
    you'll have to use XSLT as a programming language to implement an
    expression interpreter, doing the string operations to break up the
    expression into values and operators and executing the appropriate
    operations.

    This has certainly been done, and I suspect a websearch will dig up some
    examples. It isn't difficult if you have any experience with
    recursive-descent parsing, it's just a nuisance.

    Alternatively, some XSLT processors support the "dynamic" section of the
    EXSLT extension function library. This permits executing XPath
    expressions found in arbitrary string data. It's overkill for your
    stated needs, and of course relying on an extension function makes your
    stylesheet less portable, but it is another alternative. (Or you could
    plug in your own custom extension function, but obviously that's another
    step away from portability.)



    --
    () ASCII Ribbon Campaign | Joe Kesselman
    /\ Stamp out HTML e-mail! | System architexture and kinetic poetry
    Joe Kesselman, Oct 31, 2006
    #3
  4. Carles Company Soler

    Guest

    Carles Company Soler wrote:
    > 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:eek:ps="http://www.example.org/Operators">
    <ops:eek:ps>
    <ops:eek:p name="+"/><ops:eek:p name="-"/>
    <ops:eek:p name="*"/><ops:eek:p name="/"/>
    </ops:eek:ps>
    <xsl:eek:utput method="xml"/>
    <xsl:template match="ops:eek:p[@name='+']" mode="eval">
    <xsl:param name="l"/><xsl:param name="r"/>
    <xsl:value-of select="$l+$r"/>
    </xsl:template>
    <xsl:template match="ops:eek:p[@name='-']" mode="eval">
    <xsl:param name="l"/><xsl:param name="r"/>
    <xsl:value-of select="$l - $r"/>
    </xsl:template>
    <xsl:template match="ops:eek:p[@name='*']" mode="eval">
    <xsl:param name="l"/><xsl:param name="r"/>
    <xsl:value-of select="$l*$r"/>
    </xsl:template>
    <xsl:template match="ops:eek:p[@name='/']" mode="eval">
    <xsl:param name="l"/><xsl:param name="r"/>
    <xsl:value-of select="$l div $r"/>
    </xsl:template>
    <xsl:template name="eval">
    <xsl:param name="l"/>
    <xsl:param 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:eek:p[@name=$car]">
    <xsl:apply-templates
    select="document('')//ops:eek: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:eek:therwise>
    <xsl:value-of select="$l"/>
    </xsl:eek: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).

    --
    Pavel Lepin
    , Oct 31, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Max
    Replies:
    1
    Views:
    478
    Joe Kesselman
    Sep 22, 2006
  2. P4trykx
    Replies:
    2
    Views:
    1,807
    bruce barker
    Jan 31, 2007
  3. james_027

    class attributes & data attributes

    james_027, Jun 20, 2007, in forum: Python
    Replies:
    2
    Views:
    370
    Bruno Desthuilliers
    Jun 20, 2007
  4. Kyle Schmitt
    Replies:
    3
    Views:
    188
    Kyle Schmitt
    Jul 24, 2007
  5. Jayden
    Replies:
    16
    Views:
    512
    Steven D'Aprano
    Sep 29, 2012
Loading...

Share This Page