"""
A MathML printer.
"""
from __future__ import print_function, division
from sympy import sympify, S, Mul
from sympy.core.function import _coeff_isneg
from sympy.core.alphabets import greeks
from sympy.core.compatibility import range
from .printer import Printer
from .pretty.pretty_symbology import greek_unicode
from .conventions import split_super_sub, requires_partial
[docs]class MathMLPrinterBase(Printer):
"""Contains common code required for MathMLContentPrinter and
MathMLPresentationPrinter.
"""
_default_settings = {
"order": None,
"encoding": "utf-8"
}
def __init__(self, settings=None):
Printer.__init__(self, settings)
from xml.dom.minidom import Document,Text
self.dom = Document()
# Workaround to allow strings to remain unescaped
# Based on https://stackoverflow.com/questions/38015864/python-xml-dom-minidom-please-dont-escape-my-strings/38041194
class RawText(Text):
def writexml(self, writer, indent='', addindent='', newl=''):
if self.data:
writer.write(u'{}{}{}'.format(indent, self.data, newl))
def createRawTextNode(data):
r = RawText()
r.data = data
r.ownerDocument = self.dom
return r
self.dom.createTextNode = createRawTextNode
def doprint(self, expr):
"""
Prints the expression as MathML.
"""
mathML = Printer._print(self, expr)
unistr = mathML.toxml()
xmlbstr = unistr.encode('ascii', 'xmlcharrefreplace')
res = xmlbstr.decode()
return res
def apply_patch(self):
# Applying the patch of xml.dom.minidom bug
# Date: 2011-11-18
# Description: http://ronrothman.com/public/leftbraned/xml-dom-minidom-\
# toprettyxml-and-silly-whitespace/#best-solution
# Issue: http://bugs.python.org/issue4147
# Patch: http://hg.python.org/cpython/rev/7262f8f276ff/
from xml.dom.minidom import Element, Text, Node, _write_data
def writexml(self, writer, indent="", addindent="", newl=""):
# indent = current indentation
# addindent = indentation to add to higher levels
# newl = newline string
writer.write(indent + "<" + self.tagName)
attrs = self._get_attributes()
a_names = list(attrs.keys())
a_names.sort()
for a_name in a_names:
writer.write(" %s=\"" % a_name)
_write_data(writer, attrs[a_name].value)
writer.write("\"")
if self.childNodes:
writer.write(">")
if (len(self.childNodes) == 1 and
self.childNodes[0].nodeType == Node.TEXT_NODE):
self.childNodes[0].writexml(writer, '', '', '')
else:
writer.write(newl)
for node in self.childNodes:
node.writexml(
writer, indent + addindent, addindent, newl)
writer.write(indent)
writer.write("</%s>%s" % (self.tagName, newl))
else:
writer.write("/>%s" % (newl))
self._Element_writexml_old = Element.writexml
Element.writexml = writexml
def writexml(self, writer, indent="", addindent="", newl=""):
_write_data(writer, "%s%s%s" % (indent, self.data, newl))
self._Text_writexml_old = Text.writexml
Text.writexml = writexml
def restore_patch(self):
from xml.dom.minidom import Element, Text
Element.writexml = self._Element_writexml_old
Text.writexml = self._Text_writexml_old
[docs]class MathMLContentPrinter(MathMLPrinterBase):
"""Prints an expression to the Content MathML markup language.
References: https://www.w3.org/TR/MathML2/chapter4.html
"""
printmethod = "_mathml_content"
[docs] def mathml_tag(self, e):
"""Returns the MathML tag for an expression."""
translate = {
'Add': 'plus',
'Mul': 'times',
'Derivative': 'diff',
'Number': 'cn',
'int': 'cn',
'Pow': 'power',
'Symbol': 'ci',
'Integral': 'int',
'Sum': 'sum',
'sin': 'sin',
'cos': 'cos',
'tan': 'tan',
'cot': 'cot',
'asin': 'arcsin',
'asinh': 'arcsinh',
'acos': 'arccos',
'acosh': 'arccosh',
'atan': 'arctan',
'atanh': 'arctanh',
'acot': 'arccot',
'atan2': 'arctan',
'log': 'ln',
'Equality': 'eq',
'Unequality': 'neq',
'GreaterThan': 'geq',
'LessThan': 'leq',
'StrictGreaterThan': 'gt',
'StrictLessThan': 'lt',
}
for cls in e.__class__.__mro__:
n = cls.__name__
if n in translate:
return translate[n]
# Not found in the MRO set
n = e.__class__.__name__
return n.lower()
def _print_Mul(self, expr):
if _coeff_isneg(expr):
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement('minus'))
x.appendChild(self._print_Mul(-expr))
return x
from sympy.simplify import fraction
numer, denom = fraction(expr)
if denom is not S.One:
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement('divide'))
x.appendChild(self._print(numer))
x.appendChild(self._print(denom))
return x
coeff, terms = expr.as_coeff_mul()
if coeff is S.One and len(terms) == 1:
# XXX since the negative coefficient has been handled, I don't
# think a coeff of 1 can remain
return self._print(terms[0])
if self.order != 'old':
terms = Mul._from_args(terms).as_ordered_factors()
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement('times'))
if(coeff != 1):
x.appendChild(self._print(coeff))
for term in terms:
x.appendChild(self._print(term))
return x
def _print_Add(self, expr, order=None):
args = self._as_ordered_terms(expr, order=order)
lastProcessed = self._print(args[0])
plusNodes = []
for arg in args[1:]:
if _coeff_isneg(arg):
# use minus
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement('minus'))
x.appendChild(lastProcessed)
x.appendChild(self._print(-arg))
# invert expression since this is now minused
lastProcessed = x
if(arg == args[-1]):
plusNodes.append(lastProcessed)
else:
plusNodes.append(lastProcessed)
lastProcessed = self._print(arg)
if(arg == args[-1]):
plusNodes.append(self._print(arg))
if len(plusNodes) == 1:
return lastProcessed
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement('plus'))
while len(plusNodes) > 0:
x.appendChild(plusNodes.pop(0))
return x
def _print_MatrixBase(self, m):
x = self.dom.createElement('matrix')
for i in range(m.rows):
x_r = self.dom.createElement('matrixrow')
for j in range(m.cols):
x_r.appendChild(self._print(m[i, j]))
x.appendChild(x_r)
return x
def _print_Rational(self, e):
if e.q == 1:
# don't divide
x = self.dom.createElement('cn')
x.appendChild(self.dom.createTextNode(str(e.p)))
return x
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement('divide'))
# numerator
xnum = self.dom.createElement('cn')
xnum.appendChild(self.dom.createTextNode(str(e.p)))
# denominator
xdenom = self.dom.createElement('cn')
xdenom.appendChild(self.dom.createTextNode(str(e.q)))
x.appendChild(xnum)
x.appendChild(xdenom)
return x
def _print_Limit(self, e):
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement(self.mathml_tag(e)))
x_1 = self.dom.createElement('bvar')
x_2 = self.dom.createElement('lowlimit')
x_1.appendChild(self._print(e.args[1]))
x_2.appendChild(self._print(e.args[2]))
x.appendChild(x_1)
x.appendChild(x_2)
x.appendChild(self._print(e.args[0]))
return x
def _print_ImaginaryUnit(self, e):
return self.dom.createElement('imaginaryi')
def _print_EulerGamma(self, e):
return self.dom.createElement('eulergamma')
def _print_GoldenRatio(self, e):
"""We use unicode #x3c6 for Greek letter phi as defined here
http://www.w3.org/2003/entities/2007doc/isogrk1.html"""
x = self.dom.createElement('cn')
x.appendChild(self.dom.createTextNode(u"\N{GREEK SMALL LETTER PHI}"))
return x
def _print_Exp1(self, e):
return self.dom.createElement('exponentiale')
def _print_Pi(self, e):
return self.dom.createElement('pi')
def _print_Infinity(self, e):
return self.dom.createElement('infinity')
def _print_Negative_Infinity(self, e):
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement('minus'))
x.appendChild(self.dom.createElement('infinity'))
return x
def _print_Integral(self, e):
def lime_recur(limits):
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement(self.mathml_tag(e)))
bvar_elem = self.dom.createElement('bvar')
bvar_elem.appendChild(self._print(limits[0][0]))
x.appendChild(bvar_elem)
if len(limits[0]) == 3:
low_elem = self.dom.createElement('lowlimit')
low_elem.appendChild(self._print(limits[0][1]))
x.appendChild(low_elem)
up_elem = self.dom.createElement('uplimit')
up_elem.appendChild(self._print(limits[0][2]))
x.appendChild(up_elem)
if len(limits[0]) == 2:
up_elem = self.dom.createElement('uplimit')
up_elem.appendChild(self._print(limits[0][1]))
x.appendChild(up_elem)
if len(limits) == 1:
x.appendChild(self._print(e.function))
else:
x.appendChild(lime_recur(limits[1:]))
return x
limits = list(e.limits)
limits.reverse()
return lime_recur(limits)
def _print_Sum(self, e):
# Printer can be shared because Sum and Integral have the
# same internal representation.
return self._print_Integral(e)
def _print_Symbol(self, sym):
ci = self.dom.createElement(self.mathml_tag(sym))
def join(items):
if len(items) > 1:
mrow = self.dom.createElement('mml:mrow')
for i, item in enumerate(items):
if i > 0:
mo = self.dom.createElement('mml:mo')
mo.appendChild(self.dom.createTextNode(" "))
mrow.appendChild(mo)
mi = self.dom.createElement('mml:mi')
mi.appendChild(self.dom.createTextNode(item))
mrow.appendChild(mi)
return mrow
else:
mi = self.dom.createElement('mml:mi')
mi.appendChild(self.dom.createTextNode(items[0]))
return mi
# translate name, supers and subs to unicode characters
greek_letters = set(greeks) # make a copy
def translate(s):
if s in greek_unicode:
return greek_unicode.get(s)
else:
return s
name, supers, subs = split_super_sub(sym.name)
name = translate(name)
supers = [translate(sup) for sup in supers]
subs = [translate(sub) for sub in subs]
mname = self.dom.createElement('mml:mi')
mname.appendChild(self.dom.createTextNode(name))
if len(supers) == 0:
if len(subs) == 0:
ci.appendChild(self.dom.createTextNode(name))
else:
msub = self.dom.createElement('mml:msub')
msub.appendChild(mname)
msub.appendChild(join(subs))
ci.appendChild(msub)
else:
if len(subs) == 0:
msup = self.dom.createElement('mml:msup')
msup.appendChild(mname)
msup.appendChild(join(supers))
ci.appendChild(msup)
else:
msubsup = self.dom.createElement('mml:msubsup')
msubsup.appendChild(mname)
msubsup.appendChild(join(subs))
msubsup.appendChild(join(supers))
ci.appendChild(msubsup)
return ci
def _print_Pow(self, e):
# Here we use root instead of power if the exponent is the reciprocal of an integer
if e.exp.is_Rational and e.exp.p == 1:
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement('root'))
if e.exp.q != 2:
xmldeg = self.dom.createElement('degree')
xmlci = self.dom.createElement('ci')
xmlci.appendChild(self.dom.createTextNode(str(e.exp.q)))
xmldeg.appendChild(xmlci)
x.appendChild(xmldeg)
x.appendChild(self._print(e.base))
return x
x = self.dom.createElement('apply')
x_1 = self.dom.createElement(self.mathml_tag(e))
x.appendChild(x_1)
x.appendChild(self._print(e.base))
x.appendChild(self._print(e.exp))
return x
def _print_Number(self, e):
x = self.dom.createElement(self.mathml_tag(e))
x.appendChild(self.dom.createTextNode(str(e)))
return x
def _print_Derivative(self, e):
x = self.dom.createElement('apply')
diff_symbol = self.mathml_tag(e)
if requires_partial(e):
diff_symbol = 'partialdiff'
x.appendChild(self.dom.createElement(diff_symbol))
x_1 = self.dom.createElement('bvar')
for sym in e.variables:
x_1.appendChild(self._print(sym))
x.appendChild(x_1)
x.appendChild(self._print(e.expr))
return x
def _print_Function(self, e):
x = self.dom.createElement("apply")
x.appendChild(self.dom.createElement(self.mathml_tag(e)))
for arg in e.args:
x.appendChild(self._print(arg))
return x
def _print_Basic(self, e):
x = self.dom.createElement(self.mathml_tag(e))
for arg in e:
x.appendChild(self._print(arg))
return x
def _print_AssocOp(self, e):
x = self.dom.createElement('apply')
x_1 = self.dom.createElement(self.mathml_tag(e))
x.appendChild(x_1)
for arg in e.args:
x.appendChild(self._print(arg))
return x
def _print_Relational(self, e):
x = self.dom.createElement('apply')
x.appendChild(self.dom.createElement(self.mathml_tag(e)))
x.appendChild(self._print(e.lhs))
x.appendChild(self._print(e.rhs))
return x
def _print_list(self, seq):
"""MathML reference for the <list> element:
http://www.w3.org/TR/MathML2/chapter4.html#contm.list"""
dom_element = self.dom.createElement('list')
for item in seq:
dom_element.appendChild(self._print(item))
return dom_element
def _print_int(self, p):
dom_element = self.dom.createElement(self.mathml_tag(p))
dom_element.appendChild(self.dom.createTextNode(str(p)))
return dom_element
[docs]class MathMLPresentationPrinter(MathMLPrinterBase):
"""Prints an expression to the Presentation MathML markup language.
References: https://www.w3.org/TR/MathML2/chapter3.html
"""
printmethod = "_mathml_presentation"
[docs] def mathml_tag(self, e):
"""Returns the MathML tag for an expression."""
translate = {
'Mul': '⁢',
'Number': 'mn',
'Limit' : '→',
'Derivative': 'ⅆ',
'int': 'mn',
'Symbol': 'mi',
'Integral': '∫',
'Sum': '∑',
'sin': 'sin',
'cos': 'cos',
'tan': 'tan',
'cot': 'cot',
'asin': 'arcsin',
'asinh': 'arcsinh',
'acos': 'arccos',
'acosh': 'arccosh',
'atan': 'arctan',
'atanh': 'arctanh',
'acot': 'arccot',
'atan2': 'arctan',
'Equality': '=',
'Unequality': '≠',
'GreaterThan': '≥',
'LessThan': '≤',
'StrictGreaterThan': '>',
'StrictLessThan': '<',
}
for cls in e.__class__.__mro__:
n = cls.__name__
if n in translate:
return translate[n]
# Not found in the MRO set
n = e.__class__.__name__
return n.lower()
def _print_Mul(self, expr):
def multiply(expr, mrow):
from sympy.simplify import fraction
numer, denom = fraction(expr)
if denom is not S.One:
frac = self.dom.createElement('mfrac')
xnum = self._print(numer)
xden = self._print(denom)
frac.appendChild(xnum)
frac.appendChild(xden)
return frac
coeff, terms = expr.as_coeff_mul()
if coeff is S.One and len(terms) == 1:
return self._print(terms[0])
if self.order != 'old':
terms = Mul._from_args(terms).as_ordered_factors()
if(coeff != 1):
x = self._print(coeff)
y = self.dom.createElement('mo')
y.appendChild(self.dom.createTextNode(self.mathml_tag(expr)))
mrow.appendChild(x)
mrow.appendChild(y)
for term in terms:
x = self._print(term)
mrow.appendChild(x)
if not term == terms[-1]:
y = self.dom.createElement('mo')
y.appendChild(self.dom.createTextNode(self.mathml_tag(expr)))
mrow.appendChild(y)
return mrow
mrow = self.dom.createElement('mrow')
if _coeff_isneg(expr):
x = self.dom.createElement('mo')
x.appendChild(self.dom.createTextNode('-'))
mrow.appendChild(x)
mrow = multiply(-expr, mrow)
else:
mrow = multiply(expr, mrow)
return mrow
def _print_Add(self, expr, order=None):
mrow = self.dom.createElement('mrow')
args = self._as_ordered_terms(expr, order=order)
mrow.appendChild(self._print(args[0]))
for arg in args[1:]:
if _coeff_isneg(arg):
# use minus
x = self.dom.createElement('mo')
x.appendChild(self.dom.createTextNode('-'))
y = self._print(-arg)
# invert expression since this is now minused
else:
x = self.dom.createElement('mo')
x.appendChild(self.dom.createTextNode('+'))
y = self._print(arg)
mrow.appendChild(x)
mrow.appendChild(y)
return mrow
def _print_MatrixBase(self, m):
brac = self.dom.createElement('mfenced')
table = self.dom.createElement('mtable')
for i in range(m.rows):
x = self.dom.createElement('mtr')
for j in range(m.cols):
y = self.dom.createElement('mtd')
y.appendChild(self._print(m[i, j]))
x.appendChild(y)
table.appendChild(x)
brac.appendChild(table)
return brac
def _print_Rational(self, e):
if e.q == 1:
# don't divide
x = self.dom.createElement('mn')
x.appendChild(self.dom.createTextNode(str(e.p)))
return x
x = self.dom.createElement('mfrac')
num = self.dom.createElement('mn')
num.appendChild(self.dom.createTextNode(str(e.p)))
x.appendChild(num)
den = self.dom.createElement('mn')
den.appendChild(self.dom.createTextNode(str(e.q)))
x.appendChild(den)
return x
def _print_Limit(self, e):
mrow = self.dom.createElement('mrow')
munder = self.dom.createElement('munder')
mi = self.dom.createElement('mi')
mi.appendChild(self.dom.createTextNode('lim'))
x = self.dom.createElement('mrow')
x_1 = self._print(e.args[1])
arrow = self.dom.createElement('mo')
arrow.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
x_2 = self._print(e.args[2])
x.appendChild(x_1)
x.appendChild(arrow)
x.appendChild(x_2)
munder.appendChild(mi)
munder.appendChild(x)
mrow.appendChild(munder)
mrow.appendChild(self._print(e.args[0]))
return mrow
def _print_ImaginaryUnit(self, e):
x = self.dom.createElement('mi')
x.appendChild(self.dom.createTextNode('ⅈ'))
return x
def _print_GoldenRatio(self, e):
"""We use unicode #x3c6 for Greek letter phi as defined here
http://www.w3.org/2003/entities/2007doc/isogrk1.html"""
x = self.dom.createElement('mi')
x.appendChild(self.dom.createTextNode(u"\N{GREEK SMALL LETTER PHI}"))
return x
def _print_Exp1(self, e):
x = self.dom.createElement('mi')
x.appendChild(self.dom.createTextNode('ⅇ'))
return x
def _print_Pi(self, e):
x = self.dom.createElement('mi')
x.appendChild(self.dom.createTextNode('π'))
return x
def _print_Infinity(self, e):
x = self.dom.createElement('mi')
x.appendChild(self.dom.createTextNode('∞'))
return x
def _print_Negative_Infinity(self, e):
mrow = self.dom.createElement('mrow')
y = self.dom.createElement('mo')
y.appendChild(self.dom.createTextNode('-'))
x = self._print_Infinity(-e)
mrow.appendChild(y)
mrow.appendChild(x)
return mrow
def _print_Integral(self, e):
limits = list(e.limits)
if len(limits[0]) == 3:
subsup = self.dom.createElement('msubsup')
low_elem = self._print(limits[0][1])
up_elem = self._print(limits[0][2])
integral = self.dom.createElement('mo')
integral.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
subsup.appendChild(integral)
subsup.appendChild(low_elem)
subsup.appendChild(up_elem)
if len(limits[0]) == 1:
subsup = self.dom.createElement('mrow')
integral = self.dom.createElement('mo')
integral.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
subsup.appendChild(integral)
mrow = self.dom.createElement('mrow')
diff = self.dom.createElement('mo')
diff.appendChild(self.dom.createTextNode('ⅆ'))
if len(str(limits[0][0])) > 1:
var = self.dom.createElement('mfenced')
var.appendChild(self._print(limits[0][0]))
else:
var = self._print(limits[0][0])
mrow.appendChild(subsup)
if len(str(e.function)) == 1:
mrow.appendChild(self._print(e.function))
else:
fence = self.dom.createElement('mfenced')
fence.appendChild(self._print(e.function))
mrow.appendChild(fence)
mrow.appendChild(diff)
mrow.appendChild(var)
return mrow
def _print_Sum(self, e):
limits = list(e.limits)
subsup = self.dom.createElement('munderover')
low_elem = self._print(limits[0][1])
up_elem = self._print(limits[0][2])
summand = self.dom.createElement('mo')
summand.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
low = self.dom.createElement('mrow')
var = self._print(limits[0][0])
equal = self.dom.createElement('mo')
equal.appendChild(self.dom.createTextNode('='))
low.appendChild(var)
low.appendChild(equal)
low.appendChild(low_elem)
subsup.appendChild(summand)
subsup.appendChild(low)
subsup.appendChild(up_elem)
mrow = self.dom.createElement('mrow')
mrow.appendChild(subsup)
if len(str(e.function)) == 1:
mrow.appendChild(self._print(e.function))
else:
fence = self.dom.createElement('mfenced')
fence.appendChild(self._print(e.function))
mrow.appendChild(fence)
return mrow
def _print_Symbol(self, sym):
x = self.dom.createElement('mi')
def join(items):
if len(items) > 1:
mrow = self.dom.createElement('mrow')
for i, item in enumerate(items):
if i > 0:
mo = self.dom.createElement('mo')
mo.appendChild(self.dom.createTextNode(" "))
mrow.appendChild(mo)
mi = self.dom.createElement('mi')
mi.appendChild(self.dom.createTextNode(item))
mrow.appendChild(mi)
return mrow
else:
mi = self.dom.createElement('mi')
mi.appendChild(self.dom.createTextNode(items[0]))
return mi
# translate name, supers and subs to unicode characters
greek_letters = set(greeks) # make a copy
def translate(s):
if s in greek_unicode:
return greek_unicode.get(s)
else:
return s
name, supers, subs = split_super_sub(sym.name)
name = translate(name)
supers = [translate(sup) for sup in supers]
subs = [translate(sub) for sub in subs]
mname = self.dom.createElement('mi')
mname.appendChild(self.dom.createTextNode(name))
if len(supers) == 0:
if len(subs) == 0:
x.appendChild(self.dom.createTextNode(name))
else:
msub = self.dom.createElement('msub')
msub.appendChild(mname)
msub.appendChild(join(subs))
x.appendChild(msub)
else:
if len(subs) == 0:
msup = self.dom.createElement('msup')
msup.appendChild(mname)
msup.appendChild(join(supers))
x.appendChild(msup)
else:
msubsup = self.dom.createElement('msubsup')
msubsup.appendChild(mname)
msubsup.appendChild(join(subs))
msubsup.appendChild(join(supers))
x.appendChild(msubsup)
return x
def _print_Pow(self, e):
# Here we use root instead of power if the exponent is the reciprocal of an integer
if e.exp.is_negative or len(str(e.base)) > 1:
mrow = self.dom.createElement('mrow')
x = self.dom.createElement('mfenced')
x.appendChild(self._print(e.base))
mrow.appendChild(x)
x = self.dom.createElement('msup')
x.appendChild(mrow)
x.appendChild(self._print(e.exp))
return x
if e.exp.is_Rational and e.exp.p == 1:
if e.exp.q == 2:
x = self.dom.createElement('msqrt')
x.appendChild(self._print(e.base))
if e.exp.q != 2:
x = self.dom.createElement('mroot')
x.appendChild(self._print(e.base))
x.appendChild(self._print(e.exp.q))
return x
x = self.dom.createElement('msup')
x.appendChild(self._print(e.base))
x.appendChild(self._print(e.exp))
return x
def _print_Number(self, e):
x = self.dom.createElement(self.mathml_tag(e))
x.appendChild(self.dom.createTextNode(str(e)))
return x
def _print_Derivative(self, e):
mrow = self.dom.createElement('mrow')
x = self.dom.createElement('mo')
if requires_partial(e):
x.appendChild(self.dom.createTextNode('∂'))
y = self.dom.createElement('mo')
y.appendChild(self.dom.createTextNode('∂'))
else:
x.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
y = self.dom.createElement('mo')
y.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
brac = self.dom.createElement('mfenced')
brac.appendChild(self._print(e.expr))
mrow = self.dom.createElement('mrow')
mrow.appendChild(x)
mrow.appendChild(brac)
for sym in e.variables:
frac = self.dom.createElement('mfrac')
m = self.dom.createElement('mrow')
x = self.dom.createElement('mo')
if requires_partial(e):
x.appendChild(self.dom.createTextNode('∂'))
else:
x.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
y = self._print(sym)
m.appendChild(x)
m.appendChild(y)
frac.appendChild(mrow)
frac.appendChild(m)
mrow = frac
return frac
def _print_Function(self, e):
mrow = self.dom.createElement('mrow')
x = self.dom.createElement('mi')
x.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
y = self.dom.createElement('mfenced')
for arg in e.args:
y.appendChild(self._print(arg))
mrow.appendChild(x)
mrow.appendChild(y)
return mrow
def _print_Basic(self, e):
mrow = self.dom.createElement('mrow')
mi = self.dom.createElement('mi')
mi.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
mrow.appendChild(mi)
for arg in e:
x.appendChild(self._print(arg))
return mrow
def _print_AssocOp(self, e):
mrow = self.dom.createElement('mrow')
mi = self.dom.createElement('mi')
mi.append(self.dom.createTextNode(self.mathml_tag(e)))
mrow.appendChild(mi)
for arg in e.args:
mrow.appendChild(self._print(arg))
return mrow
def _print_Relational(self, e):
mrow = self.dom.createElement('mrow')
mrow.appendChild(self._print(e.lhs))
x = self.dom.createElement('mo')
x.appendChild(self.dom.createTextNode(self.mathml_tag(e)))
mrow.appendChild(x)
mrow.appendChild(self._print(e.rhs))
return mrow
def _print_int(self, p):
dom_element = self.dom.createElement(self.mathml_tag(p))
dom_element.appendChild(self.dom.createTextNode(str(p)))
return dom_element
[docs]def mathml(expr, printer='content', **settings):
"""Returns the MathML representation of expr. If printer is presentation then
prints Presentation MathML else prints content MathML.
"""
if printer == 'presentation':
return MathMLPresentationPrinter(settings).doprint(expr)
else:
return MathMLContentPrinter(settings).doprint(expr)
[docs]def print_mathml(expr, printer='content', **settings):
"""
Prints a pretty representation of the MathML code for expr. If printer is
presentation then prints Presentation MathML else prints content MathML.
Examples
========
>>> ##
>>> from sympy.printing.mathml import print_mathml
>>> from sympy.abc import x
>>> print_mathml(x+1) #doctest: +NORMALIZE_WHITESPACE
<apply>
<plus/>
<ci>x</ci>
<cn>1</cn>
</apply>
>>> print_mathml(x+1, printer='presentation')
<mrow>
<mi>x</mi>
<mo>+</mo>
<mn>1</mn>
</mrow>
"""
if printer == 'presentation':
s = MathMLPresentationPrinter(settings)
else:
s = MathMLContentPrinter(settings)
xml = s._print(sympify(expr))
s.apply_patch()
pretty_xml = xml.toprettyxml()
s.restore_patch()
print(pretty_xml)
#For backward compatibility
MathMLPrinter = MathMLContentPrinter