使用Apache POI替换docx文本框中的文本

KC *_*C L 2 java apache ms-word apache-poi

我正在使用Apache POI来替换docx的单词.对于正常段落,我成功使用XWPFParagraph和XWPFRun来替换单词.然后我尝试替换文本框中的单词.我引用了这个/sf/answers/1811407951/来获取文本框中的文本.我成功在控制台中打印文本.但是,我无法替换文本框中的单词.以下是我的一些代码:

    for (XWPFParagraph paragraph : doc.getParagraphs()) {
        XmlObject[] textBoxObjects =  paragraph.getCTP().selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' declare namespace wps='http://schemas.microsoft.com/office/word/2010/wordprocessingShape' .//*/wps:txbx/w:txbxContent");
            for (int i =0; i < textBoxObjects.length; i++) {
                XWPFParagraph embeddedPara = null;
                try {
                XmlObject[] paraObjects = textBoxObjects[i].
                    selectChildren(
                    new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "p"));

                for (int j=0; j<paraObjects.length; j++) {
                    embeddedPara = new XWPFParagraph(CTP.Factory.parse(paraObjects[j].xmlText()), paragraph.getBody());
                    List<XWPFRun> runs = embeddedPara.getRuns();
                    for (XWPFRun r : runs) {
                        String text = r.getText(0);
                        if (text != null && text.contains(someWords)) {
                            text = text.replace(someWords, "replaced");
                            r.setText(text, 0);
                        }
                    }
                } 
                } catch (XmlException e) {
                //handle
                }
            }
    }
Run Code Online (Sandbox Code Playgroud)

我认为问题在于我创建了一个新的XWPFParagraph embeddedPara,它取代了embeddedPara的单词而不是原始段落.因此,在我写入文件后,单词仍然没有改变.

如何在不创建新的XWPFParagraph的情况下阅读和替换文本框中的单词?

Axe*_*ter 6

出现此问题是因为Word文本框可能包含在多个不同XmlObjectsWord版本中.那些XmlObjects也可能在非常不同的名称空间.所以selectChildren不能遵循名称空间路线,因此它将返回一个XmlAnyTypeImpl.

所有文本框实现的共同点是它们的运行在路径中.//*/w:txbxContent/w:p/w:r.所以我们可以使用a XmlCursor选择那条路径.然后我们收集所有选中XmlObjectsList<XmlObject>.然后我们CTR从那些对象中解析s,这些对象当然只CTR在文档上下文之外.但是我们可以XWPFRuns从那里创建,替换那些,然后set将那些XML内容XWPFRuns返回到对象.在此之后,我们有包含替换内容的对象.

例:

在此输入图像描述

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor;

import  org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;

import java.util.List;
import java.util.ArrayList;

public class WordReplaceTextInTextBox {

 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument(new FileInputStream("WordReplaceTextInTextBox.docx"));

  String someWords = "TextBox";

  for (XWPFParagraph paragraph : document.getParagraphs()) {
   XmlCursor cursor = paragraph.getCTP().newCursor();
   cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent/w:p/w:r");

   List<XmlObject> ctrsintxtbx = new ArrayList<XmlObject>();

   while(cursor.hasNextSelection()) {
    cursor.toNextSelection();
    XmlObject obj = cursor.getObject();
    ctrsintxtbx.add(obj);
   }
   for (XmlObject obj : ctrsintxtbx) {
    CTR ctr = CTR.Factory.parse(obj.xmlText());
    //CTR ctr = CTR.Factory.parse(obj.newInputStream());
    XWPFRun bufferrun = new XWPFRun(ctr, (IRunBody)paragraph);
    String text = bufferrun.getText(0);
    if (text != null && text.contains(someWords)) {
     text = text.replace(someWords, "replaced");
     bufferrun.setText(text, 0);
    }
    obj.set(bufferrun.getCTR());
   }
  }

  document.write(new FileOutputStream("WordReplaceTextInTextBoxNew.docx"));
  document.close();
 }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述