使用 docx4j 创建 .docx 时如何保留 HTML?

How to preserve the HTML when creating a .docx with docx4j?

我今天开始使用 docx4j;

我已经成功创建了一个文档 table,其中包含来自外部来源的内容。

这个内容里面有简单的HTML,比如一个列可能包含一个String like:

String content = "Hello&nbsp;<strong>Word</strong><br>";

如果我使用 createParagraphOfText() 方法将此字符串放入列中:

Tc tableCell = factory.createTc();    
tableCell.getContent().add(
    wordMLPackage.getMainDocumentPart().createParagraphOfText(content)
);
tableRow.getContent().add(tableCell);

它在 Word 文档中按原样呈现(如预期):

Hello&nbsp;<strong>Word</strong><br>

我想要实现的是将 呈现的 HTML 放在文档中,以获得以下输出:

Hello Word


我在 Whosebug 和 Web 上进行了搜索,并尝试了几乎所有找到的示例,但信息非常零散,在更深入地挖掘之前,我想至少知道我是否正确方向.

我已经将 docx4j-ImportXHTML jar 添加到 Maven,但在文档中它指出内容必须是 格式良好的 X HTML,而我只有一堆文字和HTML混合在一起。

还有许多(少数)使用它的示例包括将现有的 XML 文件转换为 docx,而我很擅长手动完全创建 docx,只需要渲染一个包含 HTML 的单个字符串。这个模块有可能吗?

我也看到有other docx4j modules(例如xhtmlrenderer),但我不确定哪个是好的。

有人知道在迭代期间在 table(的单元格)中添加 HTML 块的正确程序吗?

您可以选择:

  • 自己将 (X)HTML 转换为 docx 内容,或者
  • 让 Word 来做

您自己动手可以更好地控制,并且意味着无需先在 Word 中打开 docx 即可进行下游处理(例如转换为 PDF)。

让 Word 执行此操作是 AlternativeFormatInputPart (altChunk) 方法。

如果可以的话,我的建议是自己动手。我建议您为此使用 docx4j-ImportXHTML。

I've added the docx4j-ImportXHTML jar to Maven, but in the docs it states that the content must be a well-formed XHTML, while I have only a bunch of text and HTML mixed together.

您可以使用 "tidy" 库之一转换为 XHTML。由于其中有很多,我们将您使用哪个以及如何配置它留给您。

only need to render a single String containing HTML. Is it possible with this module ?

ConvertInXHTMLFragment.java就是一个例子。

I've also seen that there are other docx4j modules (eg. xhtmlrenderer), but I'm not sure about which is the good one.

docx4j-ImportXHTML 依赖于此。

如果你有简单的 HTML 而不是 XHTML,比如

String content = "Hello&nbsp;<strong>Word</strong><br>";

解决方案是将您的 HTML 封装到 HTML 元素中,例如。一个 div:

String content = "<div>" + content + "</div>";

并手动替换未闭合的空元素,例如:

content = content.replaceAll("<br>", "<br/>");

此时,您可能会收到无法识别的 HTML 实体的错误,例如拉丁口音(&agrave; 等)。然后,您可以用带有 DTD 声明的 HTML 文档包围您的代码,而不是 div。故事结束。

工作示例

private void whatever(){

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    pkg = WordprocessingMLPackage.createPackage(PageSizePaper.A4,true);
    factory = Context.getWmlObjectFactory();

    Tbl table = factory.createTbl();
    for (Item item : Items){       
        Tr tableRow = factory.createTr();
        Tc tableCell = factory.createTc();

        /* This is the core of the problem */
        String content = wrapXHTML(item.getContent());
        List<Object> objects = importer.convert(wrapToXHTML(content), null);
        tableCell.getContent().addAll(objects);     
        /* problem solved */

        tableRow.getContent().add(tableCell);
        table.getContent().add(tableRow);
    }        
    pkg.getMainDocumentPart().addObject(table);
    pkg.save(baos);
}

private String wrapXHTML(String content) {
    content = content.replaceAll("<br>", "<br/>");
    /* ... other substitutions ... */

    return dtd + html + head + start + content + end;
}

private final static String dtd = 
                     "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\""
                     + " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
private final static String html = "<html xmlns=\"http://www.w3.org/1999/xhtml\">";
private final static String head = "<head></head>";
private final static String start = "<body><div>";
private final static String end = "</div></body></html>";

HTML 文本的格式应如下所示,在我的情况下 &nbsp; 不起作用,所以我删除了它。

  String content = "<html>Hello <strong>Word</strong><br></html>";

XHTML用于将html转换为xhtml

XHTMLImporter xHTMLImporter = new XHTMLImporterImpl(wordPackage);
        Tc tableCell = factory.createTc(); 

这是您需要在代码中进行的更改

tableCell.getContent().add(wordMLPackage.getMainDocumentPart().
          getContent().addAll(xHTMLImporter.convert(content, null)));
        tableRow.getContent().add(tableCell);

这段代码对我有用,请试试这个。