Aspose.Words Объектная модель документа (DOM)
Объектная модель документа Aspose.Words (DOM) - это представление документа Word в памяти. Объектная модель документа Aspose.Words DOM позволяет программно считывать содержимое и форматирование документа Word, манипулировать ими и изменять их.
В этом разделе описываются основные классы Aspose.Words DOM и их взаимосвязи. Используя классы Aspose.Words DOM, вы можете получить программный доступ к элементам документа и форматированию.
Создайте дерево объектов Document
Когда документ считывается в Aspose.Words DOM, то строится дерево объектов, и различные типы элементов исходного документа имеют свои собственные объекты дерева DOM с различными свойствами.
Построение дерева узлов документа
Когда Aspose.Words считывает документ Word в память, он создает объекты разных типов, которые представляют различные элементы документа. Каждый фрагмент текста, абзац, таблица или раздел является узлом, и даже сам документ является узлом. Aspose.Words определяет класс для каждого типа узла документа.
Дерево документа в Aspose.Words соответствует шаблону составного проектирования:
- Все классы узлов в конечном счете являются производными от класса Node, который является базовым классом в объектной модели документа Aspose.Words.
- Узлы, которые могут содержать другие узлы, например, Section или Paragraph, являются производными от класса CompositeNode, который, в свою очередь, является производным от класса Node.
На приведенной ниже диаграмме показано наследование между узловыми классами объектной модели документа Aspose.Words (DOM). Названия абстрактных классов выделены курсивом.
Давайте рассмотрим пример. На следующем рисунке показан документ Microsoft Word с различными типами содержимого.
При чтении приведенного выше документа в Aspose.Words DOM создается дерево объектов, как показано на схеме ниже.
Document, Section, Paragraph, Table, Shape, Run, а все остальные эллипсы на диаграмме являются объектами Aspose.Words, представляющими элементы документа Word.
Получаем Node
Тип
Хотя класса Node достаточно, чтобы отличать разные узлы друг от друга, Aspose.Words предоставляет перечисление NodeType для упрощения некоторых задач API, таких как выбор узлов определенного типа.
Тип каждого узла можно определить с помощью свойства Node.node_type. Это свойство возвращает значение перечисления NodeType. Например, узел абзаца, представленный классом Paragraph, возвращает значение NodeType.PARAGRAPH, а узел таблицы, представленный классом Table, возвращает значение NodeType.TABLE.
В следующем примере показано, как получить тип узла с помощью перечисления NodeType:
Навигация по дереву документов
Aspose.Words представляет документ в виде дерева узлов, которое позволяет перемещаться между узлами. В этом разделе описывается, как исследовать дерево документов и перемещаться по нему в Aspose.Words.
Когда вы открываете образец документа, представленный ранее, в проводнике документов, дерево узлов отображается точно так, как оно представлено в Aspose.Words.
Взаимосвязи узлов документа
Узлы в дереве имеют взаимосвязи между собой:
- Узел, содержащий другой узел, является parent.
- Узел, содержащийся в родительском узле, является child. Дочерними узлами того же родительского узла являются sibling узлов.
- Узел root всегда является узлом Document.
Узлы, которые могут содержать другие узлы, являются производными от класса CompositeNode, а все узлы, в конечном счете, являются производными от класса Node. Эти два базовых класса предоставляют общие методы и свойства для навигации и модификации древовидной структуры.
На следующей диаграмме объектов UML показаны несколько узлов образца документа и их связи друг с другом с помощью родительских, дочерних и родственных свойств:
Документ является владельцем узла
Узел всегда принадлежит определенному документу, даже если он был только что создан или удален из дерева, поскольку важные структуры всего документа, такие как стили и списки, хранятся в узле Document. Например, невозможно использовать Paragraph без Document, потому что каждому абзацу присвоен стиль, который определен глобально для документа. Это правило используется при создании любых новых узлов. Для добавления нового Paragraph непосредственно к DOM требуется объект document, переданный конструктору.
При создании нового абзаца с помощью DocumentBuilder у конструктора всегда есть класс Document, связанный с ним через свойство DocumentBuilder.document.
В следующем примере кода показано, что при создании любого узла всегда определяется документ, которому будет принадлежать этот узел:
Родительский узел
У каждого узла есть родительский узел, указанный с помощью свойства parent_node. Узел не имеет родительского узла, то есть parent_node равно None в следующих случаях:
- Узел только что был создан и еще не был добавлен в дерево.
- Узел был удален из дерева.
- Это корневой узел Document, у которого всегда нет родительского узла.
Вы можете удалить узел из родительского, вызвав метод Node.remove.В следующем примере кода показано, как получить доступ к родительскому узлу:
Дочерние узлы
Наиболее эффективный способ получить доступ к дочерним узлам CompositeNode - это использовать свойства first_child и last_child, которые возвращают первый и последний дочерние узлы соответственно. Если дочерних узлов нет, эти свойства возвращают значение None.
CompositeNode также предоставляет коллекцию get_child_nodes, обеспечивающую индексированный или перечислимый доступ к дочерним узлам. Метод get_child_nodes возвращает текущую коллекцию узлов, что означает, что всякий раз, когда документ изменяется, например, когда узлы удаляются или добавляются, коллекция get_child_nodes автоматически обновляется.
Если у узла нет дочерних узлов, то метод get_child_nodes возвращает пустую коллекцию. Вы можете проверить, содержит ли CompositeNode какие-либо дочерние узлы, используя свойство has_child_nodes.
В следующем примере кода показано, как перечислить непосредственные дочерние узлы CompositeNode, используя перечислитель, предоставляемый коллекцией get_child_nodes:
Родственные узлы
Вы можете получить узел, который непосредственно предшествует определенному узлу или следует за ним, используя свойства previous_sibling и next_sibling соответственно. Если узел является последним дочерним по отношению к своему родительскому узлу, то свойство next_sibling равно None. И наоборот, если узел является первым дочерним по отношению к своему родительскому элементу, то свойство previous_sibling равно None.
В следующем примере кода показано, как эффективно посещать все прямые и косвенные дочерние узлы составного узла:
Типизированный доступ к дочернему и родительскому узлам
До сих пор мы обсуждали свойства, которые возвращают один из базовых типов – Node или CompositeNode. Но иногда возникают ситуации, когда может потребоваться привести значения к определенному классу узлов, например Run или Paragraph. То есть, вы не можете полностью отказаться от приведения при работе с Aspose.Words DOM, который является составным.
Чтобы уменьшить необходимость в приведении в соответствие, большинство классов Aspose.Words предоставляют свойства и коллекции, которые обеспечивают строго типизированный доступ. Существует три основных шаблона типизированного доступа:
- Родительский узел предоставляет типизированные свойства first_XXX и last_XXX. Например, у Document есть свойства first_section и last_section. Аналогично, у Table есть такие свойства, как first_row, last_row и другие.
- Родительский узел предоставляет типизированную коллекцию дочерних узлов, таких как Document.sections, Body.paragraphs и другие.
- Дочерний узел предоставляет типизированный доступ к своему родительскому узлу, такой как Run.parent_paragraph, Paragraph.parent_section и другие.
Типизированные свойства - это просто полезные ярлыки, которые иногда обеспечивают более легкий доступ, чем общие свойства, унаследованные от Node.parent_node и CompositeNode.first_child.
В следующем примере кода показано, как использовать типизированные свойства для доступа к узлам дерева документов: