Aspose.Words Document Object Model (DOM)

Aspose.Words Document Object Model (DOM) เป็นตัวแทนในหน่วยความจำของเอกสาร Word Aspose.Words DOM ช่วยให้คุณสามารถอ่าน จัดการ และแก้ไขเนื้อหาและการจัดรูปแบบของเอกสาร Word โดยทางโปรแกรม

ส่วนนี้จะอธิบายคลาสหลักของ Aspose.Words DOM และความสัมพันธ์ โดยใช้คลาส Aspose.Words DOM คุณสามารถรับการเข้าถึงองค์ประกอบเอกสารและการจัดรูปแบบโดยทางโปรแกรม

สร้าง {#create-a-document-objects-tree} ทรีออบเจ็กต์ Document

เมื่ออ่านเอกสารลงใน Aspose.Words DOM แผนผังออบเจ็กต์จะถูกสร้างขึ้นและองค์ประกอบประเภทต่างๆ ของเอกสารต้นฉบับจะมีออบเจ็กต์แผนผัง DOM ของตัวเองที่มีคุณสมบัติต่างๆ

สร้างแผนผังโหนดเอกสาร

เมื่อ Aspose.Words อ่านเอกสาร Word ลงในหน่วยความจำ จะสร้างออบเจ็กต์ประเภทต่างๆ ที่แสดงถึงองค์ประกอบต่างๆ ของเอกสาร การเรียกใช้ข้อความ ย่อหน้า ตาราง หรือส่วนทุกครั้งถือเป็นโหนด และแม้แต่ตัวเอกสารเองก็คือโหนด Aspose.Words กำหนดคลาสสำหรับโหนดเอกสารทุกประเภท

แผนผังเอกสารใน Aspose.Words เป็นไปตามรูปแบบการออกแบบคอมโพสิต:

  • คลาสโหนดทั้งหมดได้รับมาจากคลาส Node ซึ่งเป็นคลาสพื้นฐานใน Aspose.Words Document Object Model ในที่สุด
  • โหนดที่สามารถมีโหนดอื่นได้ เช่น Section หรือ Paragraph ได้มาจากคลาส CompositeNode ซึ่งในทางกลับกันก็มาจากคลาส Node

แผนภาพด้านล่างแสดงการสืบทอดระหว่างคลาสโหนดของ Aspose.Words Document Object Model (DOM) ชื่อของคลาสนามธรรมเป็นภาษาตัวเอียง

aspose-คำ-dom

ลองดูตัวอย่าง รูปภาพต่อไปนี้แสดงเอกสาร Microsoft Word ที่มีเนื้อหาประเภทต่างๆ

เอกสารตัวอย่าง aspose คำ

เมื่ออ่านเอกสารด้านบนลงใน Aspose.Words DOM โครงสร้างของออบเจ็กต์จะถูกสร้างขึ้น ดังที่แสดงในสคีมาด้านล่าง

dom-aspose-คำ

Document, Section, Paragraph, Table, Shape, Run และจุดไข่ปลาอื่นๆ ทั้งหมดในไดอะแกรมคือออบเจ็กต์ Aspose.Words ที่แสดงองค์ประกอบของเอกสาร Word

รับ {#get-a-node-type} ประเภท 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-.NET
Document doc = new Document();
// Returns NodeType.Document
NodeType type = doc.NodeType;

การนำทางแผนผังเอกสาร

Aspose.Words แสดงถึงเอกสารเป็นแผนผังโหนด ซึ่งช่วยให้คุณนำทางระหว่างโหนดได้ ส่วนนี้อธิบายวิธีสำรวจและสำรวจโครงสร้างเอกสารใน Aspose.Words

เมื่อคุณเปิดเอกสารตัวอย่างที่แสดงไว้ก่อนหน้านี้ใน Document Explorer แผนผังโหนดจะปรากฏเหมือนกับที่แสดงใน Aspose.Words ทุกประการ

เอกสารในเอกสาร explorer

ความสัมพันธ์ของโหนดเอกสาร

โหนดในแผนผังมีความสัมพันธ์ระหว่างกัน:

  • โหนดที่มีโหนดอื่นคือ parent.
  • โหนดที่มีอยู่ในโหนดหลักคือโหนด child. Child ของโหนดหลักเดียวกันคือโหนด sibling
  • โหนด root จะเป็นโหนด Document เสมอ

โหนดที่สามารถมีโหนดอื่นได้มาจากคลาส CompositeNode และโหนดทั้งหมดได้รับมาจากคลาส Node ในที่สุด คลาสพื้นฐานทั้งสองนี้มีวิธีการและคุณสมบัติทั่วไปสำหรับการนำทางและการปรับเปลี่ยนโครงสร้างต้นไม้

แผนภาพอ็อบเจ็กต์ UML ต่อไปนี้แสดงหลายโหนดของเอกสารตัวอย่างและความสัมพันธ์ระหว่างกันผ่านคุณสมบัติพาเรนต์ รายการย่อย และรายการพี่น้อง:

เอกสารคอนโซลความสัมพันธ์ aspose คำ

เอกสารเป็นเจ้าของโหนด

โหนดจะอยู่ในเอกสารใดเอกสารหนึ่งเสมอ แม้ว่าจะเพิ่งสร้างหรือลบออกจากแผนผังก็ตาม เนื่องจากโครงสร้างทั่วทั้งเอกสารที่สำคัญ เช่น สไตล์และรายการจะถูกจัดเก็บไว้ในโหนด 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-.NET
// 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.
Console.WriteLine("Paragraph has no parent node: " + (para.ParentNode == null));
// But the paragraph node knows its document.
Console.WriteLine("Both nodes' documents are the same: " + (para.Document == 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.ParagraphFormat.StyleName = "Heading 1";
// Now add the paragraph to the main text of the first section.
doc.FirstSection.Body.AppendChild(para);
// The paragraph node is now a child of the Body node.
Console.WriteLine("Paragraph has a parent node: " + (para.ParentNode != null));

โหนดหลัก

แต่ละโหนดมีพาเรนต์ที่ระบุโดยคุณสมบัติ ParentNode โหนดไม่มีโหนดหลัก นั่นคือ ParentNode เป็นโมฆะ ในกรณีต่อไปนี้:

  • โหนดเพิ่งถูกสร้างขึ้นและยังไม่ได้เพิ่มลงในแผนผัง
  • โหนดถูกลบออกจากแผนผังแล้ว
  • นี่คือโหนด Document รูทซึ่งมีโหนดพาเรนต์ที่เป็นโมฆะเสมอ

คุณสามารถลบโหนดออกจากพาเรนต์ได้โดยการเรียกเมธอด Remove ตัวอย่างโค้ดต่อไปนี้แสดงวิธีเข้าถึงโหนดพาเรนต์:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
// 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.FirstChild;
// The section's parent node is the document.
Console.WriteLine("Section parent is the document: " + (doc == section.ParentNode));

โหนดย่อย

วิธีที่มีประสิทธิภาพที่สุดในการเข้าถึงโหนดลูกของ CompositeNode คือผ่านคุณสมบัติ FirstChild และ LastChild ที่ส่งคืนโหนดลูกแรกและโหนดสุดท้ายตามลำดับ หากไม่มีโหนดย่อย คุณสมบัติเหล่านี้จะส่งคืน null

CompositeNode ยังมีวิธี GetChildNodes ที่เปิดใช้งานการเข้าถึงโหนดย่อยแบบจัดทำดัชนีหรือแจกแจง คุณสมบัติ ChildNodes คือคอลเลกชันโหนดที่ใช้งานอยู่ ซึ่งหมายความว่าเมื่อใดก็ตามที่เอกสารมีการเปลี่ยนแปลง เช่น เมื่อโหนดถูกลบหรือเพิ่ม คอลเลกชัน ChildNodes จะได้รับการอัปเดตโดยอัตโนมัติ

หากโหนดไม่มีลูก คุณสมบัติ ChildNodes จะส่งกลับคอลเลกชันที่ว่างเปล่า คุณสามารถตรวจสอบว่า CompositeNode มีโหนดย่อยโดยใช้คุณสมบัติ HasChildNodes หรือไม่

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีการระบุโหนดลูกในทันทีของ CompositeNode โดยใช้ตัวแจงนับที่มาจากคอลเลกชัน ChildNodes:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
Document doc = new Document();
Paragraph paragraph = (Paragraph)doc.GetChild(NodeType.Paragraph, 0, true);
NodeCollection children = paragraph.ChildNodes;
foreach (Node child in children)
{
// Paragraph may contain children of various types such as runs, shapes and so on.
if (child.NodeType.Equals(NodeType.Run))
{
// Say we found the node that we want, do something useful.
Run run = (Run)child;
Console.WriteLine(run.Text);
}
}

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีระบุโหนดลูกในทันทีของ CompositeNode โดยใช้การเข้าถึงที่จัดทำดัชนี:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
Document doc = new Document();
Paragraph paragraph = (Paragraph)doc.GetChild(NodeType.Paragraph, 0, true);
NodeCollection children = paragraph.ChildNodes;
for (int i = 0; i < children.Count; i++)
{
Node child = children[i];
// Paragraph may contain children of various types such as runs, shapes and so on.
if (child.NodeType.Equals(NodeType.Run))
{
// Say we found the node that we want, do something useful.
Run run = (Run)child;
Console.WriteLine(run.Text);
}
}

โหนดพี่น้อง

คุณสามารถรับโหนดที่อยู่ข้างหน้าหรือตามโหนดใดโหนดหนึ่งได้ทันทีโดยใช้คุณสมบัติ PreviousSibling และ NextSibling ตามลำดับ หากโหนดเป็นโหนดลูกสุดท้ายของโหนดหลัก คุณสมบัติ NextSibling จะเป็น null ในทางกลับกัน หากโหนดเป็นโหนดลูกแรกของโหนดหลัก คุณสมบัติ PreviousSibling จะเป็น null

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีการเยี่ยมชมโหนดลูกทั้งทางตรงและทางอ้อมของโหนดคอมโพสิตอย่างมีประสิทธิภาพ:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET
public static void RecurseAllNodes()
{
// The path to the documents directory.
string dataDir = RunExamples.GetDataDir_WorkingWithNode();
// Open a document.
Document doc = new Document(dataDir + "Node.RecurseAllNodes.doc");
// Invoke the recursive function that will walk the tree.
TraverseAllNodes(doc);
}
/// <summary>
/// A simple function that will walk through all children of a specified node recursively
/// And print the type of each node to the screen.
/// </summary>
public static void TraverseAllNodes(CompositeNode parentNode)
{
// This is the most efficient way to loop through immediate children of a node.
for (Node childNode = parentNode.FirstChild; childNode != null; childNode = childNode.NextSibling)
{
// Do some useful work.
Console.WriteLine(Node.NodeTypeToString(childNode.NodeType));
// 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 ส่วนใหญ่จะมีคุณสมบัติและคอลเลกชั่นที่ให้การเข้าถึงแบบเข้มงวด การเข้าถึงด้วยการพิมพ์มีรูปแบบพื้นฐานสามรูปแบบ:

  • โหนดพาเรนต์เปิดเผยคุณสมบัติ 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-.NET
Document doc = new Document();
Section section = doc.FirstSection;
// Quick typed access to the Body child node of the Section.
Body body = section.Body;
// Quick typed access to all Table child nodes contained in the Body.
TableCollection tables = body.Tables;
foreach (Table table in tables)
{
// Quick typed access to the first row of the table.
if (table.FirstRow != null)
table.FirstRow.Remove();
// Quick typed access to the last row of the table.
if (table.LastRow != null)
table.LastRow.Remove();
}