我正在使用 Apache POI(版本 5.2.2)Java 库来替换 Word 文档中的文本占位符。我的任务之一是替换/编辑矩形中的文本。我正在使用下面的代码,它成功地工作了,我面临的唯一问题是,如果我要更改或编辑文档中的其他段落的文本,那么它会给出异常。下面给出了代码和异常。
更改文本框内容的代码:
private void replacePlaceholdersWithInAShape(XWPFParagraph paragraph) throws XmlException {
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());
XWPFRun bufferrun = new XWPFRun(ctr, (IRunBody)paragraph);
String text = bufferrun.getText(0);
if (text != null && !text.equalsIgnoreCase("")) {
if(text.contains("[{project_number}]")) {
System.out.println("contains project number");
text = text.replace("[{project_number}]", "test");
bufferrun.setText("test", 0);
} else {
bufferrun.setText(text, 0);
}
}
obj.set(bufferrun.getCTR());
}
}
成功编辑文本框/形状中的文本后用于更改段落文本的代码
protected void replaceParagraphPlaceholders(String paraText, XWPFParagraph paragraph, String key, String value, Map<String, Object> fields) {
//paragraph text's empty and null check.
String paragraphText = paragraph.getText();
if(paragraphText!=""&¶graphText!=null) {
if(paragraph.getRuns().size()<=1) {
String runText = "Sample text";
paragraph.getRuns().get(0).setText(runText, 0);
}
}
}
上述代码在更改段落文本时出现的异常如下。
java.util.ConcurrentModificationException: Document changed during select
at org.apache.xmlbeans.impl.xpath.xmlbeans.XmlbeansXPathEngine.next(XmlbeansXPathEngine.java:100)
at org.apache.xmlbeans.impl.store.Cursor._toSelection(Cursor.java:749)
at org.apache.xmlbeans.impl.store.Cursor._getSelectionCount(Cursor.java:764)
at org.apache.xmlbeans.impl.store.Cursor.notifyChange(Cursor.java:697)
at org.apache.xmlbeans.impl.store.Locale.notifyChange(Locale.java:995)
at org.apache.xmlbeans.impl.store.Cur.moveChars(Cur.java:1772)
at org.apache.xmlbeans.impl.store.Cur.moveNodeContents(Cur.java:2016)
at org.apache.xmlbeans.impl.store.Cur.moveNodeContents(Cur.java:1986)
at org.apache.xmlbeans.impl.store.Xobj.store_text(Xobj.java:1833)
at org.apache.xmlbeans.impl.values.XmlObjectBase.set_String(XmlObjectBase.java:1106)
at org.apache.xmlbeans.impl.values.XmlObjectBase.setStringValue(XmlObjectBase.java:1774)
at org.apache.poi.xwpf.usermodel.XWPFRun.setText(XWPFRun.java:363)
at net.sharesuite.formletter.builder.poibuilder.docx.PoiDocxBuilder.replaceParagraphPlaceholders(PoiDocxBuilder.java:596)
at net.sharesuite.formletter.builder.poibuilder.docx.PoiDocxBuilder.lambda$1(PoiDocxBuilder.java:205)
at java.base/java.util.ArrayList$Itr.forEachRemaining(ArrayList.java:1003)
at java.base/java.util.Collections$UnmodifiableCollection$1.forEachRemaining(Collections.java:1061)
at net.sharesuite.formletter.builder.poibuilder.docx.PoiDocxBuilder.createFormLetterFile(PoiDocxBuilder.java:175)
at net.sharesuite.formletter.service.impl.FormLetterServiceImpl.createFormLetter(FormLetterServiceImpl.java:42)
at net.sharesuite.test.formletter.DocumentTest.testNLBLFormletter(DocumentTest.java:646)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
一旦使用 XMLObject 更改文档文本,文档段落等中的其他更改就会导致上述异常。
改变
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>();
到
XmlObject[] ctrsintxtbx = paragraph.getCTP().selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent/w:p/w:r");