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.

הדיאגרמה המוצגת להלן מראה ירושה בין כיתות צומת של מודל אובייקט המסמך Aspose.Words (DOM). שמות המעמדות המופשטים הם בכתב עוקף.

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. לדוגמה, צומת פסקה המייצגת על ידי Paragraph מחזירה את הכיתה NodeType.Paragraph, וצומת טבלה המייצגת על ידי Table מחזירה את הכיתה NodeType.Table.

הדוגמה הבאה מראה כיצד להשיג סוג צומת באמצעות הספירה 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();

ניווט בעץ המסמכים

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 דורש אובייקט מסמך שהועבר לבנאי.

בעת יצירת פסקה חדשה באמצעות DocumentBuilder, לבונה תמיד יש מחלקה Document המקושרת אליה דרך המאפיין DocumentBuilder.Document.

דוגמת הקוד הבאה מראה שכאשר יוצרים כל צומת, מסמך שיהיה הבעלים של הצומת תמיד מוגדר:

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;

צומת הורה

לכל צומת יש הורה שצוין על ידי המאפיין ParentNode. לצומת אין צומת אב, כלומר ParentNode הוא אפס, במקרים הבאים:

  • הצומת נוצר זה עתה וטרם התווסף לעץ.
  • הצומת הוסר מהעץ.
  • זהו צומת השורש Document שתמיד יש לו צומת אב אפס.

ניתן להסיר צומת מההורה שלו על ידי קריאה לשיטת Remove.דוגמת הקוד הבאה מראה כיצד לגשת לצומת האב:

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;

צמתים לילדים

הדרך היעילה ביותר לגשת לצמתים של ילד של CompositeNode היא באמצעות המאפיינים FirstChild ו LastChild שמחזירים את הצמתים של הילד הראשון והאחרון, בהתאמה. אם אין צמתים של ילדים, תכונות אלה חוזרות null.

CompositeNode

אם לצומת אין ילד, המאפיין ChildNodes מחזיר אוסף ריק. אתה יכול לבדוק אם CompositeNode מכיל צמתים של ילדים באמצעות המאפיין HasChildNodes.

דוגמת הקוד הבאה מראה כיצד למנות נקודות ילד מיידיות של CompositeNode באמצעות המונה שמסופק על ידי אוסף 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;
}
}

דוגמת הקוד הבאה מראה כיצד למנות נקודות ילד מיידיות של CompositeNode באמצעות גישה ממוזגת:

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

צמתים אחים

אתה יכול להשיג את הצומת שמקדים מיד או עוקב אחר צומת מסוים באמצעות המאפיינים PreviousSibling ו NextSibling, בהתאמה. אם צומת הוא הילד האחרון של ההורה שלו, אז המאפיין NextSibling הוא null. לעומת זאת, אם הצומת הוא הילד הראשון של ההורה שלו, המאפיין PreviousSibling הוא null.

דוגמת הקוד הבאה מראה כיצד לבקר ביעילות בכל צמתים ישירים ועקיפים של צומת מורכב:

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

גישה מוקלדת לצמתים של ילדים והורים

עד כה דנו בתכונות המחזירות אחד מסוגי הבסיס – Node או CompositeNode. אבל לפעמים יש מצבים שבהם ייתכן שיהיה עליך להעביר ערכים למחלקת צומת ספציפית, כגון Run או Paragraph. כלומר, אתה לא יכול להתרחק לחלוטין מהיציקה כשאתה עובד עם Aspose.Words DOM, שהוא מורכב.

כדי להפחית את הצורך בגיסוי, רוב הכיתות Aspose.Words מספקות תכונות ואוספים המספקים גישה עם טיפוס חזק. יש שלושה דפוסים בסיסיים של גישה מודפסת:

מאפיינים מודפסים הם רק קיצורי דרך שימושיים שלפעמים מספקים גישה קלה יותר מאשר מאפיינים גנריים שירשו מ Node.ParentNode ו CompositeNode.FirstChild.

דוגמת הקוד הבאה מראה כיצד להשתמש בתכונות שהוקלדו כדי לגשת לצמתים של עץ המסמך:

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