Добавить HTML-строку в документ OpenXML (*.docx)

Я пытаюсь использовать библиотеку 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);

Очевидно, что в этом примере я не добавил altChunk, но я попытался добавить его повсюду - в run, paragraph, body и т.д. В любом случае я не могу открыть файл docx в Word 2010.

Это делает меня немного сумасшедшим, потому что кажется, что это должно быть просто (я признаю, что я не полностью понимаю вещь "AltChunk" ). Поблагодарили бы за любую помощь.

Боковое примечание. Я обнаружил, что это было интересно, и я не знаю, действительно ли это проблема или нет, этот ответ, в котором говорится, что AltChunk развращает файл при работе с MemoryStream. Кто-нибудь может подтвердить, что это/неверно?

Ответ 1

Я могу воспроизвести ошибку "... есть проблема с контентом", используя неполный HTML-документ в качестве содержимого части импорта альтернативного формата. Например, если вы используете следующий фрагмент HTML <h1>HELLO</h1> MS Word не может открыть документ.

В приведенном ниже коде показано, как добавить AlternativeFormatImportPart в документ слова. (Я тестировал код с 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);
}

В соответствии с спецификацией Office OpenXML действительные родительские элементы для Элемент w:altChunk body, comment, docPartBody, endnote, footnote, ftr, hdr and tc. Итак, я добавил элемент w:altChunk в элемент body.

Для получения дополнительной информации о элементе w:altChunk см. эту ссылку MSDN.

ИЗМЕНИТЬ

Как указано @user2945722, чтобы убедиться, что правильная версия библиотеки OpenXml интерпретирует массив байтов как UTF-8, вы должны добавить преамбулу UTF-8. Это можно сделать следующим образом:

MemoryStream ms = new MemoryStream(new UTF8Encoding(true).GetPreamble().Concat(Encoding.UTF8.GetBytes(htmlEncodedString)).ToArray()

Это предотвратит показ вашего é как à © 's, ваш ä как ä и т.д.

Ответ 2

Здесь была та же проблема, но совершенно другая причина. Стоит попробовать, если принятое решение не поможет. Попробуйте закрыть файл после сохранения. В моем случае это была разница между коррумпированным и чистым файлом docx. Как ни странно, большинство других операций работают только с сохранением() и выходом программы.

String cid = "chunkid";
WordprocessingDocument document = WordprocessingDocument.Open("somefile.docx", true);
Body body = document.MainDocumentPart.Document.Body;
MemoryStream ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("<html><head></head><body>hi</body></html>"));
AlternativeFormatImportPart formatImportPart = document.MainDocumentPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Html, cid);
formatImportPart.FeedData(ms);
AltChunk altChunk = new AltChunk();
altChunk.Id = cid;
document.MainDocumentPart.Document.Body.Append(altChunk);
document.MainDocumentPart.Document.Save();
// here the magic!
document.Close();