POI操作latex公式转mathml生成word文档

POI操作latex公式转mathml生成word文档

转发请注明出处,谢谢!

 

我的上一篇文章已经讲解了用Itext操作的方法,这篇就直接上干货,效果图,注意事项,功能说明及Itext操作请见

http://blog.csdn.net/qq_35834998/article/details/79170388             这篇文章和此文章紧密相关

 

 

Itext,POI操作---项目中所有的依赖



   commons-codec
   commons-codec
   1.3



   dom4j
   dom4j
   1.6.1



   stax
   stax-api
   1.0.1



   xml-apis
   xml-apis
   1.4.01



   org.apache.xmlbeans
   xmlbeans
   2.6.0



   com.lowagie
   itext
   2.1.7



   com.itextpdf
   itext-asian



   com.lowagie
   itext-rtf
   2.1.7


   fmath
   fmath-mathml-java
   3.1


   org.scilab.forge
   jlatexmath
   1.0.6




   jdom
   jdom-jar
   2.0.6




   org.apache.poi
   poi-scratchpad
   3.9


   org.apache.poi
   poi-ooxml
   3.16


   org.apache.poi
   poi-scratchpad
   3.16


   org.apache.poi
   ooxml-schemas
   1.3



   org.jdom
   jdom2
   2.0.6





   org.apache.commons
   commons-lang3
   3.0



      
          uk.ac.ed.ph.snuggletex
          snuggletex-core
          1.2.2
      

 

直接上代码 :

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class TextTest {


    @Autowired
    private QuesService quesService;

    private Pattern pattern = Pattern.compile("\\\\\\\\\\[(.*?)\\\\\\\\\\]");

    private  Pattern compile = Pattern.compile("\\p{Lower}");

    private  SnuggleEngine engine = new SnuggleEngine();

    static File stylesheet = new File("C:\\Program Files\\Microsoft Office\\root\\Office16\\MML2OMML.XSL");
    static TransformerFactory tFactory = TransformerFactory.newInstance();
    static StreamSource stylesource = new StreamSource(stylesheet);

    static CTOMath getOMML(String mathML) throws TransformerException, IOException, XmlException {
        Transformer transformer = tFactory.newTransformer(stylesource);

        StringReader stringreader = new StringReader(mathML);
        StreamSource source = new StreamSource(stringreader);

        StringWriter stringwriter = new StringWriter();
        StreamResult result = new StreamResult(stringwriter);

        transformer.transform(source, result);

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

        CTOMathPara ctOMathPara = CTOMathPara.Factory.parse(ooML);

        CTOMath ctOMath = ctOMathPara.getOMathArray(0);

        //for making this to work with Office 2007 Word also, special font settings are necessary
        XmlCursor xmlcursor = ctOMath.newCursor();
        while (xmlcursor.hasNextToken()) {
            XmlCursor.TokenType tokentype = xmlcursor.toNextToken();
            if (tokentype.isStart()) {
                if (xmlcursor.getObject() instanceof CTR) {
                    CTR cTR = (CTR) xmlcursor.getObject();
                    cTR.addNewRPr2().addNewRFonts().setAscii("Cambria Math");
                    cTR.getRPr2().getRFonts().setHAnsi("Cambria Math");
                }
            }
        }

        return ctOMath;
    }


    @Test
    public void test() throws Exception {
        XWPFDocument document = new XWPFDocument();

        //题目编号
        int number = 0;
        List stringList = Arrays.asList("01162767-2f7d-458d-8945-877a81fd3361",
                                                "0040110f-2c26-4865-b999-c8754f5803e3",
                                                "04e03596-eb46-4acc-9446-e492f1e664ba",
                                                "01ab3b66-81ce-47ee-946e-51247190a9b1",
                                                "03275325-4dbb-4d7b-a700-602156faaa2e",
                                                "200b40af-9b46-4f76-9856-e77007ff83ca",
                                                "0188832e-53f2-4223-bfc7-c9083adc572c"
                                                );
        for (String id : stringList ) {
            XWPFParagraph paragraph = document.createParagraph();
            paragraph.setSpacingAfter(200);

            Ques ques = quesService.getQuesFromId(id);


            //题干类容段落
            String[] titleSplit = titleGroup(++number, ques);
            //按照顺序写入文档
            for (int i = 0 ; i < titleSplit.length ; i++ ) {
                splitWrite(paragraph,document,i,titleSplit);
                //splitWriteImageLatex(paragraph,document,i,titleSplit);
            }




            //选项段落
            paragraph = document.createParagraph();
            paragraph.setSpacingAfter(200);

            //四个选项
            String[] splitOptions = ques.getOptions().split("\\|\\|\\|");
            for (int i = 0 ; i < splitOptions.length ; i++ ) {
                if (splitOptions[i].contains("http")){
                    XWPFRun run = paragraph.createRun();
                    run.setText(chooseTag(i));
                    paragraph.addRun(run);

                    String image = download(splitOptions[i], "E:\\题库文档\\test06\\" + i + ".png");
                    writeImage(paragraph,document,image);
                }else{
                    XWPFRun run = paragraph.createRun();
                    run.setText(chooseTag(i));
                    paragraph.addRun(run);

                    String[] optionsGroup = optionsGroup(splitOptions[i]);
                    for (int a = 0 ; a < optionsGroup.length ; a++ ){
                        splitWrite(paragraph,document,a,optionsGroup);
                    }
                    //latex2mathMl(paragraph,optionsGroup[a],engine);
                    //splitWriteImageLatex(paragraph,document,i,splitOptions);
                }
            }
            

            //详解类容
            paragraph = document.createParagraph();
            paragraph.setSpacingAfter(200);

            //题目类容段落
            String[] analysisSplit = analysisGroup(ques);
            //按照顺序写入文档
            for (int i = 0 ; i < analysisSplit.length ; i++ ) {
                splitWrite(paragraph,document,i,analysisSplit);
                //splitWriteImageLatex(paragraph,document,i,analysisSplit);
            }
        }

        document.write(new FileOutputStream("E:\\题库文档\\test06\\text.docx"));
        document.close();

    }



   /**
    *  测试带图片段落
    *  */
    @Test
    public void testCreateParagraphWithImg() throws Exception {
        BufferedImage read = ImageIO.read(new URL("https://img0.xuehuilema.com/70e93c38-0a35-4944-8d82-a9c00c451d46.png"));
        System.out.println(read);
        ImageIO.write(read, "png", new File("E:\\题库文档\\test06\\123.png"));
    }

    /**
     *写入文档操作latex
     * */
    private void splitWrite(XWPFParagraph paragraph,XWPFDocument document,Integer i,String[] split){
        Matcher mather = compile.matcher(split[i]);
        if (!mather.find()){
            String comment = split[i];
            if(comment.contains("$")){
                comment = comment.replaceAll("\\$","");
            }
            XWPFRun run = paragraph.createRun();
            run.setText(comment);
            paragraph.addRun(run);
        }else{
            try {
                latex2mathMl(paragraph,split[i]);
            }catch (Exception e){
                String image = null;
                try {
                    image = latexImage(split[i], "E:\\题库文档\\test06\\" + i + ".png");
                    writeImage(paragraph,document,image);
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        }

    }

    /**
     *写入文档操作latexImage
     * */
    private void splitWriteImageLatex(XWPFParagraph paragraph,XWPFDocument document,Integer i,String[] split) throws Exception {
        Matcher mather = compile.matcher(split[i]);
        if (!mather.find()){
            XWPFRun run = paragraph.createRun();
            run.setText(split[i]);
            paragraph.addRun(run);
        }else{
            String image = latexImage(split[i], "E:\\题库文档\\test06\\" + i + ".png");
            writeImage(paragraph,document,image);
        }
    }

    /**
     * 转换latex公式并写入文档
     * */
    private void latex2mathMl(XWPFParagraph paragraph,String latex) throws XmlException, TransformerException, IOException {
        String mathML = fmath.conversion.ConvertFromLatexToMathML.convertToMathML(latex);
        mathML = mathML.replaceFirst(" 0) {
                pRun = paragraph.getRuns().get(0);
            } else {
                pRun = paragraph.createRun();
            }
        }
        if (isNewLine) {
            pRun.addBreak();
        }
        return pRun;
    }

    /**
     * @Description 设置字体信息
     */
    public void setParagraphRunFontInfo(XWPFParagraph paragraph, XWPFRun pRun,
                                        String content, String fontFamily, String fontSize) {
        CTRPr pRpr = getRunCTRPr(paragraph, pRun);
        if (StringUtils.isNotBlank(content)) {
            pRun.setText(content);
        }
        // 设置字体
        CTFonts fonts = pRpr.isSetRFonts() ? pRpr.getRFonts() : pRpr
                .addNewRFonts();
        fonts.setAscii(fontFamily);
        fonts.setEastAsia(fontFamily);
        fonts.setHAnsi(fontFamily);
        // 设置字体大小
        CTHpsMeasure sz = pRpr.isSetSz() ? pRpr.getSz() : pRpr.addNewSz();
        sz.setVal(new BigInteger(fontSize));
        CTHpsMeasure szCs = pRpr.isSetSzCs() ? pRpr.getSzCs() : pRpr
                .addNewSzCs();
        szCs.setVal(new BigInteger(fontSize));
    }


    /**
     * @Description: 得到XWPFRun的CTRPr
     */
    public CTRPr getRunCTRPr(XWPFParagraph p, XWPFRun pRun) {
        CTRPr pRpr = null;
        if (pRun.getCTR() != null) {
            pRpr = pRun.getCTR().getRPr();
            if (pRpr == null) {
                pRpr = pRun.getCTR().addNewRPr();
            }
        } else {
            pRpr = p.getCTP().addNewR().addNewRPr();
        }
        return pRpr;
    }


    /**
     * 创建图片xml
     * */
    private void createPicture(String blipId, int id, int width, int height,
                              XWPFParagraph paragraph) {
        final int EMU = 9525;
        width *= EMU;
        height *= EMU;
        // String blipId =
        // getAllPictures().get(id).getPackageRelationship().getId();
        if (paragraph == null) {
            XWPFDocument document = new XWPFDocument();
            paragraph = document.createParagraph();
        }
        CTInline inline = paragraph.createRun().getCTR().addNewDrawing()
                .addNewInline();
        String picXml = ""
                + ""
                + "   "
                + "      "
                + "         " + "            "
                + "            "
                + "         "
                + "         "
                + "            "
                + "            "
                + "               "
                + "            "
                + "         "
                + "         "
                + "            "
                + "               "
                + "               "
                + "            "
                + "            "
                + "               "
                + "            "
                + "         "
                + "      "
                + "   " + "";
        // CTGraphicalObjectData graphicData =
        // inline.addNewGraphic().addNewGraphicData();
        XmlToken xmlToken = null;
        try {
            xmlToken = XmlToken.Factory.parse(picXml);
        } catch (XmlException xe) {
            xe.printStackTrace();
        }
        inline.set(xmlToken);
        // graphicData.set(xmlToken);
        inline.setDistT(0);
        inline.setDistB(0);
        inline.setDistL(0);
        inline.setDistR(0);
        CTPositiveSize2D extent = inline.addNewExtent();
        extent.setCx(width);
        extent.setCy(height);
        CTNonVisualDrawingProps docPr = inline.addNewDocPr();
        docPr.setId(id);
        docPr.setName("docx_img_ " + id);
        docPr.setDescr("docx Picture");
    }






    /**
     * 将网络图片保存到本地
     * */
    private String download(String url,String savePathAndName) throws Exception {
        url = url.replaceAll("http","https");
        BufferedImage read = ImageIO.read(new URL(url));
        ImageIO.write(read, "png", new File(savePathAndName));
        return savePathAndName;
    }

    /**
     * 题干类容段落处理
     * */
    private String[] titleGroup(Integer number,Ques ques){
        String title = number + "." + ques.getTitle();
        //公式处理
        title = title.replaceAll("\\\\","\\\\\\\\");
        String titleNot = title.replaceAll("\\\\\\\\\\[(.*?)\\\\\\\\\\]","@@@");
        Matcher mather = pattern.matcher(title);
        while (mather.find()){
            String formula = mather.group(1);
            titleNot = titleNot.replaceFirst("@@@", "@@\\$"+formula+"\\$@@");
        }
        String[] titleSplit = titleNot.split("@@");
        return titleSplit;
    }

    /**
     * 获取选择题选项标签
     * */
    private String chooseTag(Integer i){
        if (i == 0){
          return "A:";
        }else if(i == 1){
            return "        B:";
        }else if(i == 2){
            return "        C:";
        }else{
            return "        D:";
        }
    }

    /**
     * 详解类容段落处理
     * */
    private String[] analysisGroup(Ques ques){
        String analysis = ques.getAnalysis();
        //公式处理
        analysis = analysis.replaceAll("\\\\","\\\\\\\\");
        String analysisNot = analysis.replaceAll("\\\\\\\\\\[(.*?)\\\\\\\\\\]","@@@");
        Matcher mather = pattern.matcher(analysis);
        while (mather.find()){
            String formula = mather.group(1);
            analysisNot = analysisNot.replaceFirst("@@@", "@@\\$"+formula+"\\$@@");
        }
        String[] analysisSplit = analysisNot.split("@@");
        return analysisSplit;
    }

    /**
     * 选择类容段落处理
     * */
    private String[] optionsGroup(String option){
        //公式处理
        option = option.replaceAll("\\\\","\\\\\\\\");
        String optionNot = option.replaceAll("\\\\\\\\\\[(.*?)\\\\\\\\\\]","@@@");
        Matcher mather = pattern.matcher(option);
        while (mather.find()){
            String formula = mather.group(1);
            optionNot = optionNot.replaceFirst("@@@", "@@\\$"+formula+"\\$@@");
        }
        String[] optionSplit = optionNot.split("@@");
        return optionSplit;
    }


    /**
     * latex公式转图片
     * */
    private String latexImage(String formulaStr,String path) throws IOException, BadElementException {
        TeXFormula tf = new TeXFormula(formulaStr);
        TeXIcon ti = tf.createTeXIcon(TeXConstants.STYLE_DISPLAY, 15);
        BufferedImage bimg = new BufferedImage(ti.getIconWidth(), ti.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D g2d = bimg.createGraphics();
        g2d.setColor(Color.white);
        g2d.fillRect(0,0,ti.getIconWidth(), ti.getIconHeight());
        JLabel jl = new JLabel();
        jl.setForeground(new Color(0, 0, 0));
        ti.paintIcon(jl, g2d, 0, 0);
        File out = new File(path);
        ImageIO.write(bimg, "png", out);
        return path;
    }


    /**
     * 将图片写入文档
     * */
    private void writeImage(XWPFParagraph paragraph,XWPFDocument document,String image) throws IOException, InvalidFormatException {
        File file = new File(image);
        BufferedImage read = ImageIO.read(file);

        String blipId = paragraph.getDocument().addPictureData(
                new FileInputStream(file),
                Document.PICTURE_TYPE_PNG);
        createPicture(blipId,
                document.getNextPicNameNumber(Document.PICTURE_TYPE_PNG),  read.getWidth(), read.getHeight(),paragraph);
    }

}

 

如果在操作中遇到什么问题,可留言,博主会及时回答,给你意见及解决的办法,博客写得不好的地方,希望谅解!

 

 

 

 

你可能感兴趣的:(java,word,POI,latex,mathml)