Aspose.Words Model Objektu Dokumentu (DOM)

The Aspose.Words objektový Model dokumentu (DOM) je reprezentace v paměti a Word dokument. Aspose.Words DOM umožňuje programově číst, manipulovat a upravovat obsah a formátování Word dokumentu.

Tato část popisuje hlavní třídy Aspose.Words DOM a jejich vztahy. Pomocí tříd Aspose.Words DOM můžete získat programový přístup k prvkům dokumentu a formátování.

Vytvořit Strom Objektů Dokumentu

Když je dokument načten do Aspose.Words DOM, pak je vytvořen strom objektů a různé typy prvků zdrojového dokumentu mají své vlastní objekty stromu DOM s různými vlastnostmi.

Sestavte Strom Uzlů Dokumentu

Když Aspose.Words přečte dokument Word do paměti, vytvoří objekty různých typů, které představují různé prvky dokumentu. Každý běh textu, odstavce, tabulky nebo oddílu je uzel a dokonce i samotný dokument je uzel. Aspose.Words definuje třídu pro každý typ uzlu dokumentu.

Strom dokumentů v Aspose.Words sleduje složený návrhový vzor:

  • Všechny třídy uzlů nakonec pocházejí z třídy Node, což je základní třída v modelu objektu dokumentu Aspose.Words.
  • Uzly, které mohou obsahovat další uzly, například Section nebo Paragraph, pocházejí z třídy CompositeNode, která zase pochází z třídy Node.

Níže uvedený diagram ukazuje dědičnost mezi třídami uzlů modelu objektu dokumentu Aspose.Words (DOM). Názvy abstraktních tříd jsou kurzívou.

aspose-words-dom-aspose-words-cpp

Podívejme se na příklad. Následující obrázek ukazuje Microsoft Word dokument s různými typy obsahu.

document-example-aspose-words-cpp

Při čtení výše uvedeného dokumentu do Aspose.Words DOM se vytvoří strom objektů, jak je znázorněno na schématu níže.

document-example-dom-aspose-words-cpp

Document, Section, Paragraph, Table, Shape, Run, a všechny ostatní elipsy na diagramu jsou objekty Aspose.Words, které představují prvky dokumentu Word.

Získejte Node typ

Ačkoli třída Node je dostatečná k tomu, aby od sebe odlišila různé uzly, Aspose.Words poskytuje výčet NodeType pro zjednodušení některých úkolů API, jako je výběr uzlů konkrétního typu.

Typ každého uzlu lze získat pomocí vlastnosti NodeType. Tato vlastnost vrací hodnotu výčtu NodeType. Například uzel odstavce reprezentovaný třídou Paragraph vrací NodeType.Paragraph a uzel tabulky reprezentovaný třídou Table vrací NodeType.Table.

Následující příklad ukazuje, jak získat typ uzlu pomocí výčtu NodeType:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
System::SharedPtr<Document> doc = System::MakeObject<Document>();
// Returns NodeType.Document
NodeType type = doc->get_NodeType();

Navigace Ve Stromu Dokumentů

Aspose.Words představuje dokument jako strom uzlů, který umožňuje navigaci mezi uzly. Tato část popisuje, jak prozkoumat a procházet strom dokumentů v Aspose.Words.

Když otevřete ukázkový dokument prezentovaný dříve v Průzkumníku dokumentů, strom uzlů se zobrazí přesně tak, jak je znázorněn v Aspose.Words.

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

Vztahy Uzlu Dokumentu

Uzly ve stromu mají mezi sebou vztahy:

  • Uzel obsahující jiný uzel je parent.
  • Uzel obsažený v nadřazeném uzlu je child. podřízené uzly stejného rodiče jsou sibling uzly.
  • root uzel je vždy Document uzel.

Uzly, které mohou obsahovat další uzly, pocházejí z třídy CompositeNode a všechny uzly nakonec pocházejí z třídy Node. Tyto dvě základní třídy poskytují běžné metody a vlastnosti pro navigaci a modifikaci stromové struktury.

Následující UML objektový diagram zobrazuje několik uzlů vzorového dokumentu a jejich vzájemné vztahy prostřednictvím vlastností nadřazených, podřízených a sourozenců:

document-nodes-relationships-aspose-words-cpp

Dokument je vlastníkem uzlu

Uzel vždy patří ke konkrétnímu dokumentu, i když byl právě vytvořen nebo odstraněn ze stromu, protože důležité struktury pro celý dokument, jako jsou styly a seznamy, jsou uloženy v uzlu Document. Například není možné mít Paragraph bez Document, protože každý odstavec má přiřazený styl, který je globálně definován pro dokument. Toto pravidlo se používá při vytváření nových uzlů. Přidání nového Paragraph přímo do DOM vyžaduje objekt dokumentu předaný konstruktoru.

Při vytváření nového odstavce pomocí DocumentBuilder má builder vždy třídu Document propojenou pomocí vlastnosti DocumentBuilder.Document.

Následující příklad kódu ukazuje, že při vytváření libovolného uzlu je vždy definován dokument, který bude uzel vlastnit:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
// Open a file from disk.
System::SharedPtr<Document> doc = System::MakeObject<Document>();
// Creating a new node of any type requires a document passed into the constructor.
System::SharedPtr<Paragraph> para = System::MakeObject<Paragraph>(doc);
// The new paragraph node does not yet have a parent.
std::cout << "Paragraph has no parent node: " << System::ObjectExt::Box<bool>((para->get_ParentNode() == nullptr))->ToString().ToUtf8String() << std::endl;
// But the paragraph node knows its document.
std::cout << "Both nodes' documents are the same: " << System::ObjectExt::Box<bool>((para->get_Document() == doc))->ToString().ToUtf8String() << std::endl;
// 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->get_ParagraphFormat()->set_StyleName(u"Heading 1");
// Now add the paragraph to the main text of the first section.
doc->get_FirstSection()->get_Body()->AppendChild(para);
// The paragraph node is now a child of the Body node.
std::cout << "Paragraph has a parent node: " << System::ObjectExt::Box<bool>((para->get_ParentNode() != nullptr))->ToString().ToUtf8String() << std::endl;

Nadřazený Uzel

Každý uzel má rodiče určeného vlastností ParentNode. Uzel nemá žádný nadřazený uzel, to znamená, že ParentNode je null, v následujících případech:

  • Uzel byl právě vytvořen a dosud nebyl přidán do stromu.
  • Uzel byl odstraněn ze stromu.
  • Toto je kořenový Document uzel, který má vždy nulový nadřazený uzel.

Uzel můžete odebrat z jeho rodiče voláním metody Remove.Následující příklad kódu ukazuje, jak přistupovat k nadřazenému uzlu:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
// Create a new empty document. It has one section.
System::SharedPtr<Document> doc = System::MakeObject<Document>();
// The section is the first child node of the document.
System::SharedPtr<Node> section = doc->get_FirstChild();
// The section's parent node is the document.
std::cout << "Section parent is the document: " << System::ObjectExt::Box<bool>((doc == section->get_ParentNode()))->ToString().ToUtf8String() << std::endl;

Podřízené Uzly

Nejúčinnější způsob přístupu k podřízeným uzlům CompositeNode je pomocí vlastností FirstChild a LastChild, které vracejí první a poslední podřízený uzel. Pokud nejsou žádné podřízené uzly, vrátí tyto vlastnosti null.

CompositeNode

Pokud uzel nemá žádné dítě, vrátí vlastnost ChildNodes prázdnou kolekci. Pomocí vlastnosti HasChildNodes můžete zkontrolovat, zda CompositeNode obsahuje nějaké podřízené uzly.

Následující příklad kódu ukazuje, jak vyjmenovat bezprostřední podřízené uzly CompositeNode pomocí výčtu poskytnutého kolekcí ChildNodes:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
System::SharedPtr<Document> doc = System::MakeObject<Document>();
System::SharedPtr<Paragraph> paragraph = System::DynamicCast<Paragraph>(doc->GetChild(NodeType::Paragraph, 0, true));
System::SharedPtr<NodeCollection> children = paragraph->get_ChildNodes();
for (System::SharedPtr<Node> child : System::IterateOver(children))
{
if (System::ObjectExt::Equals(child->get_NodeType(), NodeType::Run))
{
// Say we found the node that we want, do something useful.
System::SharedPtr<Run> run = System::DynamicCast<Run>(child);
std::cout << run->get_Text().ToUtf8String() << std::endl;
}
}

Následující příklad kódu ukazuje, jak vyjmenovat okamžité podřízené uzly CompositeNode pomocí indexovaného přístupu:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
System::SharedPtr<Document> doc = System::MakeObject<Document>();
System::SharedPtr<Paragraph> paragraph = System::DynamicCast<Paragraph>(doc->GetChild(NodeType::Paragraph, 0, true));
System::SharedPtr<NodeCollection> children = paragraph->get_ChildNodes();
for (int32_t i = 0; i < children->get_Count(); i++)
{
System::SharedPtr<Node> child = children->idx_get(i);
// Paragraph may contain children of various types such as runs, shapes and so on.
if (System::ObjectExt::Equals(child->get_NodeType(), NodeType::Run))
{
// Say we found the node that we want, do something useful.
System::SharedPtr<Run> run = System::DynamicCast<Run>(child);
std::cout << run->get_Text().ToUtf8String() << std::endl;
}
}

Sourozenecké Uzly

Uzel, který bezprostředně předchází nebo následuje po konkrétním uzlu, můžete získat pomocí vlastností PreviousSibling a NextSibling. Pokud je uzel posledním potomkem svého rodiče, pak je vlastnost NextSibling null. Naopak, pokud je uzel prvním potomkem svého rodiče, vlastnost PreviousSibling je null.

Následující příklad kódu ukazuje, jak efektivně navštívit všechny přímé a nepřímé podřízené uzly složeného uzlu:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
void TraverseAllNodes(System::SharedPtr<CompositeNode> parentNode)
{
// This is the most efficient way to loop through immediate children of a node.
for (System::SharedPtr<Node> childNode = parentNode->get_FirstChild(); childNode != nullptr; childNode = childNode->get_NextSibling())
{
// Do some useful work.
std::cout << Node::NodeTypeToString(childNode->get_NodeType()).ToUtf8String() << std::endl;
// Recurse into the node if it is a composite node.
if (childNode->get_IsComposite())
{
TraverseAllNodes(System::DynamicCast<CompositeNode>(childNode));
}
}
}
void RecurseAllNodes(System::String const &inputDataDir)
{
// Open a document.
System::SharedPtr<Document> doc = System::MakeObject<Document>(inputDataDir + u"Node.RecurseAllNodes.doc");
// Invoke the recursive function that will walk the tree.
TraverseAllNodes(doc);
}

Zadaný přístup k podřízeným a nadřazeným uzlům

Zatím jsme diskutovali o vlastnostech, které vracejí jeden ze základních typů - Node nebo CompositeNode. Někdy však existují situace, kdy možná budete muset přenést hodnoty do konkrétní třídy uzlů, například Run nebo Paragraph. To znamená, že při práci s Aspose.Words DOM, který je složený, se nemůžete úplně zbavit odlévání.

Aby se snížila potřeba odlévání, většina tříd Aspose.Words poskytuje vlastnosti a kolekce, které poskytují silně napsaný přístup. Existují tři základní vzory typovaného přístupu:

Zadané vlastnosti jsou pouze užitečné zkratky, které někdy poskytují snadnější přístup než obecné vlastnosti zděděné z Node.ParentNode a CompositeNode.FirstChild.

Následující příklad kódu ukazuje, jak používat zadané vlastnosti pro přístup k uzlům stromu dokumentů:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
System::SharedPtr<Document> doc = System::MakeObject<Document>();
System::SharedPtr<Section> section = doc->get_FirstSection();
// Quick typed access to the Body child node of the Section.
System::SharedPtr<Body> body = section->get_Body();
// Quick typed access to all Table child nodes contained in the Body.
System::SharedPtr<TableCollection> tables = body->get_Tables();
for (System::SharedPtr<Table> table : System::IterateOver<System::SharedPtr<Table>>(tables))
{
// Quick typed access to the first row of the table.
if (table->get_FirstRow() != nullptr)
{
table->get_FirstRow()->Remove();
}
// Quick typed access to the last row of the table.
if (table->get_LastRow() != nullptr)
{
table->get_LastRow()->Remove();
}
}