<!-- 

   mml.xsl: a mathml expression evaluator
   Copyright &copy; 2004 Max Froumentin
   additions July 2004 by Damian Steer (pldms@mac.com)

     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:param name="orig" select="."/>
    <xsl:for-each select="document($datafilename)/rdf:RDF/fc:CompanyReport">
      <xsl:variable name="com" select="."/>
	:source "<xsl:value-of select="$com/fc:source"/>";
        <xsl:apply-templates select="$orig/mml:math">
        <xsl:with-param name="com" select="$com"/>
      </xsl:apply-templates>
    </xsl:for-each>
  </xsl:template>
  
  <xsl:template match="mml:apply">
    <xsl:param name="com" />

    <!-- <xsl:message>[apply]</xsl:message> -->
    <xsl:apply-templates select="*[1]">
      <xsl:with-param name="com" select="$com"/>
    </xsl:apply-templates>
  </xsl:template>
  
  
  <!--===========================================================-->
  
  <xsl:template match="mml:divide">
    <xsl:param name="com" />
    <xsl:variable name="op1">
      <xsl:apply-templates select="following-sibling::*[1]">
        <xsl:with-param name="com" select="$com"/>
      </xsl:apply-templates>
    </xsl:variable>
    <xsl:variable name="op2">
      <xsl:apply-templates select="following-sibling::*[2]">
	      <xsl:with-param name="com" select="$com"/>
            </xsl:apply-templates>
          </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:param name="com" />
          <!--    <xsl:message>[plus]</xsl:message>-->
          <xsl:apply-templates select="following-sibling::*[1]" mode="n-ary-plus">
            <xsl:with-param name="com" select="$com"/>
          </xsl:apply-templates>
          
        </xsl:template>
        
        <xsl:template match="*" mode="n-ary-plus">
          <xsl:param name="com" />
          <xsl:variable name="first">
            <xsl:apply-templates select=".">
              <xsl:with-param name="com" select="$com"/>
            </xsl:apply-templates>
          </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:with-param name="com" select="$com" />
          </xsl:apply-templates>
          
        </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:param name="com" />
    <!--    <xsl:message>[plus]</xsl:message>-->
    <xsl:apply-templates select="following-sibling::*[1]" mode="n-ary-minus">
	      <xsl:with-param name="com" select="$com" />
            </xsl:apply-templates>
          </xsl:template>

          <xsl:template match="*" mode="n-ary-minus">
            <xsl:param name="com" />
    <xsl:variable name="first">
      <xsl:apply-templates select=".">
        <xsl:with-param name="com" select="$com"/>
	    </xsl:apply-templates>
          </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:with-param name="com" select="$com" />
          </xsl:apply-templates>
          
        </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:param name="com" />
  <xsl:apply-templates select="following-sibling::*[1]" mode="n-ary-times">
    <xsl:with-param name="com" select="$com"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="*" mode="n-ary-times">
  <xsl:param name="com" />
    <xsl:variable name="first">
      <xsl:apply-templates select=".">
	      <xsl:with-param name="com" select="$com"/>
	    </xsl:apply-templates>
    </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:with-param name="com" select="$com"/>
	    </xsl:apply-templates>
	</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:param name="com" />
<!--    <xsl:message>[equal]</xsl:message> -->

    <xsl:value-of select="following-sibling::*[1]"/>
    <xsl:text>  </xsl:text>
    <xsl:apply-templates select="following-sibling::*[2]">
	      <xsl:with-param name="com" select="$com"/>
	    </xsl:apply-templates>
  </xsl:template>

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

  <xsl:template match="mml:ci">
        <xsl:param name="com" />
    <!-- fetch the value of the variable in the data file -->
    <xsl:variable name="val">
      <xsl:value-of select="$com/*[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>
