Re: [xsl] How to dynamically evaluate an equation in the input XML document?

Subject: Re: [xsl] How to dynamically evaluate an equation in the input XML document?
From: "Mukul Gandhi mukulg@xxxxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 15 Jul 2021 06:04:49 -0000
On Thu, Jul 15, 2021 at 12:18 AM Roger L Costello costello@xxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:


> I have XML documents like this:
>
> <Convert-to-Celsius>
>     <equation>(Fahrenheit - 32) * (5/9)</equation>
>     <variable>
>         <name>Fahrenheit</name>
>         <value>32</value>
>     </variable>
> </Convert-to-Celsius>
>
> The document contains an equation which might contain variables. If it
> does contain variables, then I need to fetch their values and replace the
> variables in the equation with their values and then compute the value of
> the equation.
>
> Have you done this kind of dynamic equation solving using XSLT? If so, how
> did you do it?
>

In an XSLT 2.0 environment with Saxon, I've attempted to do this as
following (examples that I've run are cited),

XSLT stylesheet,

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                         xmlns:xs="http://www.w3.org/2001/XMLSchema";

                         xmlns:saxon="http://saxon.sf.net/";
                         xmlns:fn1="http://fn1";
                         exclude-result-prefixes="xs saxon fn1"
                         version="2.0">

   <xsl:output method="text"/>

   <xsl:template match="Input">
     <xsl:value-of
select="saxon:evaluate(fn1:constructFinalExpression(equation,
variable[1]))"/>
   </xsl:template>

   <xsl:function name="fn1:constructFinalExpression" as="xs:string">
      <xsl:param name="equation" as="xs:string"/>
      <xsl:param name="variable" as="element(variable)"/>

      <xsl:choose>
        <xsl:when test="$variable/following-sibling::variable">
           <xsl:sequence select="fn1:constructFinalExpression(
                                          replace($equation,
$variable/name, $variable/value),

$variable/following-sibling::variable[1])"/>
        </xsl:when>
        <xsl:otherwise>
           <xsl:sequence select="replace($equation, $variable/name,
$variable/value)"/>
        </xsl:otherwise>
      </xsl:choose>
   </xsl:function>

</xsl:stylesheet>

1) XML document input,

<Input>
  <equation>(Fahrenheit - 32) * (5 div 9)</equation>
  <variable>
    <name>Fahrenheit</name>
    <value>32</value>
  </variable>
</Input>

Transformation result,

0

2) XML document input,

<Input>
  <equation>(x + 5) * (y + 5) * z</equation>
  <variable>
    <name>x</name>
    <value>2</value>
  </variable>
  <variable>
    <name>y</name>
    <value>3</value>
  </variable>
  <variable>
    <name>z</name>
    <value>2</value>
  </variable>
</Input>

Transformation result,

112


I've observed that, for example, if the input equation contains the
division operator as '/' instead of 'div' (as in XPath), Saxon gives me
following errors,

XPTY0019: Required item type of first operand of '/' is node(); supplied
value has item type xs:integer



-- 
Regards,
Mukul Gandhi

Current Thread