<!-- 

   mml.xsl: a mathml expression evaluator
   Copyright &copy; 2004 Max Froumentin

     Use and distribution of this code are permitted under the terms of the <a
     href="http://www.w3.org/Consortium/Legal/copyright-software-29921231"
     >W3C Software Notice and License</a>.

  this stylesheet takes a MathML file (Content MathML expression)
  describing a set of rules, like pm=ci*opoa/100,
  and a CompanyReport file (passed as 'datafilename' parameter).
  The rules are applied to the company report file and the results are 
  printed out. Usage:

  xsltproc - -param datafilename \'reports.xml\' mml.xsl mmlrules.mml

  Currently this stylesheet only supports plus, minus, times and divide.
  While it's easy to add more template to support more of MathML, it's less
  easy to actually perform complex operations. Using exslt might allow 
  coverage of many ops.

-->   


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
		xmlns:mml="http://www.w3.org/1998/Math/MathML"
		xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
		xmlns:fc="http://xmlns.com/foaf/corp#"
		version="1.0">

  <xsl:param name="datafilename" select="'reports.xml'"/>


  <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>
  
  <xsl:template match="mml:apply">
<!-- <xsl:message>[apply]</xsl:message> -->
    <xsl:apply-templates select="*[1]"/>
  </xsl:template>


  <!--===========================================================-->

  <xsl:template match="mml:divide">
    <xsl:variable name="op1">
      <xsl:apply-templates select="following-sibling::*[1]"/>
    </xsl:variable>
    <xsl:variable name="op2">
      <xsl:apply-templates select="following-sibling::*[2]"/>
    </xsl:variable>
<!--    <xsl:message>[divide: <xsl:value-of select="$op1"/> div <xsl:value-of select="$op2"/> = <xsl:value-of select="$op1 div $op2"/>]</xsl:message> -->
    <xsl:value-of select="$op1 div $op2"/>
  </xsl:template>


  <!--===========================================================-->

  <xsl:template match="mml:plus">
<!--    <xsl:message>[plus]</xsl:message>-->
    <xsl:apply-templates select="following-sibling::*[1]" mode="n-ary-plus"/>
  </xsl:template>

  <xsl:template match="*" mode="n-ary-plus">
    <xsl:variable name="first">
      <xsl:apply-templates select="."/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="following-sibling::*">
	<xsl:variable name="rest">
	  <xsl:apply-templates select="following-sibling::*[1]" 
			       mode="n-ary-plus"/>
	</xsl:variable>
<!--	<xsl:message>[plusop-list: <xsl:value-of select="$first + $rest"/>]</xsl:message>-->
	<xsl:value-of select="$first + $rest"/>
      </xsl:when>
      <xsl:otherwise>
<!--	<xsl:message>[plusop-atom: <xsl:value-of select="$first"/>]</xsl:message>-->
	<xsl:value-of select="$first"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!--===========================================================-->
  <xsl:template match="mml:minus">
    <!--    <xsl:message>[plus]</xsl:message>-->
    <xsl:apply-templates select="following-sibling::*[1]" mode="n-ary-minus"/>
  </xsl:template>

  <xsl:template match="*" mode="n-ary-minus">
    <xsl:variable name="first">
      <xsl:apply-templates select="."/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="following-sibling::*">
	<xsl:variable name="rest">
	  <xsl:apply-templates select="following-sibling::*[1]" 
			       mode="n-ary-minus"/>
	</xsl:variable>
<!--	<xsl:message>[minusop-list: <xsl:value-of select="$first - $rest"/>]</xsl:message>-->
	<xsl:value-of select="$first - $rest"/>
      </xsl:when>
      <xsl:otherwise>
<!--	<xsl:message>[minusop-atom: <xsl:value-of select="$first"/>]</xsl:message>-->
	<xsl:value-of select="$first"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!--===========================================================-->

  <xsl:template match="mml:times">
    <xsl:apply-templates select="following-sibling::*[1]" mode="n-ary-times"/>
  </xsl:template>

  <xsl:template match="*" mode="n-ary-times">
    <xsl:variable name="first">
      <xsl:apply-templates select="."/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="following-sibling::*">
	<xsl:variable name="rest">
	  <xsl:apply-templates select="following-sibling::*[1]" 
			       mode="n-ary-times"/>
	</xsl:variable>
<!--	<xsl:message>[timesop-list: <xsl:value-of select="$first * $rest"/>]</xsl:message>-->
	<xsl:value-of select="$first * $rest"/>
      </xsl:when>
      <xsl:otherwise>
<!--	<xsl:message>[timesop-atom: <xsl:value-of select="$first"/>]</xsl:message>-->
	<xsl:value-of select="$first"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!--===========================================================-->
  <xsl:template match="mml:eq">
<!--    <xsl:message>[equal]</xsl:message> -->
    <xsl:value-of select="following-sibling::*[1]"/>
    <xsl:text> = </xsl:text>
    <xsl:apply-templates select="following-sibling::*[2]"/>
  </xsl:template>

  <xsl:template match="mml:cn">
    <xsl:value-of select="."/>
  </xsl:template>

  <xsl:template match="mml:ci">
    <!-- fetch the value of the variable in the data file -->
<!--    <xsl:message>[ci:<xsl:value-of select="."/>]</xsl:message> -->
    <xsl:variable name="val">
      <xsl:value-of select="document($datafilename)/rdf:RDF/fc:CompanyReport/*[name(.)=current()]"/>
    </xsl:variable>
    <xsl:if test="$val = ''">
      <xsl:message>Error: variable name '<xsl:value-of select="."/>' not found in data file.</xsl:message>
    </xsl:if>
    <xsl:value-of select="$val"/>
  </xsl:template>


</xsl:stylesheet>