Aspose.Words Modelo de objetos de documento (DOM)
El Modelo de objetos de documento Aspose.Words (DOM) es una representación en memoria de un documento de Word. El Aspose.Words DOM le permite leer, manipular y modificar mediante programación el contenido y el formato de un documento de Word.
Esta sección describe las clases principales de Aspose.Words DOM y sus relaciones. Al usar las clases Aspose.Words DOM, puede obtener acceso programático a los elementos del documento y al formato.
Crear Árbol de Objetos de Documento
Cuando se lee un documento en el Aspose.Words DOM, se crea un árbol de objetos y los diferentes tipos de elementos del documento fuente tienen sus propios objetos de árbol DOM con varias propiedades.
Construir Árbol de Nodos de Documento
Cuando Aspose.Words lee un documento de Word en la memoria, crea objetos de diferentes tipos que representan varios elementos del documento. Cada ejecución de un texto, párrafo, tabla o sección es un nodo, e incluso el documento en sí mismo es un nodo. Aspose.Words define una clase para cada tipo de nodo de documento.
El árbol de documentos en Aspose.Words sigue el Patrón de Diseño Compuesto:
- En última instancia, todas las clases de nodo se derivan de la clase Node, que es la clase base en el Modelo de Objetos de documento Aspose.Words.
- Los nodos que pueden contener otros nodos, por ejemplo, Section o Paragraph, derivan de la clase CompositeNode, que a su vez deriva de la clase Node.
El diagrama proporcionado a continuación muestra la herencia entre clases de nodos del Modelo de Objetos de Documento Aspose.Words (DOM). Los nombres de las clases abstractas están en cursiva.

Node
.
Veamos un ejemplo. La siguiente imagen muestra un documento Microsoft Word con diferentes tipos de contenido.

Al leer el documento anterior en Aspose.Words DOM, se crea el árbol de objetos, como se muestra en el esquema a continuación.

Document, Section, Paragraph, Table, Shape, Run, y todas las demás elipses en el diagrama son Aspose.Words objetos que representan elementos del documento de Word.
Obtenga un Node
Tipo
Aunque la clase Node es suficiente para distinguir diferentes nodos entre sí, Aspose.Words proporciona la enumeración NodeType para simplificar algunas API tareas, como seleccionar nodos de un tipo específico.
El tipo de cada nodo se puede obtener utilizando la propiedad NodeType. Esta propiedad devuelve un valor de enumeración NodeType. Por ejemplo, un nodo de párrafo representado por la clase Paragraph devuelve NodeType.Paragraph, y un nodo de tabla representado por la clase Table devuelve NodeType.Table.
El siguiente ejemplo muestra cómo obtener un tipo de nodo usando la enumeración NodeType:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java | |
Document doc = new Document(); | |
// Returns NodeType.Document | |
int type = doc.getNodeType(); |
Navegación del Árbol de Documentos
Aspose.Words representa un documento como un árbol de nodos, lo que le permite navegar entre nodos. En esta sección se describe cómo explorar y navegar por el árbol de documentos en Aspose.Words.
Cuando abre el documento de muestra, presentado anteriormente, en el Explorador de documentos, el árbol de nodos aparece exactamente como está representado en Aspose.Words.

Relaciones de Nodos de Documento
Los nodos del árbol tienen relaciones entre ellos:
- Un nodo que contiene otro nodo es un parent.
- El nodo contenido en el nodo primario es un child. Nodo secundario del mismo padre son sibling nodos.
- El nodo root es siempre el nodo Document.
Los nodos que pueden contener otros nodos derivan de la clase CompositeNode y, en última instancia, todos los nodos derivan de la clase Node. Estas dos clases base proporcionan métodos y propiedades comunes para la navegación y modificación de la estructura de árbol.
El siguiente diagrama de objetos UML muestra varios nodos del documento de muestra y sus relaciones entre sí a través de las propiedades padre, hijo y hermano:

El Documento es Propietario del Nodo
Un nodo siempre pertenece a un documento en particular, incluso si acaba de crearse o eliminarse del árbol, porque las estructuras vitales de todo el documento, como los estilos y las listas, se almacenan en el nodo Document. Por ejemplo, no es posible tener un Paragraph sin un Document porque cada párrafo tiene un estilo asignado que se define globalmente para el documento. Esta regla se usa al crear nuevos nodos. Agregar un nuevo Paragraph directamente al DOM requiere que se pase un objeto de documento al constructor.
Al crear un nuevo párrafo usando DocumentBuilder, el constructor siempre tiene una clase Document vinculada a él a través de la propiedad DocumentBuilder.Document.
El siguiente ejemplo de código muestra que al crear cualquier nodo, siempre se define un documento que será el propietario del nodo:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java | |
// Open a file from disk. | |
Document doc = new Document(); | |
// Creating a new node of any type requires a document passed into the constructor. | |
Paragraph para = new Paragraph(doc); | |
// The new paragraph node does not yet have a parent. | |
System.out.println("Paragraph has no parent node: " + (para.getParentNode() == null)); | |
// But the paragraph node knows its document. | |
System.out.println("Both nodes' documents are the same: " + (para.getDocument() == doc)); | |
// The fact that a node always belongs to a document allows us to access and modify | |
// properties that reference the document-wide data such as styles or lists. | |
para.getParagraphFormat().setStyleName("Heading 1"); | |
// Now add the paragraph to the main text of the first section. | |
doc.getFirstSection().getBody().appendChild(para); | |
// The paragraph node is now a child of the Body node. | |
System.out.println("Paragraph has a parent node: " + (para.getParentNode() != null)); |
Nodo Padre
Cada nodo tiene un padre especificado por la propiedad ParentNode. Un nodo no tiene nodo padre, es decir, ParentNode es nulo, en los siguientes casos:
- El nodo acaba de crearse y aún no se ha agregado al árbol.
- El nodo se ha eliminado del árbol.
- Este es el nodo raíz Document que siempre tiene un nodo padre nulo.
Puede eliminar un nodo de su padre llamando al método Remove.El siguiente ejemplo de código muestra cómo acceder al nodo principal:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java | |
// Create a new empty document. It has one section. | |
Document doc = new Document(); | |
// The section is the first child node of the document. | |
Node section = doc.getFirstChild(); | |
// The section's parent node is the document. | |
System.out.println("Section parent is the document: " + (doc == section.getParentNode())); |
Nodos Secundarios
La forma más eficiente de acceder a los nodos secundarios de a CompositeNode es a través de las propiedades FirstChild y LastChild que devuelven el primer y el último nodo secundario, respectivamente. Si no hay nodos secundarios, estas propiedades devuelven null.
CompositeNode
Si un nodo no tiene hijos, la propiedad ChildNodes devuelve una colección vacía. Puede verificar si CompositeNode contiene nodos secundarios utilizando la propiedad HasChildNodes.
El siguiente ejemplo de código muestra cómo enumerar nodos secundarios inmediatos de un CompositeNode
usando el enumerador proporcionado por la colección ChildNodes
:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java | |
Document doc = new Document(dataDir + "Document.doc"); | |
Paragraph paragraph = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 0, true); | |
NodeCollection children = paragraph.getChildNodes(); | |
for (Node child : (Iterable<Node>) children) { | |
// Paragraph may contain children of various types such as runs, shapes and so on. | |
if (child.getNodeType() == NodeType.RUN) { | |
// Say we found the node that we want, do something useful. | |
Run run = (Run) child; | |
System.out.println(run.getText()); | |
} | |
} |
El siguiente ejemplo de código muestra cómo enumerar nodos secundarios inmediatos de un CompositeNode
usando acceso indexado:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java | |
Document doc = new Document(dataDir + "Document.doc"); | |
Paragraph paragraph = (Paragraph) doc.getChild(NodeType.PARAGRAPH, 0, true); | |
NodeCollection children = paragraph.getChildNodes(); | |
for (int i = 0; i < children.getCount(); i++) { | |
Node child = children.get(i); | |
// Paragraph may contain children of various types such as runs, shapes and so on. | |
if (child.getNodeType() == NodeType.RUN) { | |
// Say we found the node that we want, do something useful. | |
Run run = (Run) child; | |
System.out.println(run.getText()); | |
} | |
} |
Nodos Hermanos
Puede obtener el nodo que precede o sigue inmediatamente a un nodo en particular utilizando las propiedades PreviousSibling y NextSibling, respectivamente. Si un nodo es el último hijo de su padre, entonces la propiedad NextSibling es null. Por el contrario, si el nodo es el primer hijo de su padre, la propiedad PreviousSibling es null.
El siguiente ejemplo de código muestra cómo visitar de manera eficiente todos los nodos secundarios directos e indirectos de un nodo compuesto:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java | |
public static void main(String[] args) throws Exception { | |
String dataDir = Utils.getSharedDataDir(ChildNodes.class) + "DocumentObjectModel/"; | |
recurseAllNodes(dataDir); | |
} | |
public static void recurseAllNodes(String dataDir) throws Exception { | |
// Open a document | |
Document doc = new Document(dataDir + "Node.RecurseAllNodes.doc"); | |
// Invoke the recursive function that will walk the tree. | |
traverseAllNodes(doc); | |
} | |
/** | |
* A simple function that will walk through all children of a specified node | |
* recursively and print the type of each node to the screen. | |
*/ | |
public static void traverseAllNodes(CompositeNode parentNode) throws Exception { | |
// This is the most efficient way to loop through immediate children of a node. | |
for (Node childNode = parentNode.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()) { | |
// Do some useful work. | |
System.out.println(Node.nodeTypeToString(childNode.getNodeType())); | |
// Recurse into the node if it is a composite node. | |
if (childNode.isComposite()) | |
traverseAllNodes((CompositeNode) childNode); | |
} | |
} |
Acceso escrito a Nodos Secundarios y Primarios
Hasta ahora, hemos discutido las propiedades que devuelven uno de los tipos base: Node o CompositeNode. Pero a veces hay situaciones en las que es posible que deba convertir valores a una clase de nodo específica, como Run o Paragraph. Es decir, no puede evitar por completo la fundición cuando trabaja con el Aspose.Words DOM, que es compuesto.
Para reducir la necesidad de conversión, la mayoría de las clases Aspose.Words proporcionan propiedades y colecciones que proporcionan acceso fuertemente tipado. Hay tres patrones básicos de acceso mecanografiado:
- Un nodo primario expone las propiedades FirstXXX y LastXXX escritas. Por ejemplo, Document tiene propiedades FirstSection y LastSection. De manera similar, Table tiene propiedades como FirstRow, LastRow y otras.
- Un nodo primario expone una colección tipificada de nodos secundarios, como Document.Sections, Body.Paragraphs y otros.
- Un nodo secundario proporciona acceso escrito a su padre, como Run.ParentParagraph, Paragraph.ParentSection y otros.
Las propiedades escritas son simplemente accesos directos útiles que a veces brindan un acceso más fácil que las propiedades genéricas heredadas de Node.ParentNode y CompositeNode.FirstChild.
El siguiente ejemplo de código muestra cómo usar propiedades escritas para acceder a nodos del árbol de documentos:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java | |
Document doc = new Document(); | |
// Quick typed access to the first child Section node of the Document. | |
Section section = doc.getFirstSection(); | |
// Quick typed access to the Body child node of the Section. | |
Body body = section.getBody(); | |
// Quick typed access to all Table child nodes contained in the Body. | |
TableCollection tables = body.getTables(); | |
for (Table table : tables) { | |
// Quick typed access to the first row of the table. | |
if (table.getFirstRow() != null) | |
table.getFirstRow().remove(); | |
// Quick typed access to the last row of the table. | |
if (table.getLastRow() != null) | |
table.getLastRow().remove(); | |
} |