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) ชื่อของคลาสนามธรรมเป็นภาษาตัวเอียง
Node
ลองดูตัวอย่าง รูปภาพต่อไปนี้แสดงเอกสาร Microsoft Word ที่มีเนื้อหาประเภทต่างๆ
เมื่ออ่านเอกสารด้านบนลงใน Aspose.Words DOM โครงสร้างของออบเจ็กต์จะถูกสร้างขึ้น ดังที่แสดงในสคีมาด้านล่าง
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 ทุกประการ
ความสัมพันธ์ของโหนดเอกสาร
โหนดในแผนผังมีความสัมพันธ์ระหว่างกัน:
- โหนดที่มีโหนดอื่นคือ parent.
- โหนดที่มีอยู่ในโหนดหลักคือโหนด child. 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-.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(); | |
} |