Aspose.Words Объектная модель документа (DOM)

Объектная модель документа Aspose.Words (DOM) - это представление документа Word в памяти. Aspose.Words DOM позволяет программно считывать содержимое и форматирование документа Word, манипулировать ими и изменять их.

В этом разделе описываются основные классы Aspose.Words DOM и их взаимосвязи. Используя классы Aspose.Words DOM, вы можете получить программный доступ к элементам документа и форматированию.

Создать дерево объектов документа

Когда документ считывается в Aspose.Words DOM, создается дерево объектов, и различные типы элементов исходного документа имеют свои собственные объекты дерева DOM с различными свойствами.

Построение дерева узлов документа

Когда Aspose.Words считывает документ Word в память, он создает объекты разных типов, представляющие различные элементы документа. Каждый фрагмент текста, абзац, таблица или раздел является узлом, и даже сам документ является узлом. Aspose.Words определяет класс для каждого типа узла документа.

Дерево документа в Aspose.Words соответствует шаблону составного проектирования:

  • Все классы узлов в конечном счете являются производными от класса Node, который является базовым классом в объектной модели документа Aspose.Words.
  • Узлы, которые могут содержать другие узлы, например, Section или Paragraph, являются производными от класса CompositeNode, который, в свою очередь, является производным от класса Node.

На приведенной ниже диаграмме показано наследование между узловыми классами объектной модели документа (DOM) Aspose.Words. Названия абстрактных классов выделены курсивом.

aspose-words-dom-aspose-words-cpp

Давайте рассмотрим пример. На следующем рисунке показан документ Microsoft Word с различными типами содержимого.

document-example-aspose-words-cpp

При чтении приведенного выше документа в Aspose.Words DOM создается дерево объектов, как показано на схеме ниже.

document-example-dom-aspose-words-cpp

Document, Section, Paragraph, Table, Shape, Run, а все остальные эллипсы на диаграмме являются объектами Aspose.Words, представляющими элементы документа Word.

Получаем Node Тип

Хотя класса Node достаточно, чтобы отличать разные узлы друг от друга, Aspose.Words предоставляет перечисление NodeType для упрощения некоторых задач API, таких как выбор узлов определенного типа.

Тип каждого узла можно определить с помощью свойства NodeType. Это свойство возвращает значение NodeType enumeration value. For example, a paragraph node represented by the Paragraph class returns NodeType.Paragraph, а узел таблицы - значение Table class returns NodeType.Table.

В следующем примере показано, как получить тип узла с помощью перечисления NodeType:

Навигация по дереву документов

Aspose.Words представляет документ в виде дерева узлов, которое позволяет перемещаться между узлами. В этом разделе описывается, как исследовать дерево документов и перемещаться по нему в Aspose.Words.

Когда вы открываете образец документа, представленный ранее, в проводнике документов, дерево узлов отображается точно так, как оно представлено в Aspose.Words.

document-in-document-explorer-aspose-words-cpp

Связи узлов документа

Узлы в дереве имеют взаимосвязи между собой:

  • Узел, содержащий другой узел, является parent.
  • Узел, содержащийся в родительском узле, является child. Дочерними узлами того же родительского узла являются sibling узлы.
  • Узел root всегда является узлом Document.

Узлы, которые могут содержать другие узлы, являются производными от класса CompositeNode, а все узлы, в конечном счете, являются производными от класса Node. Эти два базовых класса предоставляют общие методы и свойства для навигации и модификации древовидной структуры.

На следующей диаграмме объектов UML показаны несколько узлов образца документа и их связи друг с другом с помощью родительских, дочерних и родственных свойств:

document-nodes-relationships-aspose-words-cpp

Документ является владельцем узла

Узел всегда принадлежит определенному документу, даже если он был только что создан или удален из дерева, поскольку важные структуры всего документа, такие как стили и списки, хранятся в узле Document. Например, невозможно использовать Paragraph без Document, потому что каждому абзацу присвоен стиль, который определен глобально для документа. Это правило используется при создании любых новых узлов. Для добавления нового Paragraph непосредственно в DOM требуется объект document, переданный конструктору.

При создании нового абзаца с помощью DocumentBuilder у конструктора всегда есть класс Document, связанный с ним через свойство DocumentBuilder.Document.

В следующем примере кода показано, что при создании любого узла всегда определяется документ, которому будет принадлежать этот узел:

Родительский узел

У каждого узла есть родительский узел, указанный с помощью свойства ParentNode. Узел не имеет родительского узла, то есть значение ParentNode равно null в следующих случаях:

  • Узел только что был создан и еще не был добавлен в дерево.
  • Узел был удален из дерева.
  • Это корневой узел Document, который всегда имеет нулевой родительский узел.

Вы можете удалить узел из родительского, вызвав метод Remove.В следующем примере кода показано, как получить доступ к родительскому узлу:

Дочерние узлы

Наиболее эффективный способ получить доступ к дочерним узлам CompositeNode - это использовать свойства FirstChild и LastChild, которые возвращают первый и последний дочерние узлы соответственно. Если дочерних узлов нет, эти свойства возвращают значение null.

Составной узел

Если узел не имеет дочерних узлов, то свойство ChildNodes возвращает пустую коллекцию. Вы можете проверить, содержит ли CompositeNode дочерние узлы, используя свойство HasChildNodes.

В следующем примере кода показано, как перечислить непосредственные дочерние узлы CompositeNode, используя перечислитель, предоставляемый коллекцией ChildNodes:

В следующем примере кода показано, как перечислить непосредственные дочерние узлы CompositeNode, используя индексированный доступ:

Родственные узлы

Вы можете получить узел, который непосредственно предшествует определенному узлу или следует за ним, используя свойства PreviousSibling и NextSibling соответственно. Если узел является последним дочерним по отношению к своему родительскому узлу, то свойство NextSibling равно null. И наоборот, если узел является первым дочерним по отношению к своему родительскому элементу, то свойство PreviousSibling равно null.

В следующем примере кода показано, как эффективно посещать все прямые и косвенные дочерние узлы составного узла:

Типизированный доступ к дочерним и родительским узлам

До сих пор мы обсуждали свойства, которые возвращают один из базовых типов – Node или CompositeNode. Но иногда возникают ситуации, когда может потребоваться привести значения к определенному классу узлов, например Run или Paragraph. То есть вы не можете полностью отказаться от кастинга при работе с Aspose.Words DOM, который является составным.

Чтобы уменьшить необходимость в приведении в соответствие, большинство классов Aspose.Words предоставляют свойства и коллекции, которые обеспечивают строго типизированный доступ. Существует три основных шаблона типизированного доступа:

  • Родительский узел предоставляет типизированные свойства FirstXXX и LastXXX. Например, у Document есть свойства FirstSection и LastSection. Аналогично, у Table есть такие свойства, как FirstRow, LastRow и другие.
  • Родительский узел предоставляет типизированную коллекцию дочерних узлов, таких как Document.Sections, Body.Paragraphs и другие.
  • Дочерний узел предоставляет типизированный доступ к своему родительскому узлу, такой как Run.ParentParagraph, Paragraph.ParentSection и другие.

Типизированные свойства - это просто полезные ярлыки, которые иногда обеспечивают более легкий доступ, чем общие свойства, унаследованные от Node.ParentNode и CompositeNode.FirstChild.

В следующем примере кода показано, как использовать типизированные свойства для доступа к узлам дерева документов: