Πώς να εργαστείτε με κόμβους στο .NET
Αυτός ο οδηγός δείχνει πώς να περιηγηθείτε, να ερωτήσετε και να τροποποιήσετε το δέντρο κόμβων ενός εγγράφου Word άμεσα σε Aspose.Words FOSS για .NET, χρησιμοποιώντας το Node and CompositeNode βασικές κλάσεις που Document, Section, Paragraph, Table, και κάθε άλλο στοιχείο εγγράφου χτίζονται επάνω. Καλύπτει τον καθορισμό περιοχής μιας αναζήτησης με NodeType, προσθέτοντας και αφαιρώντας κόμβους προγραμματιστικά, αντιδρώντας σε δομικές αλλαγές, και χρησιμοποιώντας DocumentVisitor για περιήγηση με διανομή τύπου.
Οδηγός βήμα-βήμα
Βήμα 1: Εγκατάσταση του πακέτου
Aspose.Words FOSS for .NET δεν έχει ακόμη δημοσιεύσει ένα πακέτο NuGet – δημιουργήστε τη βιβλιοθήκη από τον πηγαίο κώδικα αντ’ αυτού. Κλωνοποιήστε το https://github.com/aspose-words-foss/Aspose.Words-FOSS-for-.NET.git, στη συνέχεια χτίστε το Aspose.Words.sln σε διαμόρφωση Release με το SDK .NET και αναφέρετε την προκύπτουσα συναρμολόγηση Aspose.Words από το έργο σας. Η βιβλιοθήκη στοχεύει στο .NET Standard 2.0, έτσι λειτουργεί στο .NET Framework 4.6.2+ και στο .NET 6/8/10.
Βήμα 2: Εισαγωγή των απαιτούμενων κλάσεων
Προσθέστε μια οδηγία using Aspose.Words; — τα Node, CompositeNode, NodeType, NodeCollection, NodeList, INodeChangingCallback και DocumentVisitor βρίσκονται όλα στο namespace Aspose.Words μαζί με το Document.
Βήμα 3: Κατανοήστε τον Κόμβο και τις Βασικές Κλάσεις CompositeNode
Κάθε αντικείμενο σε ένα δέντρο εγγράφου κληρονομεί από την αφηρημένη κλάση Node, η οποία εκθέτει το NodeType (που προσδιορίζει τι είδους κόμβο είναι), το ParentNode (το περιβάλλον CompositeNode), το Document (το ιδιοκτησιακό έγγραφο), και τα PreviousSibling / NextSibling για μετακίνηση μεταξύ κόμβων στο ίδιο επίπεδο. Ελέγξτε το Node.IsComposite για να διαπιστώσετε εάν ένας συγκεκριμένος κόμβος μπορεί να περιέχει παιδιά πριν τον μετατρέψετε. Το CompositeNode επεκτείνει το Node για στοιχεία container – FirstChild, LastChild και Count περιγράφουν τα άμεσα παιδιά του, και το HasChildNodes αναφέρει εάν υπάρχουν.
Βήμα 4: Αναζήτηση Παιδιών κατά Τύπο
Καλέστε το CompositeNode.GetChildNodes(nodeType, isDeep) για να ανακτήσετε κάθε παιδί ενός δεδομένου NodeType, περνώντας το isDeep: true για να αναζητήσετε ολόκληρο το υποδέντρο αντί μόνο των άμεσων παιδιών, ή το NodeType.Any για να ταιριάξετε κάθε τύπο κόμβου ανεξάρτητα από το είδος. Το CompositeNode.GetChild(nodeType, index, isDeep) ανακτά ένα μοναδικό παιδί που ταιριάζει με βάση το δείκτη. Για δομικούς τύπους κόμβων (Document, Section, Body, Paragraph, Table, Row, Cell), τύπους ενσωματωμένου περιεχομένου (Run, Shape, Comment), και τύπους μηχανισμού πεδίων (FieldStart, FieldSeparator, FieldEnd, που σημειώνουν τα όρια ενός πεδίου Word και το κείμενο εναλλαγής στη ροή εκτέλεσης), περάστε τη συγκεκριμένη τιμή NodeType που προσδιορίζει τι ψάχνετε.
Βήμα 5: Εκτέλεση ερωτημάτων XPath σε ένα υποδέντρο
Το CompositeNode υλοποιεί επίσης τα SelectNodes(xpath) και SelectSingleNode(xpath) για ερωτήματα βασισμένα σε XPath σε όλο το υποδέντρο, επιστρέφοντας τα αποτελέσματα ως NodeList (ή ένα μοναδικό Node). Το CompositeNode.GetEnumerator() υποστηρίζει ένα απλό foreach πάνω στα άμεσα παιδιά ενός κόμβου όταν ένα ερώτημα XPath είναι περισσότερο από ό,τι χρειάζεται η εργασία.
Βήμα 6: Προσθήκη, Μετακίνηση και Αφαίρεση Κόμβων
Για να τροποποιήσετε το δέντρο, καλέστε το AppendChild(newChild) ή το PrependChild(newChild) για να προσθέσετε έναν κόμβο στην αρχή ή στο τέλος των παιδιών ενός container, και το InsertBefore(newChild, refChild) ή το InsertAfter(newChild, refChild) για να εισάγετε σχετικά με ένα υπάρχον παιδί. Το RemoveChild(oldChild) αφαιρεί ένα παιδί, και το RemoveAllChildren() εκκαθαρίζει όλα τα παιδιά ταυτόχρονα· το CompositeNode.IndexOf(child) αναφέρει τη θέση ενός παιδιού. Στο ίδιο το Node, το Clone(isCloneChildren) αντιγράφει έναν κόμβο – προαιρετικά συμπεριλαμβάνοντας τα παιδιά του – και το Remove() αποσυνδέει τον κόμβο από τον γονέα του.
Βήμα 7: Υλοποίηση Κόμβων Πριν την Τροποποίηση μιας Ζωντανής Συλλογής
Η τροποποίηση μιας συλλογής ενώ ένας βρόχος foreach την διασχίζει – είτε πρόκειται για NodeCollection είτε για το αποτέλεσμα του GetChildNodes – προκαλεί σφάλμα. Καλέστε το ToArray() στη συλλογή πρώτα για να υλοποιήσετε τους κόμβους σε έναν σταθερό πίνακα, στη συνέχεια διασχίστε αυτόν τον πίνακα καλώντας το Remove() ή κάνοντας άλλες αλλαγές στο δέντρο.
Βήμα 8: Σάρωση Υποδέντρου με Σειρά Εγγράφου
Node.NextPreOrder(rootNode) και PreviousPreOrder(rootNode) περνούν το δέντρο με σειρά εγγράφου, περιορισμένα από έναν δεδομένο ριζικό κόμβο – ένας συνηθισμένος τρόπος για να σαρώσετε ολόκληρο ένα υποδέντρο κόμβο-ανά-κόμβο χωρίς να γράψετε κώδικα αναδρομικής διαπλοκής.
Βήμα 9: Επεξεργασία Κάθε Τύπου Κόμβου με DocumentVisitor
Για την επεξεργασία πολλών διαφορετικών τύπων κόμβων με δομημένο τρόπο, δημιουργήστε μια υποκλάση της αφηρημένης κλάσης DocumentVisitor και παρακάμψτε τις μεθόδους Visit*Start / Visit*End για τους τύπους κόμβων που έχουν σημασία – για παράδειγμα VisitParagraphStart / VisitParagraphEnd, VisitSectionStart / VisitSectionEnd, VisitBodyStart / VisitBodyEnd – στη συνέχεια καλέστε το Node.Accept(visitor) στη ρίζα του υποδέντρου για να το εκτελέσετε. Αυτό είναι το τυπικό πρότυπο για εξαγωγή, μετασχηματισμό ή επιθεώρηση ενός εγγράφου χωρίς να γράφετε προσαρμοσμένη αναδρομική διαπλοκή για κάθε περίπτωση χρήσης.
Βήμα 10: Αντίδραση σε Δομικές Αλλαγές από Άλλο Κώδικα
Εφαρμόστε το INodeChangingCallback όταν ο κώδικας χρειάζεται να αντιδρά σε εισαγωγές ή αφαιρέσεις που έγιναν από άλλο κώδικα – συμπεριλαμβανομένων των ενσωματωμένων λειτουργιών – όχι μόνο σε αλλαγές που έγιναν άμεσα. Οι μέθοδοι NodeInserting(args), NodeInserted(args), NodeRemoving(args) και NodeRemoved(args) του παρέχουν ένα NodeChangingArgs που περιγράφει το επηρεαζόμενο Node, τον παλιό και τον νέο γονέα του, καθώς και το NodeChangingAction (Insert ή Remove) που συνέβη.
Κοινά Προβλήματα και Διορθώσεις
Η μετατροπή ενός Node σε CompositeNode προκαλεί σφάλμα μη έγκυρης μετατροπής Ο κόμβος είναι τύπου φύλλου – για παράδειγμα Run or FieldStart – που δεν μπορεί να κρατήσει παιδιά. Ελέγξτε Node.IsComposite πρώτα, ή χρησιμοποιήστε NodeType για να επιβεβαιώσετε ότι ο κόμβος είναι τύπου container πριν από τη μετατροπή.
GetChildNodes επιστρέφει άμεσους απογόνους όταν το isDeep είναι ψευδές isDeep αφήθηκε false (ή παραλείπεται όπου η υπερφόρτωση προεπιλέγει shallow). Δώστε isDeep: true to GetChildNodes() για να αναζητήσετε ολόκληρο το υποδέντρο αντί για άμεσα παιδιά.
Η τροποποίηση μιας συλλογής ενώ γίνεται επανάληψη πάνω της προκαλεί σφάλμα Κόμβοι προστέθηκαν ή αφαιρέθηκαν μέσα σε ένα foreach πάνω σε ένα NodeCollection ή το αποτέλεσμα του GetChildNodes. Κλήση ToArray() πρώτα για να υλοποιήσετε τους κόμβους που θα τροποποιήσετε, έπειτα επαναλάβετε πάνω σε αυτόν τον πίνακα ενώ μεταβάλλετε το δέντρο.
Μια υποκλάση DocumentVisitor δεν καλείται για κάποιο περιεχόμενο Ο επισκέπτης κλήθηκε μέσω Accept() σε έναν κόμβο που στην πραγματικότητα δεν περιέχει το επιθυμητό περιεχόμενο, ή το αντίστοιχο Visit* η μέθοδος δεν παρακάμφθηκε. Κλήση Accept() σε έναν πρόγονο που περιέχει το περιεχόμενο και παρακάμψτε κάθε Visit*Start / Visit*End ζεύγος σχετικό με τους τύπους κόμβων που επεξεργάζονται.
INodeChangingCallback δεν ειδοποιείται για μια αλλαγή Η callback αναφέρει μόνο αλλαγές στο Document για το οποίο καταγράφηκε. Επιβεβαιώστε ότι η callback είναι συνδεδεμένη με το σωστό Document αντικείμενο πριν συμβεί η αλλαγή, όχι μετά.
Συχνές Ερωτήσεις
Ποια είναι η διαφορά μεταξύ Node και CompositeNode;
Node είναι η βασική κλάση από την οποία κληρονομούν όλα τα στοιχεία του εγγράφου. CompositeNode επεκτείνει το Node για στοιχεία που μπορούν να περιέχουν παιδιά (όπως Body, Paragraph και Table); τα φύλλα στοιχεία όπως το Run κληρονομούν απευθείας το Node και δεν μπορούν να έχουν παιδιά.
Πώς μπορώ να βρω όλα τα nodes ενός συγκεκριμένου τύπου σε ένα έγγραφο;
Καλείστε CompositeNode.GetChildNodes(nodeType, isDeep) στον κόμβο που είναι η ρίζα της αναζήτησης – συχνά στον ίδιο τον Document – περνώντας το στόχο NodeType και isDeep: true για να αναζητήσετε ολόκληρο το υποδέντρο, όχι μόνο τα άμεσα παιδιά.
Πώς μπορώ να αφαιρέσω με ασφάλεια nodes ενώ κάνω επανάληψη;
Συλλέξτε πρώτα τα nodes που θα αφαιρεθούν σε έναν πίνακα – για παράδειγμα με NodeCollection.ToArray() – μετά επαναλάβετε πάνω σε αυτόν τον πίνακα και καλέστε Remove() σε κάθε node, αντί να τροποποιείτε τη ζωντανή συλλογή ενώ ένα foreach την επαναλαμβάνει.
Τι είναι οι κόμβοι FieldStart, FieldSeparator και FieldEnd;
Είναι τιμές NodeType που σηματοδοτούν τη μηχανική ενός πεδίου Word ενσωματωμένου στη ροή εκτέλεσης: τα FieldStart και FieldEnd δεσμεύουν το πεδίο, και το FieldSeparator διαχωρίζει τον κώδικα του πεδίου από το τρέχον εμφανιζόμενο αποτέλεσμα.
Πώς επεξεργάζομαι κάθε παράγραφο, πίνακα και run σε ένα έγγραφο;
Δημιουργήστε υποκλάση του DocumentVisitor, παρακάμψτε τις μεθόδους Visit*Start / Visit*End για τους απαιτούμενους τύπους κόμβων, στη συνέχεια καλέστε το Accept(visitor) στο Document (ή σε οποιαδήποτε ρίζα υποδέντρου) για να το εκτελέσετε.