|
"""Module with some functions for MathML, like transforming MathML |
|
content in MathML presentation. |
|
|
|
To use this module, you will need lxml. |
|
""" |
|
|
|
from pathlib import Path |
|
|
|
from sympy.utilities.decorator import doctest_depends_on |
|
|
|
|
|
__doctest_requires__ = {('apply_xsl', 'c2p'): ['lxml']} |
|
|
|
|
|
def add_mathml_headers(s): |
|
return """<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/mathml2/mathml2.xsd">""" + s + "</math>" |
|
|
|
|
|
def _read_binary(pkgname, filename): |
|
import sys |
|
|
|
if sys.version_info >= (3, 10): |
|
|
|
from importlib.resources import files |
|
return files(pkgname).joinpath(filename).read_bytes() |
|
else: |
|
|
|
from importlib.resources import read_binary |
|
return read_binary(pkgname, filename) |
|
|
|
|
|
def _read_xsl(xsl): |
|
|
|
if xsl == 'mathml/data/simple_mmlctop.xsl': |
|
xsl = 'simple_mmlctop.xsl' |
|
elif xsl == 'mathml/data/mmlctop.xsl': |
|
xsl = 'mmlctop.xsl' |
|
elif xsl == 'mathml/data/mmltex.xsl': |
|
xsl = 'mmltex.xsl' |
|
|
|
if xsl in ['simple_mmlctop.xsl', 'mmlctop.xsl', 'mmltex.xsl']: |
|
xslbytes = _read_binary('sympy.utilities.mathml.data', xsl) |
|
else: |
|
xslbytes = Path(xsl).read_bytes() |
|
|
|
return xslbytes |
|
|
|
|
|
@doctest_depends_on(modules=('lxml',)) |
|
def apply_xsl(mml, xsl): |
|
"""Apply a xsl to a MathML string. |
|
|
|
Parameters |
|
========== |
|
|
|
mml |
|
A string with MathML code. |
|
xsl |
|
A string giving the name of an xsl (xml stylesheet) file which can be |
|
found in sympy/utilities/mathml/data. The following files are supplied |
|
with SymPy: |
|
|
|
- mmlctop.xsl |
|
- mmltex.xsl |
|
- simple_mmlctop.xsl |
|
|
|
Alternatively, a full path to an xsl file can be given. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.utilities.mathml import apply_xsl |
|
>>> xsl = 'simple_mmlctop.xsl' |
|
>>> mml = '<apply> <plus/> <ci>a</ci> <ci>b</ci> </apply>' |
|
>>> res = apply_xsl(mml,xsl) |
|
>>> print(res) |
|
<?xml version="1.0"?> |
|
<mrow xmlns="http://www.w3.org/1998/Math/MathML"> |
|
<mi>a</mi> |
|
<mo> + </mo> |
|
<mi>b</mi> |
|
</mrow> |
|
""" |
|
from lxml import etree |
|
|
|
parser = etree.XMLParser(resolve_entities=False) |
|
ac = etree.XSLTAccessControl.DENY_ALL |
|
|
|
s = etree.XML(_read_xsl(xsl), parser=parser) |
|
transform = etree.XSLT(s, access_control=ac) |
|
doc = etree.XML(mml, parser=parser) |
|
result = transform(doc) |
|
s = str(result) |
|
return s |
|
|
|
|
|
@doctest_depends_on(modules=('lxml',)) |
|
def c2p(mml, simple=False): |
|
"""Transforms a document in MathML content (like the one that sympy produces) |
|
in one document in MathML presentation, more suitable for printing, and more |
|
widely accepted |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.utilities.mathml import c2p |
|
>>> mml = '<apply> <exp/> <cn>2</cn> </apply>' |
|
>>> c2p(mml,simple=True) != c2p(mml,simple=False) |
|
True |
|
|
|
""" |
|
|
|
if not mml.startswith('<math'): |
|
mml = add_mathml_headers(mml) |
|
|
|
if simple: |
|
return apply_xsl(mml, 'mathml/data/simple_mmlctop.xsl') |
|
|
|
return apply_xsl(mml, 'mathml/data/mmlctop.xsl') |
|
|