php将word中的omath转成mathml

本文介绍了如何从Word文档的XML中提取公式,并将其转换为MathML格式,以便进一步转换为Latex或生成公式图片。重点提及了使用DOMDocument、XSLT和mathjax进行转换的技术细节。

获取word的xml后,可用以下方式将所有的公式都提取并转换成mathml格式,再根据 自己的业务场景进行转换成latex、公式图片即可,mathml可用mathjax直接渲染。

		// 解析xml
        $xml_document_weizhi = stripos($xml, '<w:body>');
        $xml_document  = substr($xml, 0, $xml_document_weizhi);
        
        $mml_arrs= [];

        // 提取所有的公式,转化成mathml
        libxml_disable_entity_loader(false);
        preg_replace_callback('/(<m:oMath>)([\s\S]*?)(<\/m:oMath>)/', function ($matches) use ($xml_document,&$mml_arrs) {
            $mml =$xml_document.'<w:body><m:oMathPara>' . $matches[0] . '</m:oMathPara></w:body></w:document>';
            $domDocument = new DOMDocument();
            $domDocument->loadXML($mml);
            $numberings = $domDocument->getElementsByTagNameNS('http://schemas.openxmlformats.org/wordprocessingml/2006/main', 'body');
            $numberings = $numberings->item(0);
            $xsl        = new DOMDocument();
            $xsl->load('OMML2MML.XSL');
            $processor = new XSLTProcessor();
            $processor->importStyleSheet($xsl);
            $omml                = $processor->transformToXML($numberings);
            $omml                = str_replace('<?xml version="1.0" encoding="UTF-8"?>', '', $omml);
            $omml                = str_replace('xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"', '', $omml);
            $omml                = str_replace("mml:", '', $omml);
            $omml                = str_replace("\n", '', $omml);
 			// 上面转换后部分公式非斜体,但是使用mathjax渲染时还是斜体,就把mi改成mo
            $omml = str_replace("<mi mathvariant=\"normal\">'</mi>","<mo mathvariant=\"normal\">'</mo>",$omml);
          
            $omml = str_replace("<mi>'</mi>","<mo>'</mo>",$omml);
            // 公式中的导数符号被解析成了单引号,经过尝试后用如下格式的mathml使用mathjax渲染后可用!
            $omml = str_replace("<mo>'</mo>","<msup><mi></mi><mo>'</mo></msup>",$omml);
            // 将公式中的斜体的中文都改成正体,在word中明明已取消了斜体,但是解析道德还是斜体,故批量把斜体中文改成正常字体
            $omml = preg_replace('/<mi>([\x{4e00}-\x{9fa5}]+)<\/mi>/isu','<mo>$1</mo>',$omml);
            $mml_arrs[] = $omml;
            return "";
        }, $xml);
要在 Java 中使用你提供的 XSLT 文件将 **DOCX 文档中的数学公式(OMML)转换为 MathML**,需要完成以下几步: 1. 解压 `.docx` 文件(ZIP 格式),提取其中的 XML 内容。 2. 找到包含 OMML 公式的部分(通常在 `word/document.xml` 或 `word/header*.xml` 等文件中)。 3. 提取所有 `<m:...>` 开头的 OMML 元素。 4. 使用 Java 的 **XSLT 转换引擎(JAXP + Transformer)** 应用你的 XSLT 文件进行转换。 5. 输出标准 MathML。 下面是一个完整的、可运行的 Java 示例代码来实现这个过程。 --- ### ✅ 一、准备工作 #### 1. 保存 XSLT 文件 将你提供的 XSLT 内容保存为本地文件,例如: ``` omml-to-mathml.xsl ``` #### 2. Maven 依赖(如果使用 Maven) 确保项目中包含必要的 XML 处理库(JDK 自带 JAXP,无需额外依赖): ```xml <!-- 如果你想更方便地操作 DOCX,推荐使用 Apache POI --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.5</version> </dependency> ``` --- ### ✅ 二、Java 完整代码示例 ```java import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import org.w3c.dom.*; import java.io.*; import java.util.ArrayList; import java.util.List; public class OmmlToMathmlConverter { // XSLT 文件路径 private static final String XSLT_PATH = "omml-to-mathml.xsl"; private static final String DOCX_XML_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"; private static final String MATH_NAMESPACE = "http://schemas.openxmlformats.org/officeDocument/2006/math"; public static void main(String[] args) { try { // 输入:DOCX 中提取出的 document.xml(或完整 DOCX) File docxFile = new File("example.docx"); // 替换为你的 DOCX 文件 List<String> mathmlResults = convertDocxFormulasToMathML(docxFile); // 输出每个公式的 MathML for (int i = 0; i < mathmlResults.size(); i++) { System.out.println("Formula " + (i + 1) + ":\n" + mathmlResults.get(i) + "\n"); } } catch (Exception e) { e.printStackTrace(); } } /** * 从 DOCX 文件中提取所有 OMML 公式并转换为 MathML */ public static List<String> convertDocxFormulasToMathML(File docxFile) throws Exception { List<String> results = new ArrayList<>(); // 使用 Apache POI 读取 DOCX(更简单的方式) try (java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(docxFile)) { java.util.zip.ZipEntry documentEntry = zipFile.getEntry("word/document.xml"); if (documentEntry == null) throw new FileNotFoundException("Not a valid DOCX or missing document.xml"); InputStream inputStream = zipFile.getInputStream(documentEntry); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); Document documentXml = db.parse(inputStream); // 注册命名空间以便 XPath 查询 XPath xpath = XPathFactory.newInstance().newXPath(); xpath.setNamespaceContext(new NamespaceResolver(DOCX_XML_NAMESPACE, MATH_NAMESPACE)); // 查找所有 m:oMath 和 m:altMathInline(OMML 公式) NodeList mathNodes = (NodeList) xpath.evaluate( "//m:oMath | //m:oMathPara | //w:pict//m:*", documentXml, XPathConstants.NODESET); // 加载 XSLT 转换器 StreamSource xsltSource = new StreamSource(new File(XSLT_PATH)); Transformer transformer = TransformerFactory.newInstance().newTransformer(xsltSource); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 遍历每个 OMML 公式节点 for (int i = 0; i < mathNodes.getLength(); i++) { Node ommlNode = mathNodes.item(i); // 创建临时 DOM 文档作为根(因为有些 XSLT 要求有根节点) Document fragmentDoc = db.newDocument(); Node importedNode = fragmentDoc.importNode(ommlNode, true); fragmentDoc.appendChild(importedNode); // 转换 DOMSource source = new DOMSource(fragmentDoc); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); transformer.transform(source, result); String mathml = writer.toString().trim(); // 去掉可能生成的 <?xml ...?> 声明 mathml = mathml.replaceAll("^<\\?xml[^>]+\\?>", "").trim(); if (!mathml.isEmpty()) { results.add(mathml); } } } return results; } /** * 简单的命名空间解析器,用于支持 XPath 查询 */ public static class NamespaceResolver implements org.xml.sax.helpers.DefaultHandler, org.xml.sax.XMLReader { private final String wns; private final String mns; public NamespaceResolver(String wordNs, String mathNs) { this.wns = wordNs; this.mns = mathNs; } public String getNamespaceURI(String prefix) { switch (prefix) { case "w": return wns; case "m": return mns; default: return null; } } public String getPrefix(String uri) { return null; } public java.util.Iterator getPrefixes(String uri) { return null; } } } ``` --- ### ✅ 三、说明与关键点 | 步骤 | 说明 | |------|------| | 1. 解压 DOCX | `.docx` 是 ZIP 包,内部结构包括 `/word/document.xml` 存储正文内容。 | | 2. 解析 XML | 使用 `DocumentBuilder` 解析 XML 并启用命名空间支持。 | | 3. XPath 查找 OMML | 使用 `//m:oMath | //m:oMathPara` 找到所有公式节点。 | | 4. 应用 XSLT | 使用 `Transformer` 加载你提供的 `omml-to-mathml.xsl` 进行转换。 | | 5. 输出 MathML | 每个公式输出一段独立的 MathML 字符串。 | --- ### ✅ 四、测试建议 1. 准备一个包含公式的 `.docx` 文件(如 `a² + b² = c²`)。 2. 将 XSLT 保存为 `omml-to-mathml.xsl` 放在项目根目录。 3. 运行程序,应能看到类似如下输出: ```xml <math xmlns="http://www.w3.org/1998/Math/MathML"> <msup><mi>a</mi><mn>2</mn></msup> <mo>+</mo> <msup><mi>b</mi><mn>2</mn></msup> <mo>=</mo> <msup><mi>c</mi><mn>2</mn></msup> </math> ``` --- ### ✅ 五、注意事项 - ⚠️ 有些公式嵌套复杂,需确保 XSLT 正确处理了所有情况。 - 🔧 若不使用 Apache POI,也可以手动解压 `.docx` 并读取 `document.xml`。 - 🌐 输出的 MathML 可直接嵌入 HTML 并配合 [MathJax](https://www.mathjax.org/) 或 [KaTeX](https://katex.org/) 渲染。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值