Java 如何使用ApachePOI将altChunk元素添加到XWPFDocument

Java 如何使用ApachePOI将altChunk元素添加到XWPFDocument,java,apache-poi,Java,Apache Poi,我想使用apachepoi将HTML作为altChunk添加到DOCX文件中。我知道doc4jx可以用一个更简单的API实现这一点,但出于技术原因,我需要使用ApachePOI 使用CT类对xml进行底层处理有点棘手。我可以使用以下代码创建altChunk: import java.io.File; import java.io.FileOutputStream; import javax.xml.namespace.QName; import org.apache.poi.xwpf.use

我想使用apachepoi将HTML作为altChunk添加到DOCX文件中。我知道doc4jx可以用一个更简单的API实现这一点,但出于技术原因,我需要使用ApachePOI

使用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”it?

在Office Open XML for Word*.docx中,altChunk提供了一种使用纯html描述文档部分的方法

关于altChunk的两个重要注意事项:

第一:它仅用于导入内容。如果使用Word打开并保存文档,则新保存的文档将不包含替代格式内容部分,也不包含引用它的altChunk标记。Word将所有导入的内容保存为默认的Office Open XML元素

第二:除了Word之外,大多数能够读取*.docx的应用程序根本不会读取altChunk内容。例如,在打开*.docx文件时,Libreoffice或OpenOffice Writer不会读取altChunk内容,apache poi也不会读取altChunk内容

altChunk是如何在*.docx ZIP文件结构中实现的

*.docx ZIP文件中有/word/*.html文件。例如,/word/document.xml中的Id引用了这些文件。例如,/word/_rels/document.xml.rels中给出了ID和/word/*.html文件之间的关系

因此,我们首先需要POIXMLDocumentParts用于/word/*.html文件,POIXMLRelations用于ID和/word/*.html文件之间的关系。下面的代码提供了一个包装器类,该类扩展了*.docx ZIP归档文件中/word/htmlDoc.html文件的POIXMLDocumentPart。这还提供了操作HTML的方法。此外,它还提供了一种方法,用于在*.docx ZIP归档文件中创建/word/htmlDoc.html文件并创建与该文件的关系

代码:

注意:由于使用altChunk,这段代码需要所有模式的完整jar,如中所述的ooxml模式-*.jar

结果:

在Office Open XML for Word*.docx中,altChunk提供了一种使用纯HTML描述文档部分的方法

关于altChunk的两个重要注意事项:

第一:它仅用于导入内容。如果使用Word打开并保存文档,则新保存的文档将不包含替代格式内容部分,也不包含引用它的altChunk标记。Word将所有导入的内容保存为默认的Office Open XML元素

第二:除了Word之外,大多数能够读取*.docx的应用程序根本不会读取altChunk内容。例如,在打开*.docx文件时,Libreoffice或OpenOffice Writer不会读取altChunk内容,apache poi也不会读取altChunk内容

altChunk是如何在*.docx ZIP文件结构中实现的

*.docx ZIP文件中有/word/*.html文件。例如,/word/document.xml中的Id引用了这些文件。例如,/word/_rels/document.xml.rels中给出了ID和/word/*.html文件之间的关系

因此,我们首先需要POIXMLDocumentParts用于/word/*.html文件,POIXMLRelations用于ID和/word/*.html文件之间的关系。下面的代码提供了一个包装器类,该类扩展了*.docx ZIP归档文件中/word/htmlDoc.html文件的POIXMLDocumentPart。这还提供了操作HTML的方法。此外,它还提供了一种方法,用于在*.docx ZIP归档文件中创建/word/htmlDoc.html文件并创建与该文件的关系

代码:

注意:由于使用altChunk,这段代码需要所有模式的完整jar,如中所述的ooxml模式-*.jar

结果:

基于,我将对CTBody.addNewAltChunk的调用替换为CTBodyImpl.get\u store.add\u element\u userQName,从而消除了对的额外15MB依赖。因为这是在桌面应用程序中使用的,所以我们尝试将应用程序大小保持尽可能小。如果可能对其他任何人有帮助:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

import javax.xml.namespace.QName;

import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ooxml.POIXMLRelation;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.xmlbeans.SimpleValue;
import org.apache.xmlbeans.impl.values.XmlComplexContentImpl;
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:");
        addHtml(doc,"chunk1","<!DOCTYPE html><html><head><style></style><title></title></head><body><b>Hello World!</b></body></html>");
        FileOutputStream out = new FileOutputStream(new File("test.docx"));
        doc.write(out);
    }

    static void addHtml(XWPFDocument doc, String id,String html) throws Exception {
        OPCPackage oPCPackage = doc.getPackage();
        PackagePartName partName = PackagingURIHelper.createPartName("/word/" + id + ".html");
        PackagePart part = oPCPackage.createPart(partName, "text/html");
        class HtmlRelation extends POIXMLRelation {
            private HtmlRelation() {
                super(  "text/html",
                        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk",
                        "/word/htmlDoc#.html");
            }
        }
        class HtmlDocumentPart extends POIXMLDocumentPart {
            private HtmlDocumentPart(PackagePart part) throws Exception {
                super(part);
            }

            @Override
            protected void commit() throws IOException {
                try (OutputStream out = part.getOutputStream()) {
                    try (Writer writer = new OutputStreamWriter(out, "UTF-8")) {
                        writer.write(html);
                    }
                }
            }
        };
        HtmlDocumentPart documentPart = new HtmlDocumentPart(part);
        doc.addRelation(id, new HtmlRelation(), documentPart);
        CTBodyImpl b = (CTBodyImpl) doc.getDocument().getBody();
        QName ALTCHUNK = new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "altChunk");
        XmlComplexContentImpl altchunk = (XmlComplexContentImpl) b.get_store().add_element_user(ALTCHUNK);
        QName ID = new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id");
        SimpleValue target = (SimpleValue)altchunk.get_store().add_attribute_user(ID);
        target.setStringValue(id);
    }
}
基于,我将对CTBody.addNewAltChunk的调用替换为CTBodyImpl.get\u store.add\u element\u userQName,从而消除了对的额外15MB依赖。因为这是在桌面应用程序中使用的,所以我们尝试将应用程序大小保持尽可能小。如果可能对其他任何人有帮助:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

import javax.xml.namespace.QName;

import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ooxml.POIXMLRelation;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.xmlbeans.SimpleValue;
import org.apache.xmlbeans.impl.values.XmlComplexContentImpl;
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:");
        addHtml(doc,"chunk1","<!DOCTYPE html><html><head><style></style><title></title></head><body><b>Hello World!</b></body></html>");
        FileOutputStream out = new FileOutputStream(new File("test.docx"));
        doc.write(out);
    }

    static void addHtml(XWPFDocument doc, String id,String html) throws Exception {
        OPCPackage oPCPackage = doc.getPackage();
        PackagePartName partName = PackagingURIHelper.createPartName("/word/" + id + ".html");
        PackagePart part = oPCPackage.createPart(partName, "text/html");
        class HtmlRelation extends POIXMLRelation {
            private HtmlRelation() {
                super(  "text/html",
                        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk",
                        "/word/htmlDoc#.html");
            }
        }
        class HtmlDocumentPart extends POIXMLDocumentPart {
            private HtmlDocumentPart(PackagePart part) throws Exception {
                super(part);
            }

            @Override
            protected void commit() throws IOException {
                try (OutputStream out = part.getOutputStream()) {
                    try (Writer writer = new OutputStreamWriter(out, "UTF-8")) {
                        writer.write(html);
                    }
                }
            }
        };
        HtmlDocumentPart documentPart = new HtmlDocumentPart(part);
        doc.addRelation(id, new HtmlRelation(), documentPart);
        CTBodyImpl b = (CTBodyImpl) doc.getDocument().getBody();
        QName ALTCHUNK = new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "altChunk");
        XmlComplexContentImpl altchunk = (XmlComplexContentImpl) b.get_store().add_element_user(ALTCHUNK);
        QName ID = new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id");
        SimpleValue target = (SimpleValue)altchunk.get_store().add_attribute_user(ID);
        target.setStringValue(id);
    }
}

这个特性在poi ooxml 4.0.0中是正常的,其中类POIXMLDocumentPart和POIXMLRelation位于包org.apache.poi.ooxml中*

import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ooxml.POIXMLRelation;
但是我们如何在poi ooxml 3.9中使用,在那里类与org.apache.poi几乎没有什么不同*

import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLRelation;

这个特性在poi ooxml 4.0.0中是正常的,其中类POIXMLDocumentPart和POIXMLRelation位于包org.apache.poi.ooxml中*

import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ooxml.POIXMLRelation;
但是我们如何在poi ooxml 3.9中使用,在那里类与org.apache.poi几乎没有什么不同*

import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLRelation;

对于手动将docx文件编辑为ZIP、d的用户
在上,不要忘记添加[Content\u Types].xml。对于手动将docx文件编辑为ZIP的用户,不要忘记添加[Content\u Types].xml。