] > pmathml.modes: p-MathML support for XML and XHTML

pmathml.modes: p-MathML support for XML and XHTML

This mode provides basic support to standard p-MathML constructs in XML or HTML applications. It does not provide many "convenient" extensions -- see other modules in this directory for those.

1 Synopsis

The p-MathML module pmathml.modes in the directory GLOSS/mv/pmath/ contains code for presenting presentation-MathML in xml and xhtml documents.

See http://www.w3.org/Math/ for information on MathML. Version 2.0 is supported; other versions may also work. See also the unicode pages at http://www.unicode.org/.

The p-MathML module implements standard p-MathML only, and tries to implement ALL relevant names from the list of MathML entities and relevant unicode blocks, and all standard p-MathML constructs. It provides a small number of abbreviations and convenient features. More particularly, it is extensible: either to add new constructs and token names or to add semantics content in one of a number of forms.

Other modules present in this directory and elsewhere provide names of characters and further convenient mathematics constructs. Please report any non-compliance with the MathML standards (such as a mis-spelled, absent or extra name) as a bug.

2 Details

There are a number of driver files, with different options loaded. The MVs XXXX-xml.mv are intended for xml with embedded MathML or pure MathML itself, and XXX-xhtml.mv are intended for xhtml with embedded MathML. The driver xhtml.mv contains just about all the options available.

By and large, MathML can be entered using the normal GLOSS-xml syntax. Mathemtics mode is triggered with the math tag in GLOSS source (this is configurable with the m:math parameter) and p-MathML constructs can be used directly. An option is present to add a namespace prefix using the m:mathml-prefix parameter.

Since MathML is entered in the way outlined in the MathML specifications, the reader should consult those for details. This document will concentrate on implementation details and some shortcuts that can be used.

2.1 Tokens

Tokens are indicated using mi, mn, mo, ms, mtext. These elements accept the usual range of attributes and content is generated in the way expected.

math 
  mtext [Theorem:[ ]] 
  mrow
    mrow
      mn [234] 
      mo [+] 
      mi [y] 
    mo [=] 
    ms [happy]

yields

Theorem: 234+y=happy

The elements mspace, or mglyph behave slightly differently since they are empty, but can always be treated in this way, and these two usually are.

However, the normal way of working with tokens is to use abbreviations. pmathml.modes knows a few abbreviations and will guess and insert a tag mi, mn, mo, ms, or mtext around data.

math [Theorem:[ ]] 234 + y = "happy"

yields

Theorem: 234+y=happy

A long list of additional names for tokens along with associated attribute values are provided in extra modules. Most of these names are simply names of a single unicode character, for example naturals for . It is easy to extend this list for your own application, and a name can or other input GLOSS token can correspond to any p-MathML token, or empty character.

Note that the abbreviated tokens can be used as data for other token constructions, for the few occasions you want an operator symbol to be regarded as an identifier, perhaps. Thus

math
   mi subseteq
   =
   mi subset

should do the right thing:

=

2.2 Compound mathematics

All of the tags, mrow, mtable, msubsup, etc, can be used according to GLOSS's usual indentation and grouping rules. You are directed to chapter 3 of the MathML specification for details. However, the current (and slightly experimental) default for the grouping construct {...} is to add an automatic mrow as well as perform grouping. mrows are also added automatically to the arguments of certain standard constructs. This feature can be turned off with the m:insert-extra-mrows parameter. It doesn't apply to the entries in a table.

The rules are:

The rationale is that lazy authors of p-MathML (such as the present one) often omit to insert enough mrows, writing long rows of tokens that are difficult to parse. These rules add the required mrows automatically in the places you'd hope, once a little practice has been obtained.

For example,

math
  mfrac
    { x sup 2 + 1 }
    { x + 2 }

yields

x2+1x+2

and

math
  i
  it
  mrow
    (
    mtable
      mtr 1 2 3       4
      mtr 2 3 {4 + i} 1
      mtr x a i       1
    )
  =
  mrow
    (
    mtable
      mtr i        {2 it i} {3 it i}        {4 it i}
      mtr {2 it i} {3 it i} {-1 + {4 it i}} i
      mtr {i it x} {i it a} -1              i
    )

yields

i(1234 234+i1 xai1 )=(i2i3i4i 2i3i-1+4ii ixia-1i )

2.3 Other time-saving features

The inline module sets the display="block" or display="inline" attribute on the math tag automatically. You may have to tweak the &inline.elements; entity slightly to get this to work in unusual cases, or failing that just set display manually with math @display[block] in the usual way.

The standard mvs are designed to insert a m: prefix on all MathML elements and insert correct document types for XHTML1.1+MathML2.0. Without this prefix the file may fail to display correctly. I'm not sure why.

3 The code

!declare-prefix @prefix[m] @uri[http://gloss.bham.ac.uk/mv/pmath/pmathml] {
!declare-prefix @prefix[xml] @uri[http://gloss.bham.ac.uk/mv/xml/xml] {

Parameters configuring this module:

!init-parameter @name[m:math] @value[math] ; the element name that triggers this behaviour
!init-parameter @name[m:mathml-prefix] @value[] ; the namespace prefix for mathml
!init-parameter @name[m:mathml-namespace] @value[http$://www.w3.org/1998/Math/MathML] ; the MathML namespace
!init-parameter @name[m:insert-extra-mrows] @value[yes] ; experimental feature adding mrows

The value of ${m:math} is a special element name that starts up math mode:

!mode @name[m:element] @template[xml:element] @type[execute]
  !hook @mode[xml:element] @action[execute] 
  !elt 
    !if @test[$q] @value[$\{m:math\}]
      !if @test[$\{m:mathml-prefix\}] !set-parameter @name[m:pref] @value[$\{m:mathml-prefix\}$:]
      !else !set-parameter @name[m:pref] @value[]
      !element @name[$\{m:pref\}math] @ns[$\{m:mathml-namespace\}]
        !process-tokens @mode[m:attributes]
          !set-parameter @name[m:parent] @value[math]
        !if @test[$\{m:display\}] !attribute @name[display] [$\{m:display\}]
        !process-tokens @mode[m:mrow-content]
          !set-parameter @name[m:parent] @value[math]
          !set-parameter @name[xml:inner-structured-content] @value[m:mrow-content]
    !else !execute @mode[xml:element] @hook[execute]
  !include @mode[xml:element] @hook[execute]

The contents of a row.

!mode @name[m:mrow-content] @type[process]
  @accept[attr|char|cref|elt|eref|fp|hex|int|pdef|pelt|pref|pi|str|uri|!CDATA|!LITERAL|!|\[|\]|\{|\}|ns]
  !punc @data[\}] !abort
  !punc @data[\]] !abort
  !default !execute @mode[m:mrow-item]

An item in a row.

!mode @name[m:mrow-item] @children[1] @type[execute]
  @accept[attr|char|cref|elt|eref|fp|hex|int|pdef|pelt|pref|pi|str|uri|!CDATA|!LITERAL|!|\[|\]|\{|\}|uc]

The standard { } method of grouping is modified so that it adds an mrow as well.

  !punc @data[\{] 
    !if @test[$\{m:insert-extra-mrows\}] @value[yes]
      !element @name[$\{m:pref\}mrow]
        !process-tokens @mode[m:mrow-content] @use-indentation[false]
      !process-tokens @mode[xml:check-close-brace]
    !else 
      !process-tokens @mode[m:mrow-content] @use-indentation[false]
      !process-tokens @mode[xml:check-close-brace]
  !punc @data[\}] !abort
  !punc @data[\]] !abort
  !punc @data[\[] 
    !element @name[$\{m:pref\}mtext]
      !execute @mode[m:text]
        !set-parameter @name[m:parent] @value[mtext]

@href, @type: hyperref using xlink

  !attr @fullname[href] 
    !attribute @name[xlink$:href] @ns[http$://www.w3.org/1999/xlink]
      !process-tokens @mode[xml:text]
  !attr @fullname[type]
    !attribute @name[xlink$:type] @ns[http$://www.w3.org/1999/xlink] 
      !process-tokens @mode[xml:text]

token elements:

  !elt @data[$mi||mn||mo||mtext||ms]
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:mathmlcharacters] @children[1]
        !set-parameter @name[m:parent] @value[$q]
  !elt @data[$mspace||malignmark]
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]

Constructs with 0,1, or more arguments.

  !elt @data[$mrow||msqrt||mstyle||merror||mpadded||mphantom||mfenced||menclose||mmultiscripts||maction]
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:mrow-content]
        !set-parameter @name[m:parent] @value[$q]

Constructs with 2 arguments

  !elt @data[$mfrac||mroot||msub||msup||munder||mover]
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:math-object]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:math-object]
        !set-parameter @name[m:parent] @value[$q]

Constructs with 3 arguments.

  !elt @data[$msubsup||munderover]
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:math-object]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:math-object]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:math-object]
        !set-parameter @name[m:parent] @value[$q]

Empty constructs.

  !elt @data[$mprescripts||none||malignmark||maligngroup]
    !if-not @test[$\{m:parent\}] @value[mmultiscripts]
      !message[Warning$: mprescripts found outside mmultiscripts context[
]]
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]

Tables, matrices

  mtable
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:table-content]
        !set-parameter @name[m:parent] @value[$q]

Semantics; content is a math-object followed by any XML.

  semantics
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:math-object]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:annotations]
        !set-parameter @name[m:parent] @value[$q]

math-tokens

  !elt  !execute @mode[m:math-token]
  !int  !execute @mode[m:math-token]
  !hex  !execute @mode[m:math-token]
  !fp   !execute @mode[m:math-token]
  !str  !execute @mode[m:math-token]
  !char !execute @mode[m:math-token]
  !eref !execute @mode[m:math-token]
  !cref !execute @mode[m:math-token]
  !uc   !execute @mode[m:math-token]

finally, deal with pi, !literal !cdata etc

  !include @mode[xml:structured-content]

A single math object: use process-tokens to do this one.

!mode @name[m:math-object] @children[1] @type[process]
  @template[m:mrow-content]
  !default !execute @mode[m:mrow-item]

m:annotations: annotation or annotation-xml content of semantics

!mode @name[m:annotations] @accept[elt|\{|\}|!LITERAL|!] @type[process]
  !punc @data[\}] !abort
  !punc @data[\{]
    !execute @mode[xml:brace-group]
      !set-parameter @name[xml:inner-structured-content] @value[m:annotations]
  !elt @fullname[$annotation||annotation-xml]
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[xml:structured-content]
        !set-parameter @name[xml:inner-structured-content] @value[xml:structured-content]
  !include @mode[xml:structured-content]

m:table-content: content of a table

!mode @name[m:table-content] @type[process]
  @accept[elt|\{|\}|\]|!CDATA|!LITERAL|!]
  !punc @data[\{] 
    !process-tokens @mode[m:table-content] @use-indentation[false]
    !process-tokens @mode[xml:check-close-brace]
  !punc @data[\}] !abort
  !punc @data[\]] !abort
  !elt @fullname[$mlabeledtr||mtr]
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:mtr-content]
        !set-parameter @name[m:parent] @value[$q]
      !text 

  !elt
    !message[Warning$: unknown element $q in table[
]]
    !execute @mode[m:mrow-item]
  !include @mode[xml:structured-content]

m:mtr-content: content of a table row.

!mode @name[m:mtr-content] @type[process]
  @accept[attr|char|cref|elt|eref|fp|hex|int|pdef|pelt|pref|pi|str|uri|!CDATA|!LITERAL|!|\[|\]|\{|\}|ns]
  mtd 
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
      !process-tokens @mode[m:math-object]
        !set-parameter @name[m:parent] @value[$q]
  !punc @data[\{] !element @name[$\{m:pref\}mtd] !execute @mode[m:mrow-item]
  !punc @data[\[] !element @name[$\{m:pref\}mtd] !execute @mode[m:mrow-item]
  !elt  !element @name[$\{m:pref\}mtd] !execute @mode[m:math-token]
  !int  !element @name[$\{m:pref\}mtd] !execute @mode[m:math-token]
  !hex  !element @name[$\{m:pref\}mtd] !execute @mode[m:math-token]
  !fp   !element @name[$\{m:pref\}mtd] !execute @mode[m:math-token]
  !str  !element @name[$\{m:pref\}mtd] !execute @mode[m:math-token]
  !char !element @name[$\{m:pref\}mtd] !execute @mode[m:math-token]
  !eref !element @name[$\{m:pref\}mtd] !execute @mode[m:math-token]
  !cref !element @name[$\{m:pref\}mtd] !execute @mode[m:math-token]
  !uc   !element @name[$\{m:pref\}mtd] !execute @mode[m:math-token]
  !include @mode[xml:structured-content]

!mode @name[m:text] @template[xml:text]
  !punc @data[\[] 
    !execute @mode[xml:text]
      !set-parameter @name[xml:inner-structured-content] @value[m:mathmlcharacters]
  !punc @data[]
    !message [ERROR$: a \[ was expected here, line $l, column $c[
]]

content of token: mi,mn,mo,mtext,ms only.

!mode @name[m:mathmlcharacters] 
  @template[m:mrow-content] 
  @type[process]

allow the standard { } method of grouping and text content.

  !punc @data[\{]
    !execute @mode[xml:brace-group]
      !set-parameter @name[xml:inner-structured-content] @value[m:mathmlcharacters]
  !punc @data[\}] !abort
  !punc @data[\[] 
    !execute @mode[xml:text]
      !set-parameter @name[xml:inner-structured-content] @value[m:mathmlcharacters]
  !punc @data[\]] !abort
  !elt @fullname[$malignmark||mglyph]
    !element @name[$\{m:pref\}$q]
      !process-tokens @mode[m:attributes]
        !set-parameter @name[m:parent] @value[$q]
  !default !execute @mode[m:math-token]
   

attributes for a math object

!mode @name[m:attributes] @accept[attr] @type[process]

TO DO: if possible or feasible, check correct attributes are used; current version checks nothing

  !attr 
    !execute @mode[xml:attribute]
  !attr 
    @fullname[$href||type]
    !execute @mode[xml:attribute] @data[xlink$:$q]
      !set-parameter @name[\{http://gloss.bham.ac.uk/mv/xmlnamespaces\}xlink] @value[http$://www.w3.org/1999/xlink]

m:math-token mode

!mode @name[m:math-token] @type[execute]
  @accept[elt|int|hex|fp|str|char|eref|cref|\[|uc]
  !default
    !execute @mode[m:token-dictionary] @parameters[share]
      !set-parameter @name[m:token-type] @value[mo]
    !if-not @test[$\{m:parent\}] @value[mi]
      !if-not @test[$\{m:parent\}] @value[mn]
        !if-not @test[$\{m:parent\}] @value[mo]
          !if-not @test[$\{m:parent\}] @value[mtext]
            !if-not @test[$\{m:parent\}] @value[ms]
              !element @name[$\{m:pref\}$\{m:token-type\}]
                !execute @mode[m:token-content] 
                  !set-parameter @name[m:parent] @value[$\{m:token-type\}]
                !return
    !execute @mode[m:token-content]

m:token-content

prints token content and any remaining attributes

!mode @name [m:token-content] @children[1] @type[execute]
  @accept[elt|int|hex|fp|str|char|eref|cref|\[|uc]
  !default
    !if @test[$\{m:href\}] !attribute @name['xlink:href'] @ns[http$://www.w3.org/1999/xlink] [$\{m:href\}]
    !if @test[$\{m:type\}] !attribute @name['xlink:type'] @ns[http$://www.w3.org/1999/xlink] [$\{m:type\}]
    !if @test[$\{m:class\}] !attribute @name[class] [$\{m:class\}]
    !if @test[$\{m:style\}] !attribute @name[style] [$\{m:style\}]
    !if @test[$\{m:id\}] !attribute @name[id] [$\{m:id\}]
    !if @test[$\{m:xref\}] !attribute @name[xref] [$\{m:xref\}]
    !if @test[$\{m:fontfamily\}]
      !if @test[$\{m:parent] @value[mglyph] !attribute @name[fontfamily] [$\{m:fontfamily\}]
    !if-not @test[$\{m:parent\}] @value[mspace]
      !if @test[$\{m:mathvariant\}] !attribute @name[mathvariant] [$\{m:mathvariant\}]
      !if @test[$\{m:mathsize\}] !attribute @name[mathsize] [$\{m:mathsize\}]
      !if @test[$\{m:mathcolor\}] !attribute @name[mathcolor] [$\{m:mathcolor\}]
      !if @test[$\{m:mathbackground\}] !attribute @name[mathbackground] [$\{m:mathbackground\}]
    !if @test[$\{m:parent\}] @value[ms]
      !if @test[$\{m:lquote\}] !attribute @name[lquote] [$\{m:lquote\}]
      !if @test[$\{m:rquote\}] !attribute @name[rquote] [$\{m:rquote\}]
    !if @test[$\{m:parent\}] @value[mo]
      !if @test[$\{m:form\}] !attribute @name[form] [$\{m:form\}]
      !if @test[$\{m:fence\}] !attribute @name[fence] [$\{m:fence\}]
      !if @test[$\{m:separator\}] !attribute @name[separator] [$\{m:separator\}]
      !if @test[$\{m:lspace\}] !attribute @name[lspace] [$\{m:lspace\}]
      !if @test[$\{m:rspace\}] !attribute @name[rspace] [$\{m:rspace\}]
      !if @test[$\{m:stretchy\}] !attribute @name[stretchy] [$\{m:stretchy\}]
      !if @test[$\{m:symmetric\}] !attribute @name[symmetric] [$\{m:symmetric\}]
      !if @test[$\{m:maxsize\}] !attribute @name[maxsize] [$\{m:maxsize\}]
      !if @test[$\{m:minsize\}] !attribute @name[minsize] [$\{m:minsize\}]
      !if @test[$\{m:largeop\}] !attribute @name[largeop] [$\{m:largeop\}]
      !if @test[$\{m:movablelimits\}] !attribute @name[movablelimits] [$\{m:movablelimits\}]
      !if @test[$\{m:accent\}] !attribute @name[accent] [$\{m:accent\}]
    !if @test[$\{m:text\}] !text [$\{m:text\}]
    !else
      !if @test[$\{m:ref1\}] 
        !entity-reference @name[$\{m:ref1\}]
        !if @test[$\{m:ref2\}] !entity-reference @name[$\{m:ref2\}]
        !if @test[$\{m:ref3\}] !entity-reference @name[$\{m:ref3\}]

m:token-dictionary

This mode presents a long list of built-in standard tokens. Its job is to set parameters correctly: the parameters are ${m:token-type}="mo","mi","mn","mtext","ms" ${m:text} OR ${m:ref1},${m:ref2},${m:ref3} = content ${m:ATTR}=value, for each possible attribute In other words, this mode behaves as a dictionary of defaults. Note p-MathML itself has a built-in set of defaults for mo tokens at rendering stage, the "operator dictionary". Settings here will over-rule those, these can and should be rather minimal.

!mode @name [m:token-dictionary] @children[1] @type[execute]
  @accept[elt|int|hex|fp|str|char|elt|eref|cref|\[|uc]
  !punc @data[\[]
    !process-tokens @mode[xml:process-attr]
      !set-parameter @name[xml:attr-param] @value[m:text]
    ${m:token-type}="mtext"

arabic elements a-z and A-Z

  !elt
    @data[$a||b||c||d||e||f||g||h||i||j||k||l||m||n||o||p||q||r||s||t||u||v||w||x||y||z]
    ${m:token-type}="mi" ${m:text}="$d"
  !elt
    @data[$A||B||C||D||E||F||G||H||I||J||K||L||M||N||O||P||Q||R||S||T||U||V||W||X||Y||Z]
    ${m:token-type}="mi" ${m:text}="$d"
  !uc
    @data[$0--9] ${m:token-type}="mn" ${m:text}="$d"
  !uc
    @data[$a--z|A--Z] ${m:token-type}="mi" ${text}="$d"
  !uc
    ${m:token-type}="mo" ${m:text}="$d"

numbers and other built-in gloss types

  !int   ${m:token-type}="mn" ${m:text}="$v" ; number
  !hex   ${m:token-type}="mn" ${m:text}="$v" ; number
  !fp    ${m:token-type}="mn" ${m:text}="$v" ; number
  !char  ${m:token-type}="ms" ${m:text}="$v" ; string
  !str   ${m:token-type}="ms" ${m:text}="$v" ; string

generic entity or character reference, default = mo

  !eref ${m:token-type}="mo" ${m:ref1}="$q"
  !cref ${m:token-type}="mo" ${m:ref1}="$q"

warning on unknown token

  !elt ${m:text}="?" !message[Unknown math token name in line $l: $q;[
]]

error if no token found

  !default !error[token not in math token dictionary]

mode to hook further entity names etc

!mode @name[m:entities] @accept[elt|int|hex|fp|str|char|elt|eref|cref|\[|uc] @type[process]

}; declare-prefix
}; declare-prefix

This file is part of the GLOSS system, Copyright Richard Kaye http://gloss.bham.ac.uk/. Usage permitted under the GPL. No Warranty.

This page is copyright. Web page design and creation by GLOSS.