将HTML字符串添加到OpenXML(*.docx)文档

Jas*_*Cav 19 c# openxml openxml-sdk

我正在尝试使用Microsoft的OpenXML 2.5库来创建OpenXML文档.一切都很好,直到我尝试在我的文档中插入HTML字符串.我已经浏览了网页,这是我到目前为止所提出的内容(剪切到我遇到问题的部分):

Paragraph paragraph = new Paragraph();
Run run = new Run();

string altChunkId = "id1";
AlternativeFormatImportPart chunk =
       document.MainDocumentPart.AddAlternativeFormatImportPart(
           AlternativeFormatImportPartType.Html, altChunkId);
chunk.FeedData(new MemoryStream(Encoding.UTF8.GetBytes(ioi.Text)));
AltChunk altChunk = new AltChunk { Id = altChunkId };

run.AppendChild(new Break());

paragraph.AppendChild(run);
body.AppendChild(paragraph);
Run Code Online (Sandbox Code Playgroud)

显然,我在这个例子中并没有实际添加altChunk,但我尝试将它附加到任何地方 - 运行,段落,正文等.在任何情况下,我都无法打开Word 2010中的docx文件.

这让我有点疯狂,因为它看起来应该是直截了当的(我承认我并没有完全理解AltChunk"的事情").非常感谢任何帮助.

旁注:我发现有一件事很有意思,我不知道它是否真的是一个问题,这个响应表明AltChunk在使用MemoryStream工作时会破坏文件.任何人都能证实这是/不是真的吗?

Han*_*ans 20

我可以通过使用不完整的HTML文档作为替代格式导入部分的内容来重现错误"......内容存在问题".例如,如果您使用以下HTML代码段,则<h1>HELLO</h1> MS Word无法打开该文档.

下面的代码显示了如何添加AlternativeFormatImportPart到word文档.(我用MS Word 2013测试了代码).

using (WordprocessingDocument doc = WordprocessingDocument.Open(@"test.docx", true))
{
  string altChunkId = "myId";
  MainDocumentPart mainDocPart = doc.MainDocumentPart;

  var run = new Run(new Text("test"));
  var p = new Paragraph(new ParagraphProperties(
       new Justification() { Val = JustificationValues.Center }),
                     run);

  var body = mainDocPart.Document.Body;
  body.Append(p);        

  MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes("<html><head></head><body><h1>HELLO</h1></body></html>"));

  // Uncomment the following line to create an invalid word document.
  // MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes("<h1>HELLO</h1>"));

  // Create alternative format import part.
  AlternativeFormatImportPart formatImportPart =
     mainDocPart.AddAlternativeFormatImportPart(
        AlternativeFormatImportPartType.Html, altChunkId);
  //ms.Seek(0, SeekOrigin.Begin);

  // Feed HTML data into format import part (chunk).
  formatImportPart.FeedData(ms);
  AltChunk altChunk = new AltChunk();
  altChunk.Id = altChunkId;

  mainDocPart.Document.Body.Append(altChunk);
}
Run Code Online (Sandbox Code Playgroud)

根据Office OpenXML规范,元素的有效父元素 w:altChunkbody, comment, docPartBody, endnote, footnote, ftr, hdr and tc.所以,我已经添加w:altChunk了body元素.

有关该w:altChunk元素的更多信息,请参阅此MSDN链接.

编辑

正如@ user2945722所指出的,为了确保OpenXml库correctlty将字节数组解释为UTF-8,您应该添加UTF-8前导码.这可以这样做:

MemoryStream ms = new MemoryStream(new UTF8Encoding(true).GetPreamble().Concat(Encoding.UTF8.GetBytes(htmlEncodedString)).ToArray()
Run Code Online (Sandbox Code Playgroud)

这样可以防止你的é被rendered,your,ä's等等.

  • 在将字节数组传递给内存流之前,应考虑将UTF8 BOM添加到字节数组中.这有助于我的场景,docx文件无法正确显示某些UTF8字符.像这样的东西 - `byte [] utf8Bom = new UTF8Encoding(true).GetPreamble();`然后将它添加到"GetBytes"结果中 (3认同)