当前位置: 首页 > 知识库问答 >
问题:

如何使用Apache POI向XWPFDocument添加altChunk元素

苍意智
2023-03-14

我想使用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”中呢?

共有3个答案

韶景曜
2023-03-14

这个特性在poi ooxml 4.0.0中是可以实现的,其中类POIXMLDocumentPart和POIXMLRelation位于包org中。阿帕奇。波伊。ooxml*

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

但是我们如何在poi ooxml 3.9中使用,在poi ooxml 3.9中,类和组织中几乎没有区别。阿帕奇。波伊*

import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLRelation;
郭建华
2023-03-14

根据阿克塞尔·里克特的回答,我把电话换成了CTBody。使用CTBodyImpl添加NewAltChunk()。获取存储()。添加_元素_用户(QName),消除了对ooxml模式的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);
    }
}
沈乐邦
2023-03-14

Office Open XMLforWord*. docx)中,altChunk提供了一种使用纯超文本标记语言描述文档部分的方法。

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

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

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

如何在*中实现altChunk。docxZIP文件结构?

*. docxZIP文件中有/word/*. html文件。这些文件在/word/document.xml中被Id引用为

所以我们首先需要POIXMLDocumentParts来表示/word/*。html文件和POIXMLRelations,用于标识和/word/*之间的关系。html文件。下面的代码提供了一个包装器类,该类扩展了/word/htmlDoc#的POIXMLDocumentPart。html中的文件*。docx压缩文件。这还提供了操作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这个代码需要所有模式的完整jarooxml模式-*。jar如apache poi faq-N10025所述。

结果:

 类似资料:
  • 问题内容: 在CSS中,将鼠标悬停在元素上时,可以使用:hover伪类为其指定视图: 如何使用jquery添加或“打开”此伪类?通常在jQuery中,如果您想添加一个类,可以这样做: 我已经尝试过“ hover”,但这实际上是在元素中添加了一个名为“ hover”的类。 如果有人知道写什么,请告诉我!谢谢! 问题答案: 您不能强迫某个伪类使用jQuery来应用。伪类(尤其是动态伪类)不是这样工作的

  • 问题内容: 我有办法 在内部,我想调用另一个方法并将其传递,但是我想向其他对象添加新元素(描述)。 如何在Java中做到这一点?代码是什么样的? 问题答案: 只是一个数组。因此: 您可能需要弄混的通用类型。 您可以更快但更冗长:

  • 问题内容: 我正在尝试找到一种使用JavaScript添加/更新属性的方法。我知道我可以使用功能来做到这一点,但在IE中不起作用。 问题答案: 您可以在此处阅读有关许多不同浏览器(包括IE)中属性的行为的信息。 即使在IE中也应该做到这一点。你试过了吗?如果它不起作用,则可能 会起作用。

  • 问题内容: 我知道如何在“ jQuery”中单击按钮来添加类 我想通过angular js实现相同的功能。我有一个控制器-myController1。有人可以帮助我做到这一点吗? 问题答案: AngularJS有一些称为JQlite的方法,因此我们可以使用它。见链接 选择DOM中的元素是 像添加类 所以最后

  • 我有一个观察数据表和是和否的模型。为简单起见,我只假设对组。我浪费了一些分类统计数据,我想控制选择哪一个。我知道如何使用eval做到这一点并将其保存在另一个data.table中,但我想添加到现有的data.table中,因为我每个组只有一行。任何人都可以帮我吗? 首先,我为每个组创建列联表。 然后定义统计数据 如果我使用下面几行,它会给我一个新的数据表: 如何在此示例中使用:=将结果添加到我的旧

  • 问题内容: 我有以下代码: 这两个附录未编译。那将如何正常工作? 问题答案: 数组的大小无法修改。如果需要更大的数组,则必须实例化一个新数组。 更好的解决方案是使用可以根据需要增长的容器。如果你需要此形式的数组,该方法将为你提供数组。 如果需要将其转换为简单数组… 但是,使用数组执行的大多数操作也可以使用此ArrayList进行: