提问人:BenHT 提问时间:7/5/2023 最后编辑:BenHT 更新时间:7/6/2023 访问量:37
命名空间在保存克隆/编辑的docx时消失,导致Word中出现“不可读内容”消息
Namespace disappearing on save of cloned/edited docx, leading to "Unreadable content" message in Word
问:
我们使用 docx4j (docx4j-JAXB-MOXy v11.4.9) 将图像添加到 docx,然后将其传递到另一个系统(only-office)进行编辑。 如果我加载 docx,克隆它,清除正文,将一些原始内容复制回去然后保存它,就会删除其中一个命名空间(现在图像需要)。因此,当您在 Word 中打开时,您当然会收到“不可读内容”消息。
保存的文档缺少document.xml顶部的原始文档中的此命名空间:
xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
文档.xml 中的 Excerts,显示如何使用 wpg 命名空间添加回退图像:
<w:r>
<w:rPr>
<w:color w:val="000000"/>
</w:rPr>
<w:t xml:space="preserve">Image :</w:t>
<mc:AlternateContent>
<mc:Choice Requires="wpg">
<w:drawing>
...
</w:drawing>
</mc:Choice>
<mc:Fallback>
<w:pict>
...
</w:pict>
</mc:Fallback>
</mc:AlternateContent>
</w:r>
从包含该命名空间的原始代码重现的示例代码:
InputStream mergedDocStream = new BufferedInputStream(new FileInputStream("c:\\tmp\\original.docx"), 8 * 1024 * 1024);
WordprocessingMLPackage mergedDoc = WordprocessingMLPackage.load(mergedDocStream);
mergedDocStream.close();
List<Object> mergedDocContentList = mergedDoc.getMainDocumentPart().getContent();
// get the body section (contains styles, orientation, headers/footers) which needs adding to each doc
SectPr finalSectionProperties = mergedDoc.getMainDocumentPart().getJaxbElement().getBody().getSectPr();
// Create a blank target using the merged file
ObjectFactory objectFactory = new ObjectFactory();
mergedDoc.getMainDocumentPart().getJaxbElement().setBody(objectFactory.createBody());
WordprocessingMLPackage outputDoc = (WordprocessingMLPackage) mergedDoc.clone();
// loop through the original doc's contents and add
for (Object content : mergedDocContentList) {
outputDoc.getMainDocumentPart().addObject(content);
}
// add body section for original styles etc
outputDoc.getMainDocumentPart().getJaxbElement().getBody().setSectPr(finalSectionProperties);
// save last doc
File outputFile = new File("c:\\tmp\\output.docx");
outputDoc.save(outputFile);
有没有办法说服它保留该命名空间?
答:
1赞
JasonPlutext
7/6/2023
#1
作为后台,JAXB 会自动声明必需的名称空间。
@Requires中指定的是不同的,因为尽管 Word 需要它们,但在 XML 规范意义上不需要它们。
因此,docx4j 会在解组过程中遇到这些情况时对其进行跟踪(请参阅 Docx4jUnmarshallerListener)。但是,如果当时 docx 中不存在 @Requires 属性,则无法执行此操作。
JaxbXmlPart 包含:
/**
* Specify a namespace prefix (used in mc:Choice/@Requires) which
* docx4j should declare on the top-level element of the part
* (otherwise Microsoft Office won't be able to open the file).
*
* Specify a prefix (eg 'wpg') as opposed to the namespace itself.
*
* This is often done automatically (see further McIgnorableNamespaceDeclarator),
* but where it isn't, you should invoke this method directly
* from your code.
*
* @param mcChoiceNamespace
*/
public void addMcChoiceNamespace(String mcChoiceNamespace) {
this.mcChoiceNamespaces.add(mcChoiceNamespace);
}
就您而言,
outputDoc.getMainDocumentPart().addMcChoiceNamespace("wpg");
应该可以解决问题。
评论