java - 如何使用 Apache POI 将 altChunk 元素添加到 XWPFDocument
问题描述
我想使用 Apache POI 将 HTML 作为 altChunk 添加到 DOCX 文件中。我知道 doc4jx 可以使用更简单的 API 来做到这一点,但出于技术原因,我需要使用 Apache POI。
使用 CT 类对 xml 进行低级处理有点棘手。我可以使用以下代码创建一个 altChunk:
import java.io.File;
import java.io.FileOutputStream;
import javax.xml.namespace.QName;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.xmlbeans.impl.values.XmlComplexContentImpl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.impl.CTBodyImpl;
public class AltChunkTest {
public static void main(String[] args) throws Exception {
XWPFDocument doc = new XWPFDocument();
doc.createParagraph().createRun().setText("AltChunk below:");
QName ALTCHUNK = new QName ( "http://schemas.openxmlformats.org/wordprocessingml/2006/main" , "altChunk" ) ;
CTDocument1 ctDoc = doc.getDocument() ;
CTBodyImpl ctBody = (CTBodyImpl) ctDoc. getBody();
XmlComplexContentImpl xcci = ( XmlComplexContentImpl ) ctBody.get_store().add_element_user(ALTCHUNK);
// what's need to now add "<b>Hello World!</b>"
FileOutputStream out = new FileOutputStream(new File("test.docx"));
doc.write(out);
}
}
但是我现在如何将 html 内容添加到“xcci”呢?
解决方案
在Office Open XML
for Word
( *.docx
) 中altChunk
提供了一种使用 pureHTML
来描述文档部分的方法。
关于 的两个重要说明altChunk
:
第一:它仅用于导入内容。如果您使用打开文档Word
并保存它,新保存的文档将不包含替代格式内容部分,也不包含引用它的 altChunk 标记。Word 将所有导入的内容保存为默认Office Open XML
元素。
第二:除了Word
能够阅读的应用程序之外,大多数应用程序*.docx
根本不会阅读altChunk
内容。例如Libreoffice
或OpenOffice
Writer
不会读取内容以及在打开文件时不会读取内容。altChunk
apache poi
altChunk
*.docx
文件结构中是如何altChunk
实现的?*.docx
ZIP
/word/*.html
文件中有文件*.docx
ZIP
。/word/document.xml
例如,这些由 Id 引用<w:altChunk r:id="htmlDoc1"/>
。/word/*.html
Id 和文件之间的关系/word/_rels/document.xml.rels
如<Relationship Id="htmlDoc1" Target="htmlDoc1.html" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk"/>
示例所示。
所以我们首先需要POIXMLDocumentPart
s 来表示/word/*.html
文件,POIXMLRelation
s 来表示 Id 和文件之间的关系/word/*.html
。以下代码提供了一个包装类,该类为 /word/htmlDoc#.html
*.docx ZIP 存档中的文件扩展 POIXMLDocumentPart。这也提供了处理 HTML 的方法。它还提供了一种/word/htmlDoc#.html
在 *.docx ZIP 存档中创建文件并与之建立关系的方法。
代码:
import java.io.*;
import org.apache.poi.*;
import org.apache.poi.ooxml.*;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.xwpf.usermodel.*;
public class CreateWordWithHTMLaltChunk {
//a method for creating the htmlDoc /word/htmlDoc#.html in the *.docx ZIP archive
//String id will be htmlDoc#.
private static MyXWPFHtmlDocument createHtmlDoc(XWPFDocument document, String id) throws Exception {
OPCPackage oPCPackage = document.getPackage();
PackagePartName partName = PackagingURIHelper.createPartName("/word/" + id + ".html");
PackagePart part = oPCPackage.createPart(partName, "text/html");
MyXWPFHtmlDocument myXWPFHtmlDocument = new MyXWPFHtmlDocument(part, id);
document.addRelation(myXWPFHtmlDocument.getId(), new XWPFHtmlRelation(), myXWPFHtmlDocument);
return myXWPFHtmlDocument;
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph;
XWPFRun run;
MyXWPFHtmlDocument myXWPFHtmlDocument;
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Default paragraph followed by first HTML chunk.");
myXWPFHtmlDocument = createHtmlDoc(document, "htmlDoc1");
myXWPFHtmlDocument.setHtml(myXWPFHtmlDocument.getHtml().replace("<body></body>",
"<body><p>Simple <b>HTML</b> <i>formatted</i> <u>text</u></p></body>"));
document.getDocument().getBody().addNewAltChunk().setId(myXWPFHtmlDocument.getId());
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Default paragraph followed by second HTML chunk.");
myXWPFHtmlDocument = createHtmlDoc(document, "htmlDoc2");
myXWPFHtmlDocument.setHtml(myXWPFHtmlDocument.getHtml().replace("<body></body>",
"<body>" +
"<table>"+
"<caption>A table></caption>" +
"<tr><th>Name</th><th>Date</th><th>Amount</th></tr>" +
"<tr><td>John Doe</td><td>2018-12-01</td><td>1,234.56</td></tr>" +
"</table>" +
"</body>"
));
document.getDocument().getBody().addNewAltChunk().setId(myXWPFHtmlDocument.getId());
FileOutputStream out = new FileOutputStream("CreateWordWithHTMLaltChunk.docx");
document.write(out);
out.close();
document.close();
}
//a wrapper class for the htmlDoc /word/htmlDoc#.html in the *.docx ZIP archive
//provides methods for manipulating the HTML
//TODO: We should *not* using String methods for manipulating HTML!
private static class MyXWPFHtmlDocument extends POIXMLDocumentPart {
private String html;
private String id;
private MyXWPFHtmlDocument(PackagePart part, String id) throws Exception {
super(part);
this.html = "<!DOCTYPE html><html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"><style></style><title>HTML import</title></head><body></body>";
this.id = id;
}
private String getId() {
return id;
}
private String getHtml() {
return html;
}
private void setHtml(String html) {
this.html = html;
}
@Override
protected void commit() throws IOException {
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
Writer writer = new OutputStreamWriter(out, "UTF-8");
writer.write(html);
writer.close();
out.close();
}
}
//the XWPFRelation for /word/htmlDoc#.html
private final static class XWPFHtmlRelation extends POIXMLRelation {
private XWPFHtmlRelation() {
super(
"text/html",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk",
"/word/htmlDoc#.html");
}
}
}
注意:由于使用altChunk
此代码需要apache poi faq-N10025ooxml-schemas-*.jar
中提到的所有模式的完整 jar 。
结果:
推荐阅读
- android - App update is available on Google Play store but there in only open option available instead on Update . How to resolve this issue?
- android - Android NDK 工具链中的 LLVM 有什么用?
- c# - C# RealProxy: for chained methods not working logging (Fluent interface pattern)
- javascript - How to have a multipage-multiple tour site using intro.js?
- html - Reply link in email body
- redis - Redis 模块 ReJSON 与 OSS redis
- sql - 具有许多产品类别的站点的数据库设计
- python - 动态 if 循环(业务逻辑)
- json - 他们有什么方法可以在 Solr 中存储嵌套文档吗?
- jquery - How to set timer to a css attribute