最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java按順序提取Word內(nèi)容的方法步驟(文本+數(shù)學公式)

 更新時間:2025年09月26日 10:15:26   作者:瘋癲的老碼農(nóng)  
本文分享通過Java POI庫解析Word試卷內(nèi)容,將數(shù)學公式轉(zhuǎn)換為LaTeX并保持原有順序的方法,涉及XML文本提取、節(jié)點替換及文檔重構(gòu),解決公式位置錯亂問題,實現(xiàn)非結(jié)構(gòu)化到結(jié)構(gòu)化轉(zhuǎn)換,需要的朋友可以參考下

一、背景

因業(yè)務需求,目前正在實現(xiàn)一項需求,即將一份試卷的內(nèi)容提取出來,由非結(jié)構(gòu)化到結(jié)構(gòu)化的轉(zhuǎn)換。在試卷解析的時候在解析數(shù)學公式的時候花了一番功夫,當成功把word中的數(shù)學公式提出來并且轉(zhuǎn)換為Latex之后已經(jīng)大功告成了呢,突然發(fā)現(xiàn)從word讀取到的公式轉(zhuǎn)換成的Latex不能放到準確的位置,造成了順序錯亂的問題。本方案只是我本人實踐的一種方法(不一定是最好的方法),于是寫下來分享給大家。

二、概述

從一份word格式的試卷中讀取內(nèi)容,使用POI讀取word文件,按照XWPFParagraph進行遍歷,處理每一個XWPFParagraph,從XWPFParagraph獲取xmlText;開始ParserXMLText內(nèi)容(基于org.w3c.dom.Document);找到oMath節(jié)點后轉(zhuǎn)換為Latex,將Latex替換掉oMath節(jié)點后產(chǎn)生新的xmlText,將新的xmlText設置到XWPFParagraph,將XWPFDocument持久化成新的word文檔

三、正文

1、準備一份原始word文件

2、使用POI讀取word文件,按照XWPFParagraph進行遍歷

 
    /**
     * 提取公式并替換為唯一標識符
     * @param fis 原始Word文檔路徑
     * @param outputPath 處理后Word文檔路徑
     * @return 公式與標識符的映射關系
     */
    public Map<String, String> extractAndReplaceFormulas(InputStream fis, String outputPath) {
        Map<String, String> formulaMap = new HashMap<>();
 
        try {
            try (XWPFDocument document = new XWPFDocument(fis)) {
 
                // 遍歷所有段落
                for (XWPFParagraph paragraph : document.getParagraphs()) {
                    processParagraphViaXML(paragraph, formulaMap);
                }
 
                // 保存處理后的文檔
                try (FileOutputStream fos = new FileOutputStream(outputPath)) {
                    document.write(fos);
                }
            }
        } catch (Exception e) {
            log.error("extractAndReplace Formulas: {0}", e);
        }
 
        return formulaMap;
    }

3、處理每一個XWPFParagraph,從XWPFParagraph獲取xmlText

    /**
     * 通過XML直接處理段落中的公式
     */
    public void processParagraphViaXML(XWPFParagraph paragraph, Map<String, String> formulaMap) {
        try {
            CTP ctp = paragraph.getCTP();
 
            // 獲取段落的XML內(nèi)容
            String originalXml = ctp.xmlText();
 
            // 處理XML,替換公式
            String newXml = parserXML(originalXml, formulaMap);
 
            // 用新的XML替換原來的段落內(nèi)容
            CTP newCtp = CTP.Factory.parse(newXml);
            paragraph.getCTP().set(newCtp);
        } catch (Exception e) {
            log.error("processParagraphViaXML Error: {0}", e);
        }
    }

4、開始ParserXMLText內(nèi)容(基于org.w3c.dom.Document)

    private String parserXML(String originalXml, Map<String, String> formulaMap)
            throws IOException, SAXException, ParserConfigurationException, TransformerException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true); // 啟用命名空間支持
        DocumentBuilder builder = factory.newDocumentBuilder();
        org.w3c.dom.Document doc = builder.parse(new ByteArrayInputStream(originalXml.getBytes()));
 
        // 查找m:oMath節(jié)點(使用命名空間)
        NodeList oMathNodes = doc.getElementsByTagNameNS("http://schemas.openxmlformats.org/officeDocument/2006/math", "oMath");
 
        Map<Element,Node> map = new HashMap<>();
 
        for (int i = 0; i < oMathNodes.getLength(); i++) {
            Node oMathNode = oMathNodes.item(i);
            Element rElement = doHandleElement(oMathNode, doc);
            map.put(rElement, oMathNode);
        }
 
        map.forEach((rElement, oMathNode) -> oMathNode.getParentNode().replaceChild(rElement, oMathNode));
 
        return docmentToString(doc);
    }

5、處理Node節(jié)點,并且找到oMath節(jié)點后轉(zhuǎn)換為Latex,將Latex替換掉oMath節(jié)點后產(chǎn)生新的xmlText

 
    private Element doHandleElement(Node oMathNode, org.w3c.dom.Document doc) throws TransformerException {
        // 保存原始公式內(nèi)容(簡化處理,實際可能需要更復雜的序列化)
        String formulaContent = nodeToString(oMathNode);
 
        if(questionMathReader==null){
            questionMathReader = new QuestionMathReader2();
        }
 
        log.debug("formulaContent:{}", formulaContent);
        String latexContent = questionMathReader.convertFromMmlToLatex(formulaContent);
        log.debug("LatexContent:{}", latexContent);
 
        // 創(chuàng)建新的文本節(jié)點
        Text textNode = doc.createTextNode("<KatexText value=\""+latexContent+"\"></KatexText>");
 
        // 創(chuàng)建新的w:r節(jié)點(Word中的文本需要包裝在r中)
        Element rElement = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:r");
        Element tElement = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:t");
        tElement.appendChild(textNode);
        rElement.appendChild(tElement);
        return rElement;
    }
 
    // 輔助方法:將 Node 轉(zhuǎn)換為 XML 字符串
    private String nodeToString(Node node) throws TransformerException {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        StringWriter writer = new StringWriter();
        transformer.transform(new DOMSource(node), new StreamResult(writer));
        return writer.toString();
    }

6、將org.w3c.dom.Document轉(zhuǎn)換為字符串

    private static String docmentToString(org.w3c.dom.Document doc) throws TransformerException {
        // 將修改后的DOM轉(zhuǎn)換回XML字符串
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty(OutputKeys.INDENT, "no");
 
        StringWriter writer = new StringWriter();
        transformer.transform(new DOMSource(doc), new StreamResult(writer));
 
        return writer.toString();
    }

7、將新的xmlText設置到XWPFParagraph,將XWPFDocument持久化成新的word文檔

            // 處理XML,替換公式
            String newXml = parserXML(originalXml, formulaMap);
 
            // 用新的XML替換原來的段落內(nèi)容
            CTP newCtp = CTP.Factory.parse(newXml);
            paragraph.getCTP().set(newCtp);

8、還一個main函數(shù)也一起貼一下

    public static void main(String[] args) throws IOException {
        QuestionMathReplace2 extractor = new QuestionMathReplace2();
 
        // 執(zhí)行提取并替換公式
        Map<String, String> formulaMap = extractor.extractAndReplaceFormulas(
                Files.newInputStream(Paths.get("F://test_source.docx")),
                "F://test_target.docx"
        );
 
        // 輸出映射關系
        for (Map.Entry<String, String> entry : formulaMap.entrySet()) {
            System.out.println(entry.getKey() + " => " + entry.getValue());
        }
    }

9、運行一下,看一下控制臺

10、最后看一下生成的word文件

以上就是Java按順序提取Word內(nèi)容的方法步驟(文本+數(shù)學公式)的詳細內(nèi)容,更多關于Java按順序提取Word內(nèi)容的資料請關注腳本之家其它相關文章!

相關文章

  • 了解java中的session

    了解java中的session

    這篇文章主要介紹了了解java中的session的相關問題,什么是session,session怎么用等,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • 淺談對象與Map相互轉(zhuǎn)化

    淺談對象與Map相互轉(zhuǎn)化

    這篇文章主要介紹了利用BeanMap進行對象與Map的相互轉(zhuǎn)換,在文中列舉了完整代碼,需要的朋友可以參考下。
    2017-09-09
  • springboot默認日志框架選擇源碼解析(推薦)

    springboot默認日志框架選擇源碼解析(推薦)

    這篇文章主要介紹了springboot默認日志框架選擇源碼解析(推薦),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • java中hashmap的底層數(shù)據(jù)結(jié)構(gòu)與實現(xiàn)原理

    java中hashmap的底層數(shù)據(jù)結(jié)構(gòu)與實現(xiàn)原理

    Hashmap是java面試中經(jīng)常遇到的面試題,大部分都會問其底層原理與實現(xiàn),本人也是被這道題問慘了,為了能夠溫故而知新,特地寫了這篇文章,以便時時學習
    2021-08-08
  • ssm項目改造spring?boot項目完整步驟

    ssm項目改造spring?boot項目完整步驟

    Spring?Boot現(xiàn)在已經(jīng)成為Java開發(fā)領域的一顆璀璨明珠,它本身是包容萬象的,可以跟各種技術集成,下面這篇文章主要給大家介紹了關于ssm項目改造spring?boot項目的相關資料,需要的朋友可以參考下
    2023-04-04
  • 在idea中將創(chuàng)建的java web項目部署到Tomcat中的過程圖文詳解

    在idea中將創(chuàng)建的java web項目部署到Tomcat中的過程圖文詳解

    這篇文章主要介紹了在idea中將創(chuàng)建的java web項目部署到Tomcat中的過程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • SpringBoot+Hutool實現(xiàn)圖片驗證碼的示例代碼

    SpringBoot+Hutool實現(xiàn)圖片驗證碼的示例代碼

    圖片驗證碼在注冊、登錄、交易、交互等各類場景中都發(fā)揮著巨大作用,本文主要介紹了SpringBoot+Hutool實現(xiàn)圖片驗證碼的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • 設計模式之責任鏈模式_動力節(jié)點Java學院整理

    設計模式之責任鏈模式_動力節(jié)點Java學院整理

    這篇文章主要為大家詳細介紹了設計模式之責任鏈模式的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • 使用EasyPOI實現(xiàn)多sheet動態(tài)列導出

    使用EasyPOI實現(xiàn)多sheet動態(tài)列導出

    這篇文章主要為大家詳細介紹了如何使用EasyPOI根據(jù)指定時間范圍創(chuàng)建動態(tài)列,以及如何將數(shù)據(jù)組織成符合要求的格式并導出,感興趣的可以了解下
    2025-03-03
  • vue+springboot項目上傳部署tomcat的方法實現(xiàn)

    vue+springboot項目上傳部署tomcat的方法實現(xiàn)

    本文主要介紹了vue+springboot項目上傳部署tomcat的方法實現(xiàn),包括環(huán)境準備、配置調(diào)整以及部署步驟,文中通過圖文及示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-01-01

最新評論

大洼县| 遵化市| 永泰县| 鹤庆县| 波密县| 石阡县| 丹棱县| 苗栗市| 定安县| 岚皋县| 安岳县| 新建县| 信丰县| 章丘市| 内江市| 宁阳县| 灵寿县| 磐石市| 抚松县| 新平| 来凤县| 苍梧县| 许昌市| 日照市| 广丰县| 武城县| 陇南市| 永平县| 普陀区| 丰原市| 鹿邑县| 偃师市| 班玛县| 邻水| 沅江市| 古蔺县| 连江县| 汕尾市| 惠东县| 中卫市| 开原市|