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.
# This is the Mathematical Markup Language (MathML) 3.0, an XML # application for describing mathematical notation and capturing # both its structure and content. # # 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" ## 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"
# This is the Mathematical Markup Language (MathML) 3.0, an XML # application for describing mathematical notation and capturing # both its structure and content. # # 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" 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*' }
# This is the Mathematical Markup Language (MathML) 3.0, an XML # application for describing mathematical notation and capturing # both its structure and content. # # 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.
# This is the Mathematical Markup Language (MathML) 3.0, an XML # application for describing mathematical notation and capturing # both its structure and content. # # 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" 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.
# This is the Mathematical Markup Language (MathML) 3.0, an XML
# application for describing mathematical notation and capturing
# both its structure and content.
#
# 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, attribute type {text}?, base?
ci.attributes = CommonAtt, DefEncAtt, ci.type?
ci.type = attribute type {text}
ci.content = (text | mglyph | PresentationExpression)*
csymbol.attributes = CommonAtt, DefEncAtt, attribute type {text}?,cd?
csymbol.content = (text | mglyph | PresentationExpression)*
bvar = element bvar { (ci | semantics-ci) & degree?}
cbytes.attributes = CommonAtt, DefEncAtt
cs.attributes = CommonAtt, DefEncAtt
apply.content = ContExp+ | (ContExp, BvarQ, Qualifier*, ContExp*)
bind.content = apply.content
}
base = attribute base {text}
sep = element sep {empty}
PresentationExpression |= notAllowed
DomainQ = (domainofapplication|condition|interval|(lowlimit,uplimit?))*
domainofapplication = element domainofapplication {ContExp}
condition = element condition {ContExp}
uplimit = element uplimit {ContExp}
lowlimit = element lowlimit {ContExp}
Qualifier = DomainQ|degree|momentabout|logbase
degree = element degree {ContExp}
momentabout = element momentabout {ContExp}
logbase = element logbase {ContExp}
type = attribute type {text}
order = attribute order {"numeric" | "lexicographic"}
closure = attribute closure {text}
ContExp |= piecewise
piecewise = element piecewise {CommonAtt, DefEncAtt,(piece* & otherwise?)}
piece = element piece {CommonAtt, DefEncAtt, ContExp, ContExp}
otherwise = element otherwise {CommonAtt, DefEncAtt, ContExp}
DeprecatedContExp = reln | fn | declare
ContExp |= DeprecatedContExp
reln = element reln {ContExp*}
fn = element fn {ContExp}
declare = element declare {attribute type {xsd:string}?,
attribute scope {xsd:string}?,
attribute nargs {xsd:nonNegativeInteger}?,
attribute occurrence {"prefix"|"infix"|"function-model"}?,
DefEncAtt,
ContExp+}
interval.class = interval
ContExp |= interval.class
interval = element interval { CommonAtt, DefEncAtt,closure?, ContExp,ContExp}
unary-functional.class = inverse | ident | domain | codomain | image | ln | log | moment
ContExp |= unary-functional.class
inverse = element inverse { CommonAtt, DefEncAtt, empty}
ident = element ident { CommonAtt, DefEncAtt, empty}
domain = element domain { CommonAtt, DefEncAtt, empty}
codomain = element codomain { CommonAtt, DefEncAtt, empty}
image = element image { CommonAtt, DefEncAtt, empty}
ln = element ln { CommonAtt, DefEncAtt, empty}
log = element log { CommonAtt, DefEncAtt, empty}
moment = element moment { CommonAtt, DefEncAtt, empty}
lambda.class = lambda
ContExp |= lambda.class
lambda = element lambda { CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp}
nary-functional.class = compose
ContExp |= nary-functional.class
compose = element compose { CommonAtt, DefEncAtt, empty}
binary-arith.class = quotient | divide | minus | power | rem | root
ContExp |= binary-arith.class
quotient = element quotient { CommonAtt, DefEncAtt, empty}
divide = element divide { CommonAtt, DefEncAtt, empty}
minus = element minus { CommonAtt, DefEncAtt, empty}
power = element power { CommonAtt, DefEncAtt, empty}
rem = element rem { CommonAtt, DefEncAtt, empty}
root = element root { CommonAtt, DefEncAtt, empty}
unary-arith.class = factorial | minus | root | abs | conjugate | arg | real | imaginary | floor | ceiling | exp
ContExp |= unary-arith.class
factorial = element factorial { CommonAtt, DefEncAtt, empty}
abs = element abs { CommonAtt, DefEncAtt, empty}
conjugate = element conjugate { CommonAtt, DefEncAtt, empty}
arg = element arg { CommonAtt, DefEncAtt, empty}
real = element real { CommonAtt, DefEncAtt, empty}
imaginary = element imaginary { CommonAtt, DefEncAtt, empty}
floor = element floor { CommonAtt, DefEncAtt, empty}
ceiling = element ceiling { CommonAtt, DefEncAtt, empty}
exp = element exp { CommonAtt, DefEncAtt, empty}
nary-minmax.class = max | min
ContExp |= nary-minmax.class
max = element max { CommonAtt, DefEncAtt, empty}
min = element min { CommonAtt, DefEncAtt, empty}
nary-arith.class = plus | times | gcd | lcm
ContExp |= nary-arith.class
plus = element plus { CommonAtt, DefEncAtt, empty}
times = element times { CommonAtt, DefEncAtt, empty}
gcd = element gcd { CommonAtt, DefEncAtt, empty}
lcm = element lcm { CommonAtt, DefEncAtt, empty}
nary-logical.class = and | or | xor
ContExp |= nary-logical.class
and = element and { CommonAtt, DefEncAtt, empty}
or = element or { CommonAtt, DefEncAtt, empty}
xor = element xor { CommonAtt, DefEncAtt, empty}
unary-logical.class = not
ContExp |= unary-logical.class
not = element not { CommonAtt, DefEncAtt, empty}
binary-logical.class = implies | equivalent
ContExp |= binary-logical.class
implies = element implies { CommonAtt, DefEncAtt, empty}
equivalent = element equivalent { CommonAtt, DefEncAtt, empty}
quantifier.class = forall | exists
ContExp |= quantifier.class
forall = element forall { CommonAtt, DefEncAtt, empty}
exists = element exists { CommonAtt, DefEncAtt, empty}
nary-reln.class = eq | gt | lt | geq | leq
ContExp |= nary-reln.class
eq = element eq { CommonAtt, DefEncAtt, empty}
gt = element gt { CommonAtt, DefEncAtt, empty}
lt = element lt { CommonAtt, DefEncAtt, empty}
geq = element geq { CommonAtt, DefEncAtt, empty}
leq = element leq { CommonAtt, DefEncAtt, empty}
binary-reln.class = neq | approx | factorof | tendsto
ContExp |= binary-reln.class
neq = element neq { CommonAtt, DefEncAtt, empty}
approx = element approx { CommonAtt, DefEncAtt, empty}
factorof = element factorof { CommonAtt, DefEncAtt, empty}
tendsto = element tendsto { CommonAtt, DefEncAtt, type?, empty}
int.class = int
ContExp |= int.class
int = element int { CommonAtt, DefEncAtt, empty}
Differential-Operator.class = diff
ContExp |= Differential-Operator.class
diff = element diff { CommonAtt, DefEncAtt, empty}
partialdiff.class = partialdiff
ContExp |= partialdiff.class
partialdiff = element partialdiff { CommonAtt, DefEncAtt, empty}
unary-veccalc.class = divergence | grad | curl | laplacian
ContExp |= unary-veccalc.class
divergence = element divergence { CommonAtt, DefEncAtt, empty}
grad = element grad { CommonAtt, DefEncAtt, empty}
curl = element curl { CommonAtt, DefEncAtt, empty}
laplacian = element laplacian { CommonAtt, DefEncAtt, empty}
nary-setlist-constructor.class = set | \list
ContExp |= nary-setlist-constructor.class
set = element set { 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 = element union { CommonAtt, DefEncAtt, empty}
intersect = element intersect { CommonAtt, DefEncAtt, empty}
cartesianproduct = element cartesianproduct { CommonAtt, DefEncAtt, empty}
binary-set.class = in | notin | notsubset | notprsubset | setdiff
ContExp |= binary-set.class
in = element in { CommonAtt, DefEncAtt, empty}
notin = element notin { CommonAtt, DefEncAtt, empty}
notsubset = element notsubset { CommonAtt, DefEncAtt, empty}
notprsubset = element notprsubset { CommonAtt, DefEncAtt, empty}
setdiff = element setdiff { CommonAtt, DefEncAtt, empty}
nary-set-reln.class = subset | prsubset
ContExp |= nary-set-reln.class
subset = element subset { CommonAtt, DefEncAtt, empty}
prsubset = element prsubset { CommonAtt, DefEncAtt, empty}
unary-set.class = card
ContExp |= unary-set.class
card = element card { CommonAtt, DefEncAtt, empty}
sum.class = sum
ContExp |= sum.class
sum = element sum { CommonAtt, DefEncAtt, empty}
product.class = product
ContExp |= product.class
product = element product { CommonAtt, DefEncAtt, empty}
limit.class = limit
ContExp |= limit.class
limit = element limit { 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 = element sin { CommonAtt, DefEncAtt, empty}
cos = element cos { CommonAtt, DefEncAtt, empty}
tan = element tan { CommonAtt, DefEncAtt, empty}
sec = element sec { CommonAtt, DefEncAtt, empty}
csc = element csc { CommonAtt, DefEncAtt, empty}
cot = element cot { CommonAtt, DefEncAtt, empty}
sinh = element sinh { CommonAtt, DefEncAtt, empty}
cosh = element cosh { CommonAtt, DefEncAtt, empty}
tanh = element tanh { CommonAtt, DefEncAtt, empty}
sech = element sech { CommonAtt, DefEncAtt, empty}
csch = element csch { CommonAtt, DefEncAtt, empty}
coth = element coth { CommonAtt, DefEncAtt, empty}
arcsin = element arcsin { CommonAtt, DefEncAtt, empty}
arccos = element arccos { CommonAtt, DefEncAtt, empty}
arctan = element arctan { CommonAtt, DefEncAtt, empty}
arccosh = element arccosh { CommonAtt, DefEncAtt, empty}
arccot = element arccot { CommonAtt, DefEncAtt, empty}
arccoth = element arccoth { CommonAtt, DefEncAtt, empty}
arccsc = element arccsc { CommonAtt, DefEncAtt, empty}
arccsch = element arccsch { CommonAtt, DefEncAtt, empty}
arcsec = element arcsec { CommonAtt, DefEncAtt, empty}
arcsech = element arcsech { CommonAtt, DefEncAtt, empty}
arcsinh = element arcsinh { CommonAtt, DefEncAtt, empty}
arctanh = element arctanh { CommonAtt, DefEncAtt, empty}
nary-stats.class = mean | sdev | variance | median | mode
ContExp |= nary-stats.class
mean = element mean { CommonAtt, DefEncAtt, empty}
sdev = element sdev { CommonAtt, DefEncAtt, empty}
variance = element variance { CommonAtt, DefEncAtt, empty}
median = element median { CommonAtt, DefEncAtt, empty}
mode = element mode { CommonAtt, DefEncAtt, empty}
nary-constructor.class = vector | matrix | matrixrow
ContExp |= nary-constructor.class
vector = element vector { CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp*}
matrix = element matrix { CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp*}
matrixrow = element matrixrow { CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp*}
unary-linalg.class = determinant | transpose
ContExp |= unary-linalg.class
determinant = element determinant { CommonAtt, DefEncAtt, empty}
transpose = element transpose { CommonAtt, DefEncAtt, empty}
nary-linalg.class = selector
ContExp |= nary-linalg.class
selector = element selector { CommonAtt, DefEncAtt, empty}
binary-linalg.class = vectorproduct | scalarproduct | outerproduct
ContExp |= binary-linalg.class
vectorproduct = element vectorproduct { CommonAtt, DefEncAtt, empty}
scalarproduct = element scalarproduct { CommonAtt, DefEncAtt, empty}
outerproduct = element outerproduct { CommonAtt, DefEncAtt, empty}
constant-set.class = integers | reals | rationals | naturalnumbers | complexes | primes | emptyset
ContExp |= constant-set.class
integers = element integers { CommonAtt, DefEncAtt, empty}
reals = element reals { CommonAtt, DefEncAtt, empty}
rationals = element rationals { CommonAtt, DefEncAtt, empty}
naturalnumbers = element naturalnumbers { CommonAtt, DefEncAtt, empty}
complexes = element complexes { CommonAtt, DefEncAtt, empty}
primes = element primes { CommonAtt, DefEncAtt, empty}
emptyset = element emptyset { CommonAtt, DefEncAtt, empty}
constant-arith.class = exponentiale | imaginaryi | notanumber | true | false | pi | eulergamma | infinity
ContExp |= constant-arith.class
exponentiale = element exponentiale { CommonAtt, DefEncAtt, empty}
imaginaryi = element imaginaryi { CommonAtt, DefEncAtt, empty}
notanumber = element notanumber { CommonAtt, DefEncAtt, empty}
true = element true { CommonAtt, DefEncAtt, empty}
false = element false { CommonAtt, DefEncAtt, empty}
pi = element pi { CommonAtt, DefEncAtt, empty}
eulergamma = element eulergamma { CommonAtt, DefEncAtt, empty}
infinity = element infinity { 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.