Aspose.Words نموذج كائن المستند (DOM)

نموذج كائن المستند Aspose.Words (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). أسماء الفئات المجردة مكتوبة بخط مائل.

aspose-words-dom

دعونا ننظر إلى مثال. تعرض الصورة التالية مستندا Microsoft Word يحتوي على أنواع مختلفة من المحتوى.

document-example

عند قراءة المستند أعلاه في Aspose.Words DOM، يتم إنشاء شجرة الكائنات، كما هو موضح في المخطط أدناه.

document-example-dom

Document, Section, Paragraph, Table, Shape, Run, وجميع علامات الحذف الأخرى في الرسم التخطيطي هي Aspose.Words كائنات تمثل عناصر مستند الكلمة.

الحصول على 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-Java
Document doc = new Document();
// Returns NodeType.Document
int type = doc.getNodeType();

التنقل في شجرة المستندات

Aspose.Words يمثل وثيقة كشجرة عقدة، والتي تمكنك من التنقل بين العقد. يصف هذا القسم كيفية استكشاف شجرة المستندات والتنقل فيها في Aspose.Words.

عند فتح نموذج المستند، الذي تم تقديمه مسبقا، في مستكشف المستندات، تظهر شجرة العقدة تماما كما يتم تمثيلها في Aspose.Words.

document-in-document-explorer

علاقات عقدة المستند

العقد في الشجرة لها علاقات بينهما:

  • العقدة التي تحتوي على عقدة أخرى هي parent.
  • العقدة الموجودة في العقدة الأم هي child. العقد الفرعية لنفس الأصل هي sibling العقد.
  • العقدة root هي دائما عقدة Document.

العقد التي يمكن أن تحتوي على عقد أخرى مشتقة من فئة CompositeNode، وجميع العقد مشتقة في النهاية من فئة Node. توفر هاتان الفئتان الأساسيتان طرقا وخصائص شائعة للملاحة والتعديل في بنية الشجرة.

يوضح مخطط الكائن UML التالي عدة عقد من نموذج المستند وعلاقاتها ببعضها البعض عبر خصائص الوالد والطفل والأخوة:

document-nodes-relationships

المستند هو مالك العقدة

تنتمي العقدة دائما إلى مستند معين، حتى لو تم إنشاؤه للتو أو إزالته من الشجرة، لأنه يتم تخزين الهياكل الحيوية على مستوى المستند مثل الأنماط والقوائم في عقدة 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-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));

العقدة الأم

كل عقدة لها أصل محدد بواسطة ParentNode خاصية. لا تحتوي العقدة على عقدة أصل، أي ParentNode فارغ، في الحالات التالية:

  • تم إنشاء العقدة للتو ولم تتم إضافتها بعد إلى الشجرة.
  • تمت إزالة العقدة من الشجرة.
  • هذه هي عقدة الجذر Document التي تحتوي دائما على عقدة أصل فارغة.

يمكنك إزالة عقدة من الأصل عن طريق استدعاء طريقة Remove.يوضح مثال التعليمات البرمجية التالية كيفية الوصول إلى العقدة الأصل:

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

العقد الفرعية

الطريقة الأكثر فعالية للوصول إلى العقد الفرعية لـ 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-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());
}
}

يوضح مثال الكود التالي كيفية تعداد العقد الفرعية الفورية لـ CompositeNode باستخدام الوصول المفهرس:

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

عقد الأخوة

يمكنك الحصول على العقدة التي تسبق أو تتبع عقدة معينة مباشرة باستخدام خصائص PreviousSibling و NextSibling، على التوالي. إذا كانت العقدة هي آخر طفل في الأصل، فإن الخاصية NextSibling هي null. على العكس من ذلك، إذا كانت العقدة هي الطفل الأول لوالدها، فإن PreviousSibling الخاصية هي null.

يوضح مثال الكود التالي كيفية زيارة جميع العقد الفرعية المباشرة وغير المباشرة للعقدة المركبة بكفاءة:

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

الوصول المكتوب إلى العقد الفرعية والوالدية

حتى الآن، ناقشنا الخصائص التي تعيد أحد الأنواع الأساسية – 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-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();
}