Aspose.Words مدل شیء سند (DOM)
مدل Aspose.Words Document Object (DOM) یک نمایش در حافظه یک سند ورد است. Aspose.Words DOM به شما اجازه می دهد تا محتوای و قالب بندی یک سند ورد را به صورت برنامه ریزی شده بخوانید، دستکاری کنید و تغییر دهید.
این بخش کلاس های اصلی Aspose.Words DOM و روابط آنها را توصیف می کند. با استفاده از کلاس های Aspose.Words DOM، می توانید دسترسی برنامه ریزی شده به عناصر سند و قالب بندی را بدست آورید.
ایجاد سند شی درخت
وقتی یک سند در Aspose.Words DOM خوانده می شود، یک درخت شی ساخته می شود و انواع مختلف عناصر سند منبع اشیاء درخت DOM خود را با خواص مختلف دارند.
درخت گره های سند را بسازید
وقتی Aspose.Words یک سند ورد را به حافظه می خواند، اشیاء مختلفی را ایجاد می کند که عناصر مختلف سند را نشان می دهند. هر اجرا از یک متن، پاراگراف، جدول یا بخش یک گره است، و حتی خود سند یک گره است. Aspose.Words برای هر نوع گره سند یک کلاس تعریف می کند.
درخت سند در Aspose.Words از الگوی طراحی کامپوزیت پیروی می کند:
- تمام کلاس های گره در نهایت از کلاس Node مشتق می شوند که کلاس پایه در مدل شیء سند Aspose.Words است.
- گره هایی که می توانند شامل گره های دیگر باشند، به عنوان مثال، Section یا Paragraph، از کلاس CompositeNode مشتق می شوند، که به نوبه خود از کلاس Node مشتق می شوند.
نمودار زیر ارث بین کلاس های گره ای مدل شیء سند Aspose.Words (DOM) را نشان می دهد. نام کلاس های انتزاعی با خط کش است.

Node
به ارث نرسیده اند.
بیایید به یک مثال نگاه کنیم. تصویر زیر یک سند Microsoft Word با انواع مختلف محتوا را نشان می دهد.

هنگام خواندن سند بالا به Aspose.Words DOM، درخت اشیاء ایجاد می شود، همانطور که در طرح زیر نشان داده شده است.

Document, Section, Paragraph, Table, Shape, Run, و تمام بیضوی های دیگر در نمودار اشیاء Aspose.Words هستند که عناصر سند ورد را نشان می دهند.
یک نوع Node
{#get-a-node-type}دریافت کنید
اگرچه کلاس Node به اندازه کافی برای تمایز گره های مختلف از یکدیگر کافی است، Aspose.Words برای ساده سازی برخی از وظایف API، مانند انتخاب گره های یک نوع خاص، شمارش NodeType را فراهم می کند.
نوع هر گره را می توان با استفاده از ویژگی NodeType بدست آورد. این ویژگی یک NodeType enumeration value. For example, a paragraph node represented by the Paragraph class returns NodeType.Paragraph و یک گره جدول را که توسط Table class returns 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 توصیف می کند.
وقتی نمونه سند را که قبلا در Document Explorer ارائه شده است باز می کنید، درخت گره دقیقا همان طور که در Aspose.Words نشان داده شده است ظاهر می شود.

روابط گره سند
گره های درخت رابطه ای بین آنها دارند:
- یک گره حاوی گره دیگر یک *parent.*است
- گره ای که در گره اصلی وجود دارد یک گره فرزند child. از همان پدر و مادر sibling گره است.
- گره root همیشه گره Document است.
گره هایی که می توانند شامل گره های دیگر باشند از کلاس CompositeNode مشتق می شوند و در نهایت همه گره ها از کلاس Node مشتق می شوند. این دو کلاس پایه روش ها و خواص مشترک برای ناوبری و اصلاح ساختار درخت را فراهم می کنند.
نمودار شیء UML زیر چندین گره از سند نمونه و روابط آنها با یکدیگر را از طریق ویژگی های والدین، کودک و خواهر و برادر نشان می دهد:

سند مالک گره است
یک گره همیشه متعلق به یک سند خاص است، حتی اگر تازه ایجاد شده یا از درخت حذف شده باشد، زیرا ساختارهای حیاتی در سراسر سند مانند سبک ها و لیست ها در گره 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 در موارد زیر null است:
- گره تازه ایجاد شده و هنوز به درخت اضافه نشده است.
- گره از درخت برداشته شده
- این گره ریشه Document است که همیشه یک گره اصلی null دارد.
شما می توانید یک گره را از والد خود با فراخوانی روش 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 مجموعه خالی را باز می گرداند. شما می توانید با استفاده از ویژگی HasChildNodes بررسی کنید که آیا CompositeNode شامل هر گره کودک است یا خیر.
مثال کد زیر نشان می دهد که چگونه گره های کودک فوری یک 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 ویژگی ها و مجموعه هایی را فراهم می کنند که دسترسی به نوع قوی را فراهم می کنند. سه الگوی اساسی دسترسی تایپ شده وجود دارد:
- یک گره اصلی ویژگی های تایپ شده FirstXXX و LastXXX را نشان می دهد. به عنوان مثال، Document دارای ویژگی های FirstSection و LastSection است. به طور مشابه، Table دارای ویژگی هایی مانند FirstRow، LastRow و دیگران است.
- یک گره والدین مجموعه ای تایپ شده از گره های کودک مانند Document.Sections، Body.Paragraphs و دیگران را نشان می دهد.
- یک گره کودک دسترسی تایپ شده به والدین خود را فراهم می کند، مانند Run.ParentParagraph، Paragraph.ParentSection و دیگران.
ویژگی های تایپ شده فقط میانبر های مفیدی هستند که گاهی اوقات دسترسی آسان تری نسبت به ویژگی های عمومی که از 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(); | |
} | |
} |