Aspose.Words Document Object Model (DOM)

W Aspose.Words Document Object Model (DOM) jest in- memoriałową reprezentacją dokumentu Word. W Aspose.Words DOM pozwala programowo czytać, manipulować i modyfikować zawartość i formatowanie dokumentu Word.

Niniejsza sekcja opisuje główne klasy Aspose.Words DOM i ich związki. Używając Aspose.Words DOM zajęcia, można uzyskać dostęp programowy do elementów dokumentów i formatowanie.

Utwórz dokument Drzewo obiektów

Kiedy dokument jest odczytywany do Aspose.Words DOM, > Następnie powstaje drzewo obiektowe i różne rodzaje elementów dokumentu źródłowego mają swoje własne DOM obiekty drzewne o różnych właściwościach.

Zbuduj drzewo węzłów dokumentów

Kiedy Aspose.Words odczyt dokumentu Word do pamięci, tworzy obiekty różnych typów, które reprezentują różne elementy dokumentu. Każdy ciąg tekstu, paragrafu, tabeli lub sekcji jest węzłem, a nawet sam dokument jest węzłem. Aspose.Words definiuje klasę dla każdego typu węzła dokumentu.

Drzewo dokumentów w Aspose.Words następujące wzory konstrukcyjne kompozytowe:

  • Wszystkie klasy węzłów ostatecznie pochodzą z Node klasa, która jest klasa podstawowa w Aspose.Words Document Object Model.
  • Węzły, które mogą zawierać inne węzły, na przykład, Section lub Paragraph, pochodzą z CompositeNode klasy, która z kolei pochodzi z Node Klasa.

Schemat przedstawiony poniżej pokazuje dziedziczenie między klasami węzłów Aspose.Words Document Object Model (DOM). Nazwy klas abstrakcyjnych są po włosku.

aspose-words-dom

Spójrzmy na przykład. Poniższy obrazek pokazuje Microsoft Word dokument z różnymi rodzajami treści.

document-example

Podczas czytania powyższego dokumentu do Aspose.Words DOM, drzewo obiektów jest tworzone, jak pokazano w schemacie poniżej.

document-example-dom

Document, Section, Paragraph, Table, Shape, Run, i wszystkie inne elipsy na diagramie są Aspose.Words obiekty, które reprezentują elementy dokumentu Word.

Pobierz Node Rodzaj

Chociaż Node klasa jest wystarczająca do odróżnienia różnych węzłów od siebie, Aspose.Words zapewnia NodeType wyliczenie w celu uproszczenia niektórych API zadania takie jak wybór węzłów określonego typu.

Typ każdego węzła można uzyskać za pomocą NodeType nieruchomości. Ta właściwość zwraca a NodeType wartość wyliczenia. Na przykład, węzeł paragrafu reprezentowany przez Paragraph zwroty klasy NodeType.Paragraphoraz węzeł stołowy reprezentowany przez Table zwroty klasy NodeType.Table.

Poniższy przykład pokazuje jak uzyskać typ węzła za pomocą NodeType wyliczenie:

// 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();

Nawigacja drzewa dokumentów

Aspose.Words reprezentuje dokument jako drzewo węzłów, które pozwala poruszać się między węzłami. Ta sekcja opisuje, jak badać i nawigować drzewo dokumentów w Aspose.Words.

Po otwarciu przykładowego dokumentu, przedstawionego wcześniej, w dokumencie Document Explorer drzewo węzła pojawia się dokładnie tak, jak jest reprezentowane w Aspose.Words.

document-in-document-explorer

Powiązania węzła dokumentu

Węzły w drzewie mają relacje między nimi:

  • Węzeł zawierający inny węzeł jest parent.
  • Węzeł zawarty w węźle macierzystym jest child. Węzły dziecięce tego samego rodzica są sibling węzły.
  • root węzeł jest zawsze Document węzeł.

Węzły, które mogą zawierać inne węzły pochodzą z CompositeNode klasy, i wszystkie węzły ostatecznie pochodzą z Node Klasa. Te dwie klasy bazowe zapewniają wspólne metody i właściwości nawigacji i modyfikacji struktury drzew.

Poniższy diagram obiektu UML pokazuje kilka węzłów dokumentu próbki i ich relacje ze sobą poprzez właściwości rodzica, dziecka i rodzeństwa:

document-nodes-relationships

Dokument jest właścicielem węzła

Węzeł zawsze należy do konkretnego dokumentu, nawet jeśli został on po prostu stworzony lub usunięty z drzewa, ponieważ istotne struktury dokumentów, takie jak style i listy są przechowywane w Document węzeł. Na przykład, nie jest możliwe posiadanie Paragraph bez Document ponieważ każdy akapit ma przypisany styl zdefiniowany globalnie dla dokumentu. Zasada ta jest używana przy tworzeniu nowych węzłów. Dodawanie nowego Paragraph bezpośrednio do DOM wymaga obiektu dokumentu przekazanego konstruktorowi.

Przy tworzeniu nowego akapitu DocumentBuilder, budowniczy zawsze ma Document klasy związane z nim poprzez DocumentBuilder.Document nieruchomości.

Poniższy przykład kodu pokazuje, że przy tworzeniu dowolnego węzła zawsze jest zdefiniowany dokument, który będzie właścicielem węzła:

// 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));

Węzeł rodzica

Każdy węzeł ma określony przez ParentNode nieruchomości. Węzeł nie ma węzła macierzystego. ParentNode jest zerowa, w następujących przypadkach:

  • Węzeł został właśnie stworzony i nie został jeszcze dodany do drzewa.
  • Węzeł został usunięty z drzewa.
  • To jest pierwiastek Document węzeł, który zawsze ma zerowy węzeł macierzysty.

Możesz usunąć węzeł z jego rodzica przez wywołanie Remove Metoda. Poniższy przykład kodu pokazuje jak uzyskać dostęp do węzła macierzystego:

// 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()));

Węzły dziecięce

Najbardziej skuteczny sposób dostępu do węzłów dziecięcych CompositeNode jest za pośrednictwem FirstChild oraz LastChild właściwości, które zwracają odpowiednio pierwsze i ostatnie węzły dziecięce. Jeśli nie ma węzłów dziecięcych, te właściwości wracają null.

CompositeNode zapewnia również ChildNodes kolekcja umożliwiająca dostęp do węzłów dziecięcych z indeksem lub numeracją. W ChildNodes właściwość jest zbiór na żywo węzłów, co oznacza, że w każdym przypadku zmiany dokumentu, takich jak gdy węzły są usuwane lub dodawane, ChildNodes zbieranie jest automatycznie aktualizowane.

Jeśli węzeł nie ma dziecka, to ChildNodes właściwość zwraca pusty zbiór. Można sprawdzić, czy CompositeNode zawiera wszystkie węzły dziecięce za pomocą HasChildNodes nieruchomości.

Poniższy przykład kodu pokazuje, jak wyliczyć natychmiastowe węzły dziecięce CompositeNode przy użyciu enumeratora dostarczonego przez ChildNodes Kolekcja:

// 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());
}
}

Poniższy przykład kodu pokazuje, jak wyliczyć natychmiastowe węzły dziecięce CompositeNode korzystanie ze zindeksowanego dostępu:

// 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());
}
}

Węzły rodzeństwa

Można uzyskać węzeł, który natychmiast poprzedza lub podąża za danym węzłem za pomocą PreviousSibling oraz NextSibling właściwości, odpowiednio. Jeśli węzeł jest ostatnim dzieckiem jego rodzica, to NextSibling nieruchomość jest null. Natomiast, jeśli węzeł jest pierwszym dzieckiem jego rodzica, PreviousSibling nieruchomość jest null.

Poniższy przykład kodu pokazuje, jak skutecznie odwiedzić wszystkie bezpośrednie i pośrednie węzły dziecięce węzła kompozytowego:

// 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);
}
}

Wpisany dostęp do węzłów dziecięcych i rodzicielskich

Dotychczas omawialiśmy właściwości, które zwracają jeden z typów podstawowych - Node lub CompositeNode. Ale czasami są sytuacje, w których może być konieczne rzucenie wartości do określonej klasy węzłów, takich jak Run lub Paragraph. To znaczy, nie można całkowicie uciec od castingu podczas pracy z Aspose.Words DOM, który jest złożony.

Aby zmniejszyć potrzebę odlewania, większość Aspose.Words klasy zapewniają właściwości i kolekcje, które zapewniają dostęp do warstw. Istnieją trzy podstawowe wzory dostępu na maszynie:

Właściwości wpisywane są jedynie przydatnymi skrótami, które czasami zapewniają łatwiejszy dostęp niż właściwości ogólne odziedziczone po Node.ParentNode oraz CompositeNode.FirstChild.

Poniższy przykład kodu pokazuje, jak używać właściwości wpisanych do dostępu do węzłów drzewa dokumentów:

// 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();
}