解析word公式的解决方案(office插入和wps插入不同的解决方案)

这几天在公司的项目有个需求就是数学公式的导入,而对于word来说,插入的公式xml格式,需要转换为mathML,借用插件MathJax来进行展示,而对于wps插入的公式来说,获取到的是一个wmf图片,wmf是无法在页面上进行展示的,所以思路就是将wmf转换为png图片. 这个在网上的资料有很多,是先转换为svg,再转换为png,但是我在实际操作过程中发现很多问题,就是公式的一些特殊符号展示不出来,所以在这总结下解决办法,最后有两种解决方案,一个是硬编码,一个是借助 第三方来实现.

使用的是poi解析word

先说一下office插入的公式解决方案

思路就是读取出来的xml,先进行转换为mathML,然后直接在页面上展示就可以,直接代码实现:

// 进行转换的过程中需要借助这个文件,网上搜索就可以,或者使用everything这个软件全盘搜一下,一般来说本机安装office就会有这个文件,找到就可以
private static File stylesheet = new File("src/main/resources/OMML2MML.XSL");
private static TransformerFactory tFactory = TransformerFactory.newInstance();
private static StreamSource stylesource = new StreamSource(stylesheet);


/**
 * 获取MathML
 * @param ctomath
 * @return
 * @throws Exception
 */
static String getMathML(CTOMath ctomath) throws Exception {

    Transformer transformer = tFactory.newTransformer(stylesource);

    Node node = ctomath.getDomNode();

    DOMSource source = new DOMSource(node);
    StringWriter stringwriter = new StringWriter();
    StreamResult result = new StreamResult(stringwriter);
    transformer.setOutputProperty("omit-xml-declaration", "yes");
    transformer.transform(source, result);

    String mathML = stringwriter.toString();
    stringwriter.close();

    mathML = mathML.replaceAll("xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"", "");
    mathML = mathML.replaceAll("xmlns:mml", "xmlns");
    mathML = mathML.replaceAll("mml:", "");

    return mathML;
}

/**
 * 返回公式的集合
 * @param document
 * @return
 */
public static Map mml2Html(XWPFDocument document){
    Map result = new HashMap<>();
    try{

        //storing the found MathML in a AllayList of strings
        List mathMLList = new ArrayList(16);

        //getting the formulas out of all body elements
        for (IBodyElement ibodyelement : document.getBodyElements()) {
            if (ibodyelement.getElementType().equals(BodyElementType.PARAGRAPH)) {
                XWPFParagraph paragraph = (XWPFParagraph)ibodyelement;
                for (CTOMath ctomath : paragraph.getCTP().getOMathList()) {
                    mathMLList.add(getMathML(ctomath));
                }
                for (CTOMathPara ctomathpara : paragraph.getCTP().getOMathParaList()) {
                    for (CTOMath ctomath : ctomathpara.getOMathList()) {
                        mathMLList.add(getMathML(ctomath));
                    }
                }
            } else if (ibodyelement.getElementType().equals(BodyElementType.TABLE)) {
                XWPFTable table = (XWPFTable)ibodyelement;
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        for (XWPFParagraph paragraph : cell.getParagraphs()) {
                            for (CTOMath ctomath : paragraph.getCTP().getOMathList()) {
                                mathMLList.add(getMathML(ctomath));
                            }
                            for (CTOMathPara ctomathpara : paragraph.getCTP().getOMathParaList()) {
                                for (CTOMath ctomath : ctomathpara.getOMathList()) {
                                    mathMLList.add(getMathML(ctomath));
                                }
                            }
                        }
                    }
                }
            }
        }

        document.close();

        for (int i = 0; i < mathMLList.size(); i++) {
            // 替换特殊符号(由于页面上无法直接展示特殊符号,所以需要进行替换,将特殊符号替换为html可以认识的标签(https://www.cnblogs.com/xinlvtian/p/8646683.html))
            String s = mathMLList.get(i)
                    .replaceAll("±", "±")
                    .replaceAll("∑","∑");
            s = "" + s + "";
            result.put(i,s);
        }
        return result;
    }catch (Exception e){
        e.printStackTrace();
    }
    return result;
}

/**
 * 获取所有的公式
 * @param xwpfDocument
 * @return
 */
public static Map getFormulaMap(XWPFDocument xwpfDocument){
    Map result = new HashMap<>();
    // 获取到公式的Map集合
    Map mml2Html = mml2Html(xwpfDocument);
    Set> entries = mml2Html.entrySet();
    // 遍历所有段落,获取所有包含公式的段落
    List paragraphs = xwpfDocument.getParagraphs();
    int j = 0;
    for (int i = 0; i < paragraphs.size(); i++) {
        XWPFParagraph xwpfParagraph = paragraphs.get(i);
        CTP ctp = xwpfParagraph.getCTP();
        String xmlText = ctp.xmlText();
        if(xmlText.contains("")){
            StringBuilder sb = new StringBuilder();
            sb.append(xwpfParagraph.getParagraphText());
            sb.append(mml2Html.get(j++));
            result.put(i,sb.toString());
        }

    }
    return result;
}    

public static void main(String[] args) throws Exception {
    XWPFDocument xwpfDocument = new XWPFDocument(new FileInputStream("C:\\Users\\wz157\\Desktop\\题目批量导入模板 (1).docx"));
    // 这个就能获取到所有公式了,Integer表示的是第几个公式,String表示公式转化后的mathML,借助mathJax可以在页面上进行展示
    Map formulaMap = getFormulaMap(xwpfDocument);
    // 接下来就看自己公司的业务了,我们是将这个东西直接存入数据库,到时候展示的时候直接拿出来就可以了
    // 前台展示的时候需要注意,将mathJax下载下来里面有实例,其实就是添加
                    
                    

你可能感兴趣的:(解析word公式的解决方案(office插入和wps插入不同的解决方案))