4

I want to use xslt to output the math expression from Mathml input. There must be some mistake in my transform. I don't know how to correct it. Could you help me? Should I use parameter or variable to control it? xml:

<?xml version="1.0" encoding="UTF-8"?>

<math>
  <apply>
    <eq/>
    <apply>
      <plus/>
      <apply>
        <power/>
        <ci>x</ci>
        <cn>2</cn>
      </apply>
      <apply>
        <times/>
        <cn>2</cn>
        <ci>x</ci>
      </apply>
      <cn>2</cn>
    </apply>
    <cn>0</cn>
  </apply>
</math>

This is my xsl:

  <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:output method="text" encoding="UTF-8"/>

    <xsl:template match="/">
     <xsl:apply-templates/>
     <xsl:text>&#10;</xsl:text>
    </xsl:template>

    <xsl:template match="math">
            <xsl:apply-templates select="apply"/>
    </xsl:template>

    <xsl:template match="apply">

        <xsl:sequence select="name(element()[1]),'('"/>
        <xsl:apply-templates select="apply">
        </xsl:apply-templates>
        <xsl:sequence select="element()[2],','"/>
        <xsl:sequence select="element()[3],')',','"/>

   </xsl:template>

</xsl:stylesheet>

The result should be:

   eq(plus(power(x,2),times(2,x),2),0)
Emiliano Poggi
  • 24,390
  • 8
  • 55
  • 67
ZAWD
  • 651
  • 7
  • 31
  • @empo, I have to wonder if your edits should have been included in an answer instead of the question; it feels like you know what you're doing :) but I don't know _why_ you're doing them. :) – sarnold May 21 '11 at 21:25
  • @sarnold: they should be safe edits which make the question clear. I've added the missing portion of code to the xslt which declares the version used. I've set version 2.0 because the OP is using elements and function proper of XSLT 2.0. – Emiliano Poggi May 21 '11 at 21:36
  • @pst, the `1.0` was in @empo's _first_ edit, not supplied by @ZAWD's original post. :) – sarnold May 21 '11 at 21:40
  • Yes, sorry guys for making a few changes instead of a single one :) and thanks for having accepted them. – Emiliano Poggi May 21 '11 at 21:45
  • Good question, +1. See my answer for a complete and the simplest and shortest (for now) solution. :) – Dimitre Novatchev May 21 '11 at 22:54

2 Answers2

2

I've slightly changed your original transform to obtain the wanted result. Basically, the apply template rule it's the one deciding for the function parentesis. To determine whether or not insert a comma I'm checking for following sibling elements of specific types.

Moreover, I've replaced your xsl:sequence with xsl:value-of thus preventing the creation of unwanted spaces (I immagine they are unwanted). Also the function element() has been replaced. The stylesheet is now XSLT 1.0 compatible. I'm not a fun of XSLT 1.0, but I prefer to use new functions only when really necessary.

This solution is not very general (MATHML is a huge spec you know), but you can use it and adapt it to more complex cases.


XSLT 1.0 tested under Saxon 6.5.5

  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" encoding="UTF-8"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="apply">
        <xsl:value-of select="concat(name(child::*[1]),'(')"/>
        <xsl:apply-templates select="apply|cn|ci"/>
        <xsl:value-of select="')'"/>
        <xsl:if test="count(following-sibling::*)">
            <xsl:value-of select="','"/>
        </xsl:if>
    </xsl:template>

    <xsl:template match="cn|ci">
        <xsl:value-of select="."/>
        <xsl:if test="count(following-sibling::*)&gt;0">
            <xsl:value-of select="','"/>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

When applied to the input shown in the question produces:

eq(plus(power(x,2),times(2,x),2),0)
Emiliano Poggi
  • 24,390
  • 8
  • 55
  • 67
2

This complete and short transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="apply">
  <xsl:if test="not(position()=1)">,</xsl:if>
  <xsl:apply-templates select="*[1]"/>
 </xsl:template>

 <xsl:template match="eq|plus|power|times">
  <xsl:if test="not(position()=1)">,</xsl:if>
  <xsl:value-of select="concat(name(), '(')"/>
   <xsl:apply-templates select="following-sibling::*"/>
   <xsl:text>)</xsl:text>
 </xsl:template>

 <xsl:template match="cn|ci">
  <xsl:if test="not(position()=1)">,</xsl:if>
  <xsl:value-of select="."/>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<math>
    <apply>
        <eq/>
        <apply>
            <plus/>
            <apply>
                <power/>
                <ci>x</ci>
                <cn>2</cn>
            </apply>
            <apply>
                <times/>
                <cn>2</cn>
                <ci>x</ci>
            </apply>
            <cn>2</cn>
        </apply>
        <cn>0</cn>
    </apply>
</math>

produce the wanted, correct result:

eq(plus(power(x,2),times(2,x),2),0)
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • could you help me again.I have a new question about it:http://stackoverflow.com/questions/6113865/some-problems-in-my-xsl-about-mathml – ZAWD May 24 '11 at 16:45