我需要用docx4j合并两个(或更多,但我们坚持两个)word文档(docx)。我的合并方法是从一个文档复制所有body子文档,然后附加到另一个文档。然后,我只是重新安排一些东西。我已经用了两年了,它很适合我的目的。
下面是一个简单的例子:
first.docx = simple text
Second.docx = simple text + image
File first = new File("first.docx");
File second = new File("second.docx");
WordprocessingMLPackage f = WordprocessingMLPackage.load(first);
WordprocessingMLPackage s = WordprocessingMLPackage.load(second);
List body = s.getMainDocumentPart().getJAXBNodesViaXPath("//w:body", false);
for(Object b : body){
List filhos = ((org.docx4j.wml.Body)b).getContent();
for(Object k : filhos)
f.getMainDocumentPart().addObject(k);
}
List blips = s.getMainDocumentPart().getJAXBNodesViaXPath("//a:blip", false);
for(Object el : blips){
try {
CTBlip blip = (CTBlip) el;
RelationshipsPart parts = s.getMainDocumentPart().getRelationshipsPart();
Relationship rel = parts.getRelationshipByID(blip.getEmbed());
RelationshipsPart docRels = f.getMainDocumentPart().getRelationshipsPart();
rel.setId(null);
docRels.addRelationship(rel);
blip.setEmbed(rel.getId());
f.getMainDocumentPart().addTargetPart(s.getParts().getParts().get(new PartName("/word/"+rel.getTarget())));
} catch (Exception ex){}
}
File saved = new File("saved.docx");
f.save(saved);
Desktop.getDesktop().open(saved);
问题是当我保存。出现以下错误:
org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships of /
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:390)
at org.docx4j.openpackaging.io3.Save.save(Save.java:192)
at org.docx4j.openpackaging.packages.OpcPackage.save(OpcPackage.java:441)
at org.docx4j.openpackaging.packages.OpcPackage.save(OpcPackage.java:406)
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships of /word/document.xml
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:390)
at org.docx4j.openpackaging.io3.Save.savePart(Save.java:442)
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:385)
... 4 more
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to put binary part
at
org.docx4j.openpackaging.io3.stores.ZipPartStore.saveBinaryPart(ZipPartStore.java:398)
at org.docx4j.openpackaging.io3.Save.savePart(Save.java:418)
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:385)
... 6 more
Caused by: java.io.IOException: part '/word/media/image1.jpg' not found
at
org.docx4j.openpackaging.io3.stores.ZipPartStore.saveBinaryPart(ZipPartStore.java:361)
... 8 more
Exception in thread "main" org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships of /
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:390)
at org.docx4j.openpackaging.io3.Save.save(Save.java:192)
at org.docx4j.openpackaging.packages.OpcPackage.save(OpcPackage.java:441)
at org.docx4j.openpackaging.packages.OpcPackage.save(OpcPackage.java:406)
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to add parts from relationships of /word/document.xml
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:390)
at org.docx4j.openpackaging.io3.Save.savePart(Save.java:442)
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:385)
... 4 more
Caused by: org.docx4j.openpackaging.exceptions.Docx4JException: Failed to put binary part
at
org.docx4j.openpackaging.io3.stores.ZipPartStore.saveBinaryPart(ZipPartStore.java:398)
at org.docx4j.openpackaging.io3.Save.savePart(Save.java:418)
at org.docx4j.openpackaging.io3.Save.addPartsFromRelationships(Save.java:385)
... 6 more
Caused by: java.io.IOException: part '/word/media/image1.jpg' not found
at
org.docx4j.openpackaging.io3.stores.ZipPartStore.saveBinaryPart(ZipPartStore.java:361)
... 8 more
这里有灯可以解决吗?
1)我不想要所有的大块,它很糟糕。2) docx4j的商业(企业)版本可以做到这一点,但我正在寻找自由/开源软件。
谢谢
在将s中的光点添加到f之前对其进行操作。换句话说,交换for循环的顺序。
那么在你的光点操作中,你需要做的是:
- 获取感兴趣的部分
- Rel = f.getMainDocumentPart().addTargetPart
- 从rel.getId 更新光点中的relId
现在将s的内容添加到f中。您可以使用addAll来完成这项工作,而不需要嵌套循环。而且只有一个body对象,所以不需要外部循环。
显然,这个答案仅限于处理CTBlip,然后只有嵌入的。关于合并docx文件的完整解决方案还有很多…
注意:我在docx4j Enterprise中编写了合并文档的代码
这里我们从帖子中组合了一个真正的工作代码:
List<Object> blips = s.getMainDocumentPart().getJAXBNodesViaXPath("//a:blip", false);
for (Object el : blips) {
try {
CTBlip blip = (CTBlip) el;
RelationshipsPart parts = s.getMainDocumentPart().getRelationshipsPart();
Relationship rel = parts.getRelationshipByID(blip.getEmbed());
Part part = parts.getPart(rel);
if (part instanceof ImagePngPart)
System.out.println(((ImagePngPart) part).getBytes());
if (part instanceof ImageJpegPart)
System.out.println(((ImageJpegPart) part).getBytes());
if (part instanceof ImageBmpPart)
System.out.println(((ImageBmpPart) part).getBytes());
if (part instanceof ImageGifPart)
System.out.println(((ImageGifPart) part).getBytes());
if (part instanceof ImageEpsPart)
System.out.println(((ImageEpsPart) part).getBytes());
if (part instanceof ImageTiffPart)
System.out.println(((ImageTiffPart) part).getBytes());
Relationship newrel = f.getMainDocumentPart().addTargetPart(part, AddPartBehaviour.RENAME_IF_NAME_EXISTS);
blip.setEmbed(newrel.getId());
f.getMainDocumentPart().addTargetPart(s.getParts().getParts().get(new PartName("/word/" + rel.getTarget())));
} catch (Exception ex) {
ex.printStackTrace();
}
}
这个片段在docx中将带有装饰的图像从s文档传输到f文档。需要systs的原因我已经忘记了,但是没有它,lib无法确定图像的mime