A MathML document must be a well-formed XML document using elements in the MathML namespace as defined by this specification, however it is not required that the document refer to any specific Document Type Definition (DTD) or schema that specifies MathML. It is sometimes advantageous not to specify such a language definition as these files are large, often much larger than the MathML expression and unless they have been previously cached by the MathML application, the time taken to fetch the DTD or schema may have an appreciable effect on the processing of the MathML document.
Note that if no DTD is specified with a DOCTYPE declaration, that entity references (for example to refer to MathML characters by name) may not be used. The document should be encoded in an encoding (for example UTF-8) in which all needed characters may be encoded as character data, or characters may be referenced using numeric character references, for example ∫ rather than ∫
If a MathML fragment is parsed without a DTD, in other words as a well-formed XML fragment, it is the responsibility of the processing application to treat the white space characters occurring outside of token elements as not significant.
However, in many circumstances, especially while producing or editing MathML, it is useful to use a language definition to constrain the editing process or to check the correctness of generated files. The following section, Section A.2 Using the RelaxNG Schema for MathML3, discusses the RelaxNG Schema for MathML3 [RELAX-NG], which forms a normative part of the specification. Following that, Section A.4 Using the MathML XML Schema, and Section A.3 Using the MathML DTD discuss alternative languages definition using the document type definitions (DTD) and the W3C XML schema language, [XMLSchemas], both of which are derived from the normative RelaxNG schema automatically. One should note that the schema definitions of the language is currently stricter than the DTD version. That is, a schema validating processor will declare invalid documents that are declared valid by a (DTD) validating XML parser. This is partly due to the fact that the XML schema language may express additional constraints not expressable in the DTD, and partly due to the fact that for reasons of compatibility with earlier releases, the DTD is intentionally forgiving in some places and does not enforce constraints that are specified in the text of this specification.
MathML documents should be validated using the RelaxNG Schema for MathML, either in the XML encoding (http://www.w3.org/Math/RelaxNG/mathml3/mathml3.rng) or in compact notation (http://www.w3.org/Math/RelaxNG/mathml3/mathml3.rnc) which is also shown below.
In contrast to DTDs there is no in-document method to associate a RelaxNG schema with a document.
We provide five RelaxNG schema for MathML3 in five parts:
The grammar for full MathML
The grammar for elements common to Content and Presentation
The grammar for Presentation MathML
The grammar for Strict Content MathML
The grammar for Content MathML3
The RelaxNG schema for full MathML builds on the schema describing the various parts of the language which are given in the following sections. It can be found at http://www.w3.org/Math/RelaxNG/mathml3/mathml3.rnc.
# # Use and distribution of this code are permitted under the terms # W3C Software Notice and License # http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 default namespace m = "http://www.w3.org/1998/Math/MathML" ## Content MathML include "mathml3-content.rnc" ## Presentation MathML include "mathml3-presentation.rnc" ## math and semantics common to both Content and Presentation include "mathml3-common.rnc"
# # Use and distribution of this code are permitted under the terms # W3C Software Notice and License # http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 default namespace m = "http://www.w3.org/1998/Math/MathML" namespace local = "" start = math math = elementmath
{math.attributes,MathExpression*} MathExpression = semantics NonMathMLAtt = attribute(* - (local:*|m:*)
) {xsd:string} CommonDeprecatedAtt = attributeother
{text}? CommonAtt = attributeid
{xsd:ID}?, attributexref
{text}?, attributeclass
{xsd:NMTOKENS}?, attributestyle
{xsd:string}?, attributehref
{xsd:anyURI}?, CommonDeprecatedAtt, NonMathMLAtt* math.attributes = CommonAtt, attributedisplay
{"block" | "inline"}?, attributemaxwidth
{length}?, attributeoverflow
{"linebreak" | "scroll" | "elide" | "truncate" | "scale"}?, attributealtimg
{xsd:anyURI}?, attributealtimg-width
{length}?, attributealtimg-height
{length}?, attributealtimg-valign
{length | "top" | "middle" | "bottom"}?, attributealttext
{text}?, attributecdgroup
{xsd:anyURI}?, math.deprecatedattributes # the mathml3-presentation schema adds additional attributes # to the math element, all those valid on mstyle math.deprecatedattributes = attributemode
{xsd:string}?, attributemacros
{xsd:string}? name = attributename
{xsd:NCName} cd = attributecd
{xsd:NCName} src = attributesrc
{xsd:anyURI}? annotation = elementannotation
{annotation.attributes,text} annotation-xml.model = (MathExpression|anyElement)* anyElement = element (* - m:*) {(attribute*
{text}|text| anyElement)*} annotation-xml = elementannotation-xml
{annotation.attributes, annotation-xml.model} annotation.attributes = CommonAtt, cd?, name?, DefEncAtt, src? DefEncAtt = attributeencoding
{xsd:string}?, attributedefinitionURL
{xsd:anyURI}? semantics = elementsemantics
{semantics.attributes, MathExpression, (annotation|annotation-xml)*} semantics.attributes = CommonAtt,DefEncAtt,cd?,name? length # wrapped for display = xsd:string { pattern = '\s*((-?[0-9]*(\.[0-9]*)?(e[mx]|in|cm|mm|p[xtc]|%)?)|(negative)?((very){0,2}thi(n| ck)|medium)mathspace)\s*' }
# Copyright 1998-2010 W3C (MIT, ERCIM, Keio) # # Use and distribution of this code are permitted under the terms # W3C Software Notice and License # http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 default namespace m = "http://www.w3.org/1998/Math/MathML" MathExpression |= PresentationExpression ImpliedMrow = MathExpression* TableRowExpression = mtr|mlabeledtr TableCellExpression = mtd MstackExpression = MathExpression|mscarries|msline|msrow|msgroup MsrowExpression = MathExpression|none MultiScriptExpression = (MathExpression|none),(MathExpression|none) mpadded-length # wrapped for display = xsd:string { pattern = '\s*([\+\-]?[0-9]*(\.[0-9]*)?\s*((%?\s*(height|depth|width)?)|e[mx]|in| cm|mm|p[xtc]|((negative)?((very){0,2}thi(n|ck)|medium)mathspace)))\s*' } linestyle = "none" | "solid" | "dashed" verticalalign = "top" | "bottom" | "center" | "baseline" | "axis" columnalignstyle = "left" | "center" | "right" notationstyle = "longdiv" | "actuarial" | "radical" | "box" | "roundedbox" | "circle" | "left" | "right" | "top" | "bottom" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike" | "madruwb" idref = text unsigned-integer = xsd:unsignedLong integer = xsd:integer number = xsd:decimal character = xsd:string { pattern = '\s*\S\s*'} color # wrapped for display = xsd:string { pattern = '\s*((#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)|[aA][qQ][uU][aA]|[bB][lL][aA][cC][kK]| [bB][lL][uU][eE]|[fF][uU][cC][hH][sS][iI][aA]|[gG][rR][aA][yY]|[gG][rR][eE][eE][nN]| [lL][iI][mM][eE]|[mM][aA][rR][oO][oO][nN]|[nN][aA][vV][yY]|[oO][lL][iI][vV][eE]|[pP][uU][rR][pP][lL][eE]| [rR][eE][dD]|[sS][iI][lL][vV][eE][rR]|[tT][eE][aA][lL]|[wW][hH][iI][tT][eE]|[yY][eE][lL][lL][oO][wW])\s*'} group-alignment = "left" | "center" | "right" | "decimalpoint" group-alignment-list = list {group-alignment+} group-alignment-list-list = xsd:string { pattern = '(\s*\{\s*(left|center|right|decimalpoint)(\s+(left|center|right|decimalpoint))*\})*\s*' } positive-integer = xsd:positiveInteger TokenExpression = mi|mn|mo|mtext|mspace|ms token.content = mglyph|malignmark|text mi = elementmi
{mi.attributes, token.content*} mi.attributes = CommonAtt, CommonPresAtt, TokenAtt mn = elementmn
{mn.attributes, token.content*} mn.attributes = CommonAtt, CommonPresAtt, TokenAtt mo = elementmo
{mo.attributes, token.content*} mo.attributes = CommonAtt, CommonPresAtt, TokenAtt, attributeform
{"prefix" | "infix" | "postfix"}?, attributefence
{"true" | "false"}?, attributeseparator
{"true" | "false"}?, attributelspace
{length}?, attributerspace
{length}?, attributestretchy
{"true" | "false"}?, attributesymmetric
{"true" | "false"}?, attributemaxsize
{length | "infinity"}?, attributeminsize
{length}?, attributelargeop
{"true" | "false"}?, attributemovablelimits
{"true" | "false"}?, attributeaccent
{"true" | "false"}?, attributelinebreak
{"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak"}?, attributelineleading
{length}?, attributelinebreakstyle
{"before" | "after" | "duplicate" | "infixlinebreakstyle"}?, attributelinebreakmultchar
{text}?, attributeindentalign
{"left" | "center" | "right" | "auto" | "id"}?, attributeindentshift
{length}?, attributeindenttarget
{idref}?, attributeindentalignfirst
{"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, attributeindentshiftfirst
{length | "indentshift"}?, attributeindentalignlast
{"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, attributeindentshiftlast
{length | "indentshift"}? mtext = elementmtext
{mtext.attributes, token.content*} mtext.attributes = CommonAtt, CommonPresAtt, TokenAtt mspace = elementmspace
{mspace.attributes, empty} mspace.attributes = CommonAtt, CommonPresAtt, TokenAtt, attributewidth
{length}?, attributeheight
{length}?, attributedepth
{length}?, attributelinebreak
{"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak" | "indentingnewline"}? ms = elementms
{ms.attributes, token.content*} ms.attributes = CommonAtt, CommonPresAtt, TokenAtt, attributelquote
{text}?, attributerquote
{text}? mglyph = elementmglyph
{mglyph.attributes,mglyph.deprecatedattributes,empty} mglyph.attributes = CommonAtt, CommonPresAtt, attributesrc
{xsd:anyURI}?, attributewidth
{length}?, attributeheight
{length}?, attributevalign
{length}?, attributealt
{text}? mglyph.deprecatedattributes = attributeindex
{integer}?, attributemathvariant
{"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched"}?, attributemathsize
{"small" | "normal" | "big" | length}?, DeprecatedTokenAtt msline = elementmsline
{msline.attributes,empty} msline.attributes = CommonAtt, CommonPresAtt, attributeposition
{integer}?, attributelength
{unsigned-integer}?, attributeleftoverhang
{length}?, attributerightoverhang
{length}?, attributemslinethickness
{length | "thin" | "medium" | "thick"}? none = elementnone
{none.attributes,empty} none.attributes = CommonAtt, CommonPresAtt mprescripts = elementmprescripts
{mprescripts.attributes,empty} mprescripts.attributes = CommonAtt, CommonPresAtt CommonPresAtt = attributemathcolor
{color}?, attributemathbackground
{color | "transparent"}? TokenAtt = attributemathvariant
{"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched"}?, attributemathsize
{"small" | "normal" | "big" | length}?, attributedir
{"ltr" | "rtl"}?, DeprecatedTokenAtt DeprecatedTokenAtt = attributefontfamily
{text}?, attributefontweight
{"normal" | "bold"}?, attributefontstyle
{"normal" | "italic"}?, attributefontsize
{length}?, attributecolor
{color}?, attributebackground
{color | "transparent"}? MalignExpression = maligngroup|malignmark malignmark = elementmalignmark
{malignmark.attributes, empty} malignmark.attributes = CommonAtt, CommonPresAtt, attributeedge
{"left" | "right"}? maligngroup = elementmaligngroup
{maligngroup.attributes, empty} maligngroup.attributes = CommonAtt, CommonPresAtt, attributegroupalign
{"left" | "center" | "right" | "decimalpoint"}? PresentationExpression = TokenExpression|MalignExpression| mrow|mfrac|msqrt|mroot|mstyle|merror|mpadded|mphantom| mfenced|menclose|msub|msup|msubsup|munder|mover|munderover| mmultiscripts|mtable|mstack|mlongdiv|maction mrow = elementmrow
{mrow.attributes, MathExpression*} mrow.attributes = CommonAtt, CommonPresAtt, attributedir
{"ltr" | "rtl"}? mfrac = elementmfrac
{mfrac.attributes, MathExpression, MathExpression} mfrac.attributes = CommonAtt, CommonPresAtt, attributelinethickness
{length | "thin" | "medium" | "thick"}?, attributenumalign
{"left" | "center" | "right"}?, attributedenomalign
{"left" | "center" | "right"}?, attributebevelled
{"true" | "false"}? msqrt = elementmsqrt
{msqrt.attributes, ImpliedMrow} msqrt.attributes = CommonAtt, CommonPresAtt mroot = elementmroot
{mroot.attributes, MathExpression, MathExpression} mroot.attributes = CommonAtt, CommonPresAtt mstyle = elementmstyle
{mstyle.attributes, ImpliedMrow} mstyle.attributes = CommonAtt, CommonPresAtt, mstyle.specificattributes, mstyle.generalattributes, mstyle.deprecatedattributes mstyle.specificattributes = attributescriptlevel
{integer}?, attributedisplaystyle
{"true" | "false"}?, attributescriptsizemultiplier
{number}?, attributescriptminsize
{length}?, attributeinfixlinebreakstyle
{"before" | "after" | "duplicate"}?, attributedecimalpoint
{character}? mstyle.generalattributes = attributeaccent
{"true" | "false"}?, attributeaccentunder
{"true" | "false"}?, attributealign
{"left" | "right" | "center"}?, attributealignmentscope
{list {("true" | "false") +}}?, attributebevelled
{"true" | "false"}?, attributecharalign
{"left" | "center" | "right"}?, attributecharspacing
{length | "loose" | "medium" | "tight"}?, attributeclose
{text}?, attributecolumnalign
{list {columnalignstyle+} }?, attributecolumnlines
{list {linestyle +}}?, attributecolumnspacing
{list {(length) +}}?, attributecolumnspan
{positive-integer}?, attributecolumnwidth
{list {("auto" | length | "fit") +}}?, attributecrossout
{list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}?, attributedenomalign
{"left" | "center" | "right"}?, attributedepth
{length}?, attributedir
{"ltr" | "rtl"}?, attributeedge
{"left" | "right"}?, attributeequalcolumns
{"true" | "false"}?, attributeequalrows
{"true" | "false"}?, attributefence
{"true" | "false"}?, attributeform
{"prefix" | "infix" | "postfix"}?, attributeframe
{linestyle}?, attributeframespacing
{list {length, length}}?, attributegroupalign
{group-alignment-list-list}?, attributeheight
{length}?, attributeindentalign
{"left" | "center" | "right" | "auto" | "id"}?, attributeindentalignfirst
{"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, attributeindentalignlast
{"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, attributeindentshift
{length}?, attributeindentshiftfirst
{length | "indentshift"}?, attributeindentshiftlast
{length | "indentshift"}?, attributeindenttarget
{idref}?, attributelargeop
{"true" | "false"}?, attributeleftoverhang
{length}?, attributelength
{unsigned-integer}?, attributelinebreak
{"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak"}?, attributelinebreakmultchar
{text}?, attributelinebreakstyle
{"before" | "after" | "duplicate" | "infixlinebreakstyle"}?, attributelineleading
{length}?, attributelinethickness
{length | "thin" | "medium" | "thick"}?, attributelocation
{"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?, attributelongdivstyle
{"lefttop" | "stackedrightright" | "mediumstackedrightright" | "shortstackedrightright" | "righttop" | "left/\right" | "left)(right" | ":right=right" | "stackedleftleft" | "stackedleftlinetop"}?, attributelquote
{text}?, attributelspace
{length}?, attributemathsize
{"small" | "normal" | "big" | length}?, attributemathvariant
{"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched"}?, attributemaxsize
{length | "infinity"}?, attributeminlabelspacing
{length}?, attributeminsize
{length}?, attributemovablelimits
{"true" | "false"}?, attributemslinethickness
{length | "thin" | "medium" | "thick"}?, attributenotation
{text}?, attributenumalign
{"left" | "center" | "right"}?, attributeopen
{text}?, attributeposition
{integer}?, attributerightoverhang
{length}?, attributerowalign
{list {verticalalign+} }?, attributerowlines
{list {linestyle +}}?, attributerowspacing
{list {(length) +}}?, attributerowspan
{positive-integer}?, attributerquote
{text}?, attributerspace
{length}?, attributeselection
{positive-integer}?, attributeseparator
{"true" | "false"}?, attributeseparators
{text}?, attributeshift
{integer}?, attributeside
{"left" | "right" | "leftoverlap" | "rightoverlap"}?, attributestackalign
{"left" | "center" | "right" | "decimalpoint"}?, attributestretchy
{"true" | "false"}?, attributesubscriptshift
{length}?, attributesuperscriptshift
{length}?, attributesymmetric
{"true" | "false"}?, attributevalign
{length}?, attributewidth
{length}? mstyle.deprecatedattributes = DeprecatedTokenAtt, attributeveryverythinmathspace
{length}?, attributeverythinmathspace
{length}?, attributethinmathspace
{length}?, attributemediummathspace
{length}?, attributethickmathspace
{length}?, attributeverythickmathspace
{length}?, attributeveryverythickmathspace
{length}? math.attributes &= CommonPresAtt math.attributes &= mstyle.specificattributes math.attributes &= mstyle.generalattributes merror = elementmerror
{merror.attributes, ImpliedMrow} merror.attributes = CommonAtt, CommonPresAtt mpadded = elementmpadded
{mpadded.attributes, ImpliedMrow} mpadded.attributes = CommonAtt, CommonPresAtt, attributeheight
{mpadded-length}?, attributedepth
{mpadded-length}?, attributewidth
{mpadded-length}?, attributelspace
{mpadded-length}?, attributevoffset
{mpadded-length}? mphantom = elementmphantom
{mphantom.attributes, ImpliedMrow} mphantom.attributes = CommonAtt, CommonPresAtt mfenced = elementmfenced
{mfenced.attributes, MathExpression*} mfenced.attributes = CommonAtt, CommonPresAtt, attributeopen
{text}?, attributeclose
{text}?, attributeseparators
{text}? menclose = elementmenclose
{menclose.attributes, ImpliedMrow} menclose.attributes = CommonAtt, CommonPresAtt, attributenotation
{text}? msub = elementmsub
{msub.attributes, MathExpression, MathExpression} msub.attributes = CommonAtt, CommonPresAtt, attributesubscriptshift
{length}? msup = elementmsup
{msup.attributes, MathExpression, MathExpression} msup.attributes = CommonAtt, CommonPresAtt, attributesuperscriptshift
{length}? msubsup = elementmsubsup
{msubsup.attributes, MathExpression, MathExpression, MathExpression} msubsup.attributes = CommonAtt, CommonPresAtt, attributesubscriptshift
{length}?, attributesuperscriptshift
{length}? munder = elementmunder
{munder.attributes, MathExpression, MathExpression} munder.attributes = CommonAtt, CommonPresAtt, attributeaccentunder
{"true" | "false"}?, attributealign
{"left" | "right" | "center"}? mover = elementmover
{mover.attributes, MathExpression, MathExpression} mover.attributes = CommonAtt, CommonPresAtt, attributeaccent
{"true" | "false"}?, attributealign
{"left" | "right" | "center"}? munderover = elementmunderover
{munderover.attributes, MathExpression, MathExpression, MathExpression} munderover.attributes = CommonAtt, CommonPresAtt, attributeaccent
{"true" | "false"}?, attributeaccentunder
{"true" | "false"}?, attributealign
{"left" | "right" | "center"}? mmultiscripts = elementmmultiscripts
{mmultiscripts.attributes, MathExpression,MultiScriptExpression*,(mprescripts,MultiScriptExpression*)?} mmultiscripts.attributes = msubsup.attributes mtable = elementmtable
{mtable.attributes, TableRowExpression*} mtable.attributes = CommonAtt, CommonPresAtt, attributealign
{xsd:string { pattern ='\s*(top|bottom|center|baseline|axis)\s*[0-9]*'}}?, attributerowalign
{list {verticalalign+} }?, attributecolumnalign
{list {columnalignstyle+} }?, attributegroupalign
{group-alignment-list-list}?, attributealignmentscope
{list {("true" | "false") +}}?, attributecolumnwidth
{list {("auto" | length | "fit") +}}?, attributewidth
{"auto" | length}?, attributerowspacing
{list {(length) +}}?, attributecolumnspacing
{list {(length) +}}?, attributerowlines
{list {linestyle +}}?, attributecolumnlines
{list {linestyle +}}?, attributeframe
{linestyle}?, attributeframespacing
{list {length, length}}?, attributeequalrows
{"true" | "false"}?, attributeequalcolumns
{"true" | "false"}?, attributedisplaystyle
{"true" | "false"}?, attributeside
{"left" | "right" | "leftoverlap" | "rightoverlap"}?, attributeminlabelspacing
{length}? mlabeledtr = elementmlabeledtr
{mlabeledtr.attributes, TableCellExpression+} mlabeledtr.attributes = mtr.attributes mtr = elementmtr
{mtr.attributes, TableCellExpression*} mtr.attributes = CommonAtt, CommonPresAtt, attributerowalign
{"top" | "bottom" | "center" | "baseline" | "axis"}?, attributecolumnalign
{list {columnalignstyle+} }?, attributegroupalign
{group-alignment-list-list}? mtd = elementmtd
{mtd.attributes, ImpliedMrow} mtd.attributes = CommonAtt, CommonPresAtt, attributerowspan
{positive-integer}?, attributecolumnspan
{positive-integer}?, attributerowalign
{"top" | "bottom" | "center" | "baseline" | "axis"}?, attributecolumnalign
{columnalignstyle}?, attributegroupalign
{group-alignment-list}? mstack = elementmstack
{mstack.attributes, MstackExpression*} mstack.attributes = CommonAtt, CommonPresAtt, attributealign
{xsd:string { pattern ='\s*(top|bottom|center|baseline|axis)\s*[0-9]*'}}?, attributestackalign
{"left" | "center" | "right" | "decimalpoint"}?, attributecharalign
{"left" | "center" | "right"}?, attributecharspacing
{length | "loose" | "medium" | "tight"}? mlongdiv = elementmlongdiv
{mlongdiv.attributes, MstackExpression,MstackExpression,MstackExpression+} mlongdiv.attributes = msgroup.attributes, attributelongdivstyle
{"lefttop" | "stackedrightright" | "mediumstackedrightright" | "shortstackedrightright" | "righttop" | "left/\right" | "left)(right" | ":right=right" | "stackedleftleft" | "stackedleftlinetop"}? msgroup = elementmsgroup
{msgroup.attributes, MstackExpression*} msgroup.attributes = CommonAtt, CommonPresAtt, attributeposition
{integer}?, attributeshift
{integer}? msrow = elementmsrow
{msrow.attributes, MsrowExpression*} msrow.attributes = CommonAtt, CommonPresAtt, attributeposition
{integer}? mscarries = elementmscarries
{mscarries.attributes, (MsrowExpression|mscarry)*} mscarries.attributes = CommonAtt, CommonPresAtt, attributeposition
{integer}?, attributelocation
{"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?, attributecrossout
{list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}?, attributescriptsizemultiplier
{number}? mscarry = elementmscarry
{mscarry.attributes, MsrowExpression*} mscarry.attributes = CommonAtt, CommonPresAtt, attributelocation
{"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?, attributecrossout
{list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}? maction = elementmaction
{maction.attributes, MathExpression+} maction.attributes = CommonAtt, CommonPresAtt, attributeactiontype
{text}?, attributeselection
{positive-integer}?
The grammar for Strict Content MathML3 can be found at http://www.w3.org/Math/RelaxNG/mathml3/mathml3-strict-content.rnc.
# # Use and distribution of this code are permitted under the terms # W3C Software Notice and License # http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 default namespace m = "http://www.w3.org/1998/Math/MathML" ContExp = semantics-contexp | cn | ci | csymbol | apply | bind | share | cerror | cbytes | cs cn = elementcn
{cn.attributes,cn.content} cn.content = text cn.attributes = attributetype
{"integer" | "real" | "double" | "hexdouble"} semantics-ci = elementsemantics
{semantics.attributes,(ci|semantics-ci), (annotation|annotation-xml)*} semantics-contexp = elementsemantics
{semantics.attributes,ContExp, (annotation|annotation-xml)*} ci = elementci
{ci.attributes, ci.content} ci.attributes = CommonAtt, ci.type? ci.type = attributetype
{"integer" | "rational" | "real" | "complex" | "complex-polar" | "complex-cartesian" | "constant" | "function" | "vector" | "list" | "set" | "matrix"} ci.content = text csymbol = elementcsymbol
{csymbol.attributes,csymbol.content} SymbolName = xsd:NCName csymbol.attributes = CommonAtt, cd csymbol.content = SymbolName BvarQ = bvar* bvar = elementbvar
{ ci | semantics-ci} apply = elementapply
{CommonAtt,apply.content} apply.content = ContExp+ bind = elementbind
{CommonAtt,bind.content} bind.content = ContExp,bvar*,ContExp share = elementshare
{CommonAtt, src, empty} cerror = elementcerror
{cerror.attributes, csymbol, ContExp*} cerror.attributes = CommonAtt cbytes = elementcbytes
{cbytes.attributes, base64} cbytes.attributes = CommonAtt base64 = xsd:base64Binary cs = elementcs
{cs.attributes, text} cs.attributes = CommonAtt MathExpression |= ContExp
The grammar for Content MathML3 builds on the grammar for the Strict Content MathML subset, and can be found at http://www.w3.org/Math/RelaxNG/mathml3/mathml3-content.rnc.
# Copyright 1998-2010 W3C (MIT, ERCIM, Keio) # # Use and distribution of this code are permitted under the terms # W3C Software Notice and License # http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 include "mathml3-strict-content.rnc"{ cn.content = (text | mglyph | sep | PresentationExpression)* cn.attributes = CommonAtt, DefEncAtt, attributetype
{text}?, base? ci.attributes = CommonAtt, DefEncAtt, ci.type? ci.type = attributetype
{text} ci.content = (text | mglyph | PresentationExpression)* csymbol.attributes = CommonAtt, DefEncAtt, attributetype
{text}?,cd? csymbol.content = (text | mglyph | PresentationExpression)* bvar = elementbvar
{ (ci | semantics-ci) & degree?} cbytes.attributes = CommonAtt, DefEncAtt cs.attributes = CommonAtt, DefEncAtt apply.content = ContExp+ | (ContExp, BvarQ, Qualifier*, ContExp*) bind.content = apply.content } base = attributebase
{text} sep = elementsep
{empty} PresentationExpression |= notAllowed DomainQ = (domainofapplication|condition|interval|(lowlimit,uplimit?))* domainofapplication = elementdomainofapplication
{ContExp} condition = elementcondition
{ContExp} uplimit = elementuplimit
{ContExp} lowlimit = elementlowlimit
{ContExp} Qualifier = DomainQ|degree|momentabout|logbase degree = elementdegree
{ContExp} momentabout = elementmomentabout
{ContExp} logbase = elementlogbase
{ContExp} type = attributetype
{text} order = attributeorder
{"numeric" | "lexicographic"} closure = attributeclosure
{text} ContExp |= piecewise piecewise = elementpiecewise
{CommonAtt, DefEncAtt,(piece* & otherwise?)} piece = elementpiece
{CommonAtt, DefEncAtt, ContExp, ContExp} otherwise = elementotherwise
{CommonAtt, DefEncAtt, ContExp} DeprecatedContExp = reln | fn | declare ContExp |= DeprecatedContExp reln = elementreln
{ContExp*} fn = elementfn
{ContExp} declare = elementdeclare
{attributetype
{xsd:string}?, attributescope
{xsd:string}?, attributenargs
{xsd:nonNegativeInteger}?, attributeoccurrence
{"prefix"|"infix"|"function-model"}?, DefEncAtt, ContExp+} interval.class = interval ContExp |= interval.class interval = elementinterval
{ CommonAtt, DefEncAtt,closure?, ContExp,ContExp} unary-functional.class = inverse | ident | domain | codomain | image | ln | log | moment ContExp |= unary-functional.class inverse = elementinverse
{ CommonAtt, DefEncAtt, empty} ident = elementident
{ CommonAtt, DefEncAtt, empty} domain = elementdomain
{ CommonAtt, DefEncAtt, empty} codomain = elementcodomain
{ CommonAtt, DefEncAtt, empty} image = elementimage
{ CommonAtt, DefEncAtt, empty} ln = elementln
{ CommonAtt, DefEncAtt, empty} log = elementlog
{ CommonAtt, DefEncAtt, empty} moment = elementmoment
{ CommonAtt, DefEncAtt, empty} lambda.class = lambda ContExp |= lambda.class lambda = elementlambda
{ CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp} nary-functional.class = compose ContExp |= nary-functional.class compose = elementcompose
{ CommonAtt, DefEncAtt, empty} binary-arith.class = quotient | divide | minus | power | rem | root ContExp |= binary-arith.class quotient = elementquotient
{ CommonAtt, DefEncAtt, empty} divide = elementdivide
{ CommonAtt, DefEncAtt, empty} minus = elementminus
{ CommonAtt, DefEncAtt, empty} power = elementpower
{ CommonAtt, DefEncAtt, empty} rem = elementrem
{ CommonAtt, DefEncAtt, empty} root = elementroot
{ CommonAtt, DefEncAtt, empty} unary-arith.class = factorial | minus | root | abs | conjugate | arg | real | imaginary | floor | ceiling | exp ContExp |= unary-arith.class factorial = elementfactorial
{ CommonAtt, DefEncAtt, empty} abs = elementabs
{ CommonAtt, DefEncAtt, empty} conjugate = elementconjugate
{ CommonAtt, DefEncAtt, empty} arg = elementarg
{ CommonAtt, DefEncAtt, empty} real = elementreal
{ CommonAtt, DefEncAtt, empty} imaginary = elementimaginary
{ CommonAtt, DefEncAtt, empty} floor = elementfloor
{ CommonAtt, DefEncAtt, empty} ceiling = elementceiling
{ CommonAtt, DefEncAtt, empty} exp = elementexp
{ CommonAtt, DefEncAtt, empty} nary-minmax.class = max | min ContExp |= nary-minmax.class max = elementmax
{ CommonAtt, DefEncAtt, empty} min = elementmin
{ CommonAtt, DefEncAtt, empty} nary-arith.class = plus | times | gcd | lcm ContExp |= nary-arith.class plus = elementplus
{ CommonAtt, DefEncAtt, empty} times = elementtimes
{ CommonAtt, DefEncAtt, empty} gcd = elementgcd
{ CommonAtt, DefEncAtt, empty} lcm = elementlcm
{ CommonAtt, DefEncAtt, empty} nary-logical.class = and | or | xor ContExp |= nary-logical.class and = elementand
{ CommonAtt, DefEncAtt, empty} or = elementor
{ CommonAtt, DefEncAtt, empty} xor = elementxor
{ CommonAtt, DefEncAtt, empty} unary-logical.class = not ContExp |= unary-logical.class not = elementnot
{ CommonAtt, DefEncAtt, empty} binary-logical.class = implies | equivalent ContExp |= binary-logical.class implies = elementimplies
{ CommonAtt, DefEncAtt, empty} equivalent = elementequivalent
{ CommonAtt, DefEncAtt, empty} quantifier.class = forall | exists ContExp |= quantifier.class forall = elementforall
{ CommonAtt, DefEncAtt, empty} exists = elementexists
{ CommonAtt, DefEncAtt, empty} nary-reln.class = eq | gt | lt | geq | leq ContExp |= nary-reln.class eq = elementeq
{ CommonAtt, DefEncAtt, empty} gt = elementgt
{ CommonAtt, DefEncAtt, empty} lt = elementlt
{ CommonAtt, DefEncAtt, empty} geq = elementgeq
{ CommonAtt, DefEncAtt, empty} leq = elementleq
{ CommonAtt, DefEncAtt, empty} binary-reln.class = neq | approx | factorof | tendsto ContExp |= binary-reln.class neq = elementneq
{ CommonAtt, DefEncAtt, empty} approx = elementapprox
{ CommonAtt, DefEncAtt, empty} factorof = elementfactorof
{ CommonAtt, DefEncAtt, empty} tendsto = elementtendsto
{ CommonAtt, DefEncAtt, type?, empty} int.class = int ContExp |= int.class int = elementint
{ CommonAtt, DefEncAtt, empty} Differential-Operator.class = diff ContExp |= Differential-Operator.class diff = elementdiff
{ CommonAtt, DefEncAtt, empty} partialdiff.class = partialdiff ContExp |= partialdiff.class partialdiff = elementpartialdiff
{ CommonAtt, DefEncAtt, empty} unary-veccalc.class = divergence | grad | curl | laplacian ContExp |= unary-veccalc.class divergence = elementdivergence
{ CommonAtt, DefEncAtt, empty} grad = elementgrad
{ CommonAtt, DefEncAtt, empty} curl = elementcurl
{ CommonAtt, DefEncAtt, empty} laplacian = elementlaplacian
{ CommonAtt, DefEncAtt, empty} nary-setlist-constructor.class = set | \list ContExp |= nary-setlist-constructor.class set = elementset
{ CommonAtt, DefEncAtt, type?, BvarQ*, DomainQ*, ContExp*} \list = element\list
{ CommonAtt, DefEncAtt, order?, BvarQ*, DomainQ*, ContExp*} nary-set.class = union | intersect | cartesianproduct ContExp |= nary-set.class union = elementunion
{ CommonAtt, DefEncAtt, empty} intersect = elementintersect
{ CommonAtt, DefEncAtt, empty} cartesianproduct = elementcartesianproduct
{ CommonAtt, DefEncAtt, empty} binary-set.class = in | notin | notsubset | notprsubset | setdiff ContExp |= binary-set.class in = elementin
{ CommonAtt, DefEncAtt, empty} notin = elementnotin
{ CommonAtt, DefEncAtt, empty} notsubset = elementnotsubset
{ CommonAtt, DefEncAtt, empty} notprsubset = elementnotprsubset
{ CommonAtt, DefEncAtt, empty} setdiff = elementsetdiff
{ CommonAtt, DefEncAtt, empty} nary-set-reln.class = subset | prsubset ContExp |= nary-set-reln.class subset = elementsubset
{ CommonAtt, DefEncAtt, empty} prsubset = elementprsubset
{ CommonAtt, DefEncAtt, empty} unary-set.class = card ContExp |= unary-set.class card = elementcard
{ CommonAtt, DefEncAtt, empty} sum.class = sum ContExp |= sum.class sum = elementsum
{ CommonAtt, DefEncAtt, empty} product.class = product ContExp |= product.class product = elementproduct
{ CommonAtt, DefEncAtt, empty} limit.class = limit ContExp |= limit.class limit = elementlimit
{ CommonAtt, DefEncAtt, empty} unary-elementary.class = sin | cos | tan | sec | csc | cot | sinh | cosh | tanh | sech | csch | coth | arcsin | arccos | arctan | arccosh | arccot | arccoth | arccsc | arccsch | arcsec | arcsech | arcsinh | arctanh ContExp |= unary-elementary.class sin = elementsin
{ CommonAtt, DefEncAtt, empty} cos = elementcos
{ CommonAtt, DefEncAtt, empty} tan = elementtan
{ CommonAtt, DefEncAtt, empty} sec = elementsec
{ CommonAtt, DefEncAtt, empty} csc = elementcsc
{ CommonAtt, DefEncAtt, empty} cot = elementcot
{ CommonAtt, DefEncAtt, empty} sinh = elementsinh
{ CommonAtt, DefEncAtt, empty} cosh = elementcosh
{ CommonAtt, DefEncAtt, empty} tanh = elementtanh
{ CommonAtt, DefEncAtt, empty} sech = elementsech
{ CommonAtt, DefEncAtt, empty} csch = elementcsch
{ CommonAtt, DefEncAtt, empty} coth = elementcoth
{ CommonAtt, DefEncAtt, empty} arcsin = elementarcsin
{ CommonAtt, DefEncAtt, empty} arccos = elementarccos
{ CommonAtt, DefEncAtt, empty} arctan = elementarctan
{ CommonAtt, DefEncAtt, empty} arccosh = elementarccosh
{ CommonAtt, DefEncAtt, empty} arccot = elementarccot
{ CommonAtt, DefEncAtt, empty} arccoth = elementarccoth
{ CommonAtt, DefEncAtt, empty} arccsc = elementarccsc
{ CommonAtt, DefEncAtt, empty} arccsch = elementarccsch
{ CommonAtt, DefEncAtt, empty} arcsec = elementarcsec
{ CommonAtt, DefEncAtt, empty} arcsech = elementarcsech
{ CommonAtt, DefEncAtt, empty} arcsinh = elementarcsinh
{ CommonAtt, DefEncAtt, empty} arctanh = elementarctanh
{ CommonAtt, DefEncAtt, empty} nary-stats.class = mean | sdev | variance | median | mode ContExp |= nary-stats.class mean = elementmean
{ CommonAtt, DefEncAtt, empty} sdev = elementsdev
{ CommonAtt, DefEncAtt, empty} variance = elementvariance
{ CommonAtt, DefEncAtt, empty} median = elementmedian
{ CommonAtt, DefEncAtt, empty} mode = elementmode
{ CommonAtt, DefEncAtt, empty} nary-constructor.class = vector | matrix | matrixrow ContExp |= nary-constructor.class vector = elementvector
{ CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp*} matrix = elementmatrix
{ CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp*} matrixrow = elementmatrixrow
{ CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp*} unary-linalg.class = determinant | transpose ContExp |= unary-linalg.class determinant = elementdeterminant
{ CommonAtt, DefEncAtt, empty} transpose = elementtranspose
{ CommonAtt, DefEncAtt, empty} nary-linalg.class = selector ContExp |= nary-linalg.class selector = elementselector
{ CommonAtt, DefEncAtt, empty} binary-linalg.class = vectorproduct | scalarproduct | outerproduct ContExp |= binary-linalg.class vectorproduct = elementvectorproduct
{ CommonAtt, DefEncAtt, empty} scalarproduct = elementscalarproduct
{ CommonAtt, DefEncAtt, empty} outerproduct = elementouterproduct
{ CommonAtt, DefEncAtt, empty} constant-set.class = integers | reals | rationals | naturalnumbers | complexes | primes | emptyset ContExp |= constant-set.class integers = elementintegers
{ CommonAtt, DefEncAtt, empty} reals = elementreals
{ CommonAtt, DefEncAtt, empty} rationals = elementrationals
{ CommonAtt, DefEncAtt, empty} naturalnumbers = elementnaturalnumbers
{ CommonAtt, DefEncAtt, empty} complexes = elementcomplexes
{ CommonAtt, DefEncAtt, empty} primes = elementprimes
{ CommonAtt, DefEncAtt, empty} emptyset = elementemptyset
{ CommonAtt, DefEncAtt, empty} constant-arith.class = exponentiale | imaginaryi | notanumber | true | false | pi | eulergamma | infinity ContExp |= constant-arith.class exponentiale = elementexponentiale
{ CommonAtt, DefEncAtt, empty} imaginaryi = elementimaginaryi
{ CommonAtt, DefEncAtt, empty} notanumber = elementnotanumber
{ CommonAtt, DefEncAtt, empty} true = elementtrue
{ CommonAtt, DefEncAtt, empty} false = elementfalse
{ CommonAtt, DefEncAtt, empty} pi = elementpi
{ CommonAtt, DefEncAtt, empty} eulergamma = elementeulergamma
{ CommonAtt, DefEncAtt, empty} infinity = elementinfinity
{ CommonAtt, DefEncAtt, empty}
Normally, a MathML expression does not constitute an entire XML document. MathML is designed to be used as the mathematics fragment of larger markup languages. In particular it is designed to be used as a module in documents marked up with the XHTML family of markup languages. As RelaxNG directly supports modular development, this is usually very easy: an XHTML+MathML schema can be specified as simply as
# A RelaxNG Schema for XHTML+MathML include "xhtml.rnc" math = external "mathml3.rnc" Inline.class |= math Block.class |= math
assuming that we have access to a modular RelaxNG schema for XHTML that uses
Inline.class
and Block.class
to collect the the content models
for inline and block-level elements.
Customizing the MathML3 schema so that we can restrict the content of
annotation-xml
elements is similarly simple, for example:
# A RelaxNG Schema for MathML with OpenMath3 annotations omobj = external "openmath3.rnc" include "mathml3.rnc" {anotation-xml.model = omobj}
The MathML3 schema is organized so that subsetting to one of the sublanguages specified here is easy. To include strict content MathML3 in a schema just include
include "mathml3-common.rnc" include "mathml3-strict-content.rnc"
instead of include mathml3.rnc
.
For details about RelaxNG grammars and modularization see [RELAX-NG] or [RelaxNGBook].
The use of namespace prefixes creates an issue for DTD validation of documents embedding MathML. DTD validation requires knowing the literal (possibly prefixed) element names used in the document. However, the Namespaces in XML Recommendation [Namespaces] allows the prefix to be changed at arbitrary points in the document, since namespace prefixes may be declared on any element.
The MathML DTD uses the strategy outlined in [Modularization] of making every element name in the DTD be accessed by an entity reference. This means that by declaring a couple of entities to specify the prefix before the DTD is loaded, the prefix can be chosen by a document author, and compound DTDs that include several modules can, without changing the module DTDs, specify unique prefixes for each module to avoid clashes.
Note that the DTD is far more permissive than the Relax NG schema, many constraints on attribute values may not be enforced using DTD syntax. For example, many attributes expect numerical values or specific micro-syntax, but are declared as CDATA (arbitrary string) in the DTD. However, lack of enforcement of a requirement in the DTD does not imply that the requirement is not part of the MathML language itself, or that it will not be enforced by a particular MathML renderer. (See Section 2.3.2 Handling of Errors for a description of how MathML renderers should respond to MathML errors.)
Furthermore, the MathML DTD is provided for convenience; although it is intended to be fully compatible with the text of the specification, the text should be taken as definitive if there is a contradiction. (Any contradictions which may exist between various chapters of the text should be resolved by favoring Chapter 7 Characters, Entities and Fonts first, then Chapter 3 Presentation Markup, Chapter 4 Content Markup, then Section 2.1 MathML Syntax and Grammar, and then other parts of the text.)
MathML documents should be validated using the XML DTD for MathML, http://www.w3.org/Math/DTD/mathml3/mathml3.dtd.
Documents using this DTD should contain a DOCTYPE declaration of the form:
<!DOCTYPE math PUBLIC "-//W3C//DTD MathML 3.0//EN" "http://www.w3.org/Math/DTD/mathml3/mathml3.dtd">
The URI may be changed to that of a local copy of the DTD if required.
MathML fragments can be validated using the XML Schema for MathML, located at http://www.w3.org/Math/XMLSchema/mathml3/mathml3.xsd. The provided schema has been mechanically generated from the Relax NG schema, it omits some constraints that can not be enforced using XSD syntax.
Similarly to the DOCTYPE declaration used in documents, it is possible to link a MathML fragment to the XML Schema, as shown below.
<mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/1998/Math/MathML http://www.w3.org/Math/XMLSchema/mathml3/mathml3.xsd"> ... </mml:math>
The xsi:schemaLocation
attribute belongs to the XML Schema
instance namespace, defined in [XMLSchemas]. The value
of the attribute is a pair of URIs: the first is the MathML namespace
URI and the second is the location of the schema for that
namespace. The second URI may be changed to that of a local copy if
required.
As the XML Schema specification indicates, the use of the
schemaLocation
attribute is only a hint for schema
processors: validation by a MathML-aware processor can be performed
without requiring that the schemaLocation
attribute be
declared in the instance. Moreover, a processor can even ignore or
override the specified schema URI, if it is directed to.