【问题标题】:How to preserve the HTML when creating a .docx with docx4j?使用 docx4j 创建 .docx 时如何保留 HTML?
【发布时间】:2015-01-27 17:35:45
【问题描述】:

我今天开始使用 docx4j;

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

这个内容里面有简单的HTML,例如一列可能包含这样的字符串:

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,以获得以下输出:

你好单词


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

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

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

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

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

【问题讨论】:

  • 您是否尝试过使用AlternativeFormatInputPart
  • 谢谢,我现在就试试。第二个是我正在尝试的,在继续之前我在这里停下来询问,因为我不能保证我的源代码是 XHTML,也不能保证格式正确......除了打开/关闭标签,我可以假设它是正确嵌套的。因此,如果我得到
    ,那是完全有效的 HTML5,它会因为缺少 void 元素自闭合斜线而中断?
  • @Ascalonian 我尝试过不更改内容,但它按预期失败,因为它不是有效的 XHTML,引发org.xml.sax.SAXParseException: Content is not allowed in prolog. 我现在尝试AlternativeFormatInputPart 方式并让你知道跨度>
  • 期待了解:-)

标签: java escaping docx4j html-escape-characters html-escape


【解决方案1】:

您可以选择:

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

自己动手可以为您提供更大的控制权,这意味着无需先在 Word 中打开 docx 即可进行下游处理(例如转换为 PDF)。

让 Word 来做是 AlternativeFormatInputPart (altChunk) 方法。

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

我已将 docx4j-ImportXHTML jar 添加到 Maven,但在文档中 声明内容必须是格式正确的 XHTML,而我只有 一堆文本和 HTML 混合在一起。

您可以使用其中一种“整洁”的库来转换为 XHTML。由于其中有很多,我们将由您决定使用哪个以及如何配置它。

只需要渲染一个包含 HTML 的字符串。这个模块可以吗?

ConvertInXHTMLFragment.java 就是一个例子。

我还看到还有其他 docx4j 模块(例如 xhtmlrenderer),但我不确定哪个是好的。

docx4j-ImportXHTML 依赖于此。

【讨论】:

  • 很好的答案!您能否解释一下在构建表格期间是否(以及如何)可以使用 docx4j-importXHTML 方法?非常感谢
  • XHTMLImporter.convert 返回 List,因此您可以使用 addAll 将这些对象添加到表格单元格的内容列表中。
  • 它正在工作! TBH,我本能地尝试了 TableCell 的.addAll()ImportXHTML.convert() 方法的结果在较早的尝试中,但我忘记将我的内容包含在&lt;div&gt;&lt;/div&gt; 中以使其有效,得到不言而喻的错误......太天真了:) 今天,它抱怨未解决的&amp;agrave;,所以我用 XHTML 1.0 过渡 DTD 将我的内容(每个单元格的)包含在整个 XHTML 页面中。现在它生成了文档,但它去掉了拉丁重音符号(à 是 à)。顺便说一句,我真的快结束了。 100% 的时候我也会提供答案,再次感谢您!
【解决方案2】:

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

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

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

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

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

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

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

工作示例

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>";

【讨论】:

    【解决方案3】:

    HTML 文本的格式应如下所示,在我的情况下,&amp;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);
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-26
      • 2015-03-21
      • 2014-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-14
      相关资源
      最近更新 更多