Document.Body.Descendants <SdtBlock>() не возвращает все элементы * sdt * - PullRequest
0 голосов
/ 24 января 2020

Я пытаюсь найти все SdtElement в документе Word. Я использовал следующий код:

using (var wordDoc = WordprocessingDocument.Open(FilePath, true))
{
    var docSdts = wordDoc.MainDocumentPart.Document.Descendants<SdtElement>();
    // MainDocumentPart.Document.Body.Descendants<SdtElement>(); also used but same result

    MainDocumentPart mainPart = wordDoc.MainDocumentPart;
    List<SdtBlock> sdtList = mainPart.Document.Body.Descendants<SdtBlock>().ToList();

    // process all sdt
}

Проблема заключается в том, что приведенный выше код не возвращает все элементы SdtElements из файла. В одном документе имеется 19 SdtElements, но он возвращает только 7.

Согласно документу метод Descendants должен возвращать элементы со всех уровней:

Elements find только те элементы, которые являются прямыми потомками, то есть непосредственными детьми. vs Потомки находит детей на любом уровне, то есть детей, внуков и т. д. c ...

Одна наблюдаемая вещь была только sdt под body , para и ячейки таблицы возвращаются, но когда sdt меньше para внутри ячейка таблицы , она не возвращается.

Я пробовал код из http://www.ericwhite.com/blog/iterating-through-all-content-controls-in-an-open-xml-wordprocessingml-document/ и других подобных статей.

Как получить все sdt элементы всего документа независимо от уровня вложенности?

1 Ответ

1 голос
/ 24 января 2020

SdtElement - базовый класс для других элементов sdt:

  • SdtBlock
  • SdtCell
  • SdtRow
  • SdtRun
  • SdtRun Ruby

(источник: https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.sdtelement?view=openxml-2.8.1)

Вы пытаетесь получить только SdtBlock элементов:

List<SdtBlock> sdtList = mainPart.Document.Body.Descendants<SdtBlock>().ToList();

Если вы хотите получить все SdtElements, вы должны изменить его на:

List<SdtElement> sdtList = mainPart.Document.Body.Descendants<SdtElement>().ToList();

Обратите внимание, что SdtElements также может быть в других частях WordprocessingDocument, например:

В этом случае вам следует выполнить итерацию по всем этим частям, например:

List<SdtElement> sdtList = mainPart.Document.Body.Descendants<SdtElement>().ToList();
foreach(var part in mainPart.Document.HeaderParts)
{
   sdtList.AddRange(part.Header.Descedants<SdtElement>());
}
foreach(var part in mainPart.Document.FooterParts)
{
   sdtList.AddRange(part.Footer.Descedants<SdtElement>());
}
...