公式格式简述
-
Latex
一种排版系统和标记语言,通常用于科学、技术、工程和数学(STEM)领域的文档,如学术论文、报告、书籍等。
在学术界和专业领域中得到广泛应用。
示例:
sqrt[y]{x}
渲染为 xysqrt[y]{x}yx -
MML (MathML)
全称为 Mathematical Markup Language(数学标记语言),一种用于在计算机中描述数学公式和数学内容的标记语言,它使用 XML 格式来在计算机系统中表示数学公式。
示例:
x y
-
OMML
Office Math Markup Language(OMML)是由微软开发的一种标记语言,用于在Microsoft Office文档中表示和排版数学公式和数学内容。OMML 是一种基于XML的标记语言,旨在帮助用户在Microsoft Word、Microsoft PowerPoint 和 Microsoft Excel等Office应用程序中创建和编辑复杂的数学表达式。
OMML 用于 Office Word 中渲染,这里不放示例了。
总结一下这个三种公式格式:
- Latex 在大型论文领域应用的最广泛,所以它对各种奇形怪状的化学/物理公式支持的都较好;
- MML 主要是为了在网页上渲染数学公式;
- OMML 主要是为了在 Office 中渲染数学公式。
成熟的教育产品是如何使用公式的?
MML/OMML 都是侧重于 数学公式,而 Latex 对于理科公式都能良好的表达。
但 MML 便于网页渲染,Latex 则无法直接在网页上渲染。
目前的在线题库/教育资源等网站,一般都采用同时保存 MML/ Latex 公式,便于不同场景的使用。
学科网开放平台推题返回试题信息示例:
我们可以看到,仍在标签中保留了 latex 源码,主要可能用于后台试题编辑。
xOy
中,已知圆
C:5x2+5y2+10y−4=0
学科网页面渲染,采用 将公式转为 SVG 的方式渲染
21世纪教育网暂无开放平台,页面渲染则采用将 MML 公式转为 PNG 的方式来渲染
公式格式转换
在线题库的题量需求很大,达到百万级也只是毛毛雨。
试题大部分都来源于批量导入,而不是教研老师一道题一道题在页面上编辑。
使用到最多的就是 Word 导入,而上面我们讲过,Word 中公式的格式为 OMML 格式,所以此时就涉及到 OMML --> Latex / MML 格式的转换。
公式之间的相互转换,不是一件简单的事。因为他们各自都有自己的标准。
有一件尴尬的事,目前并没有很好的直接转换 OMML 为 Latex 的方法,所以公式转换的路径一般为 OMML --> MML --> Latex。
比较幸运的,Office 中携带了一些映射文件,我们可以借助映射文件,比较方便的实现上述的路径。
使用方法具体如下:
将映射文件放入项目中
构建转换方法
//设置xls依赖文件的路径
public static URIResolver r = (href, base) -> {
InputStream inputStream = FormulaConvertUtil.class.getResourceAsStream("/formula/xsl/" + href);
return new StreamSource(inputStream);
};
/**
* Description: office mathml转为mml
*
* @param xml
* @return
*/
public static String convertOMMLToMML(String xml) {
String result = xslConvert(xml, "/formula/xsl/omml2mml.xsl", null);
return result;
}
/**
* mathml to latex
*
* @param mml mathml 公式源码
* @return java.lang.String
*/
public static String convertMMLToLatex(String mml) {
String latex = xslConvert(mml, "/formula/xsl/mmltex.xsl", r);
//latex = latex.replaceAll("△"," \\triangle ");
return latex;
}
/**
* xsl Convert
*
* @param formula 公式
* @param uriResolver 转换器
* @return java.lang.String
* @author YangXinFu
*/
public static String xslConvert(String formula, String xslPath, URIResolver uriResolver) {
TransformerFactory tFac = TransformerFactory.newInstance();
if (uriResolver != null) tFac.setURIResolver(uriResolver);
// InputStream inputStream = FormulaConvertUtil.class.getResourceAsStream("/formula/xsl/mmltex.xsl");
InputStream inputStream = FormulaConvertUtil.class.getResourceAsStream(xslPath);
StreamSource xslSource = new StreamSource(inputStream);
StringWriter writer = new StringWriter();
try {
Transformer t = tFac.newTransformer(xslSource);
Source source = new StreamSource(new StringReader(formula));
Result result = new StreamResult(writer);
t.transform(source, result);
} catch (TransformerException e) {
log.warn("公式转换失败。",e);
return "";
}
return writer.getBuffer().toString();
}
到这里基本可以使用了,但还需要注意转换并不是 100% 映射,不常用的符号有可能失败。
Latex转图
在 Java 中 Latex 公式转图片,一般使用 jlatexmath 。
但是在 Maven 仓库中 1.0.8 版本,不支持 ce
命令,使用时需要注意。
ce
命令被包含在 Latex 的 Mhchem 扩展中,所以需要额外功能支持。例如:ce{SO4^2- + Ba^2+ -> BaSO4 v}
应渲染为 :
但,其实早在 2018 年,已经有人提过 issue:
对于 mhchem 的支持,已经被合并到 github.com/opencollab/… 实验分支上,并未推送正式版 jar 包到 Maven Resp 中。
所以想要使用该特性,我们只需要将 experimental 分支代码拉到本地,进行简单的修改,打包推送到自己的 Maven 私服中便可使用。
在此分支中,包含一些 GWT 的代码
GWT 是 Google Web Toolkit 的缩写,它是一个用于构建富客户端 Web 应用程序的开源开发工具集。GWT 最初由 Google 开发并发布,旨在帮助开发人员使用 Java 编程语言来构建现代的、高性能的、交互式的 Web 应用程序。
开发人员可以使用熟悉的 Java 编程语言来构建客户端代码,然后使用 GWT 编译器将 Java 代码转换为高效的 JavaScript 代码。
但是,对在服务转换的情况,基本没什么用。我们只需要“酌情”把 GWT 相关的代码,全部干掉就行了。
打完包,使用方法如下:
// 这里需要初始化一个 Provider。
static {
FactoryProvider.setInstance(new FactoryProviderDesktop());
}
public static Image latexToImg(String latex, Float size) {
int style = TeXConstants.STYLE_DISPLAY; // 样式 符号以最大的尺寸呈现
float fontSize = Objects.isNull(size) ? 16 : size ; // 生成公式图片的字体大小
// 字体颜色,黑色
ColorD fg = new ColorD(Color.BLACK);
TeXFormula.setDPITarget(72);
return (BufferedImage) TeXFormula.createBufferedImage(latex, style, fontSize * 3, fg, null);
}
另外,还有 Aspose.TeX 工具可以转图,但是暂不支持中文,即公式中包含中文时,会乱码。
小结
在线题库项目中,公式可存储为 Latex/MML 两种格式,MML 进一步可转为 SVG/PNG 等格式在线渲染,Latex 格式可用于在线编辑。
MML目前没有友好的可视化编辑器,而 Latex 公式有 LatexLive 等很优秀的可视化编辑器。
另外,公式转换想一劳永逸是不可能的事,因为总会有一些奇奇怪怪的符号没发转换,这时只能手动的进行符号对应。
举个例子:
Latex 中有长等号
$xlongequal[b]{a}$
表现为 =baxlongequal[b]{a}ab
但是 OMML 并没有对应的符号可以表示,只能通过其他形式处理。