Hoe te werken met knooppunten in .NET

Hoe te werken met knooppunten in .NET

Deze gids laat zien hoe je een Word-document’s knooppuntboom direct kunt doorlopen, bevragen en wijzigen in Aspose.Words FOSS voor .NET, met behulp van de Node and CompositeNode basis-klassen die Document, Section, Paragraph, Table, en elk ander documentelement zijn opgebouwd. Het behandelt het afbakenen van een zoekopdracht door NodeType, knooppunten programmeerbaar toevoegen en verwijderen, reageren op structurele wijzigingen, en het gebruiken DocumentVisitor voor type-dispatched traversie.

Stap-voor-stap gids

Stap 1: Installeer het pakket

Aspose.Words FOSS for .NET publiceert nog geen NuGet pakket – bouw de bibliotheek in plaats daarvan vanuit de bron. Clone https://github.com/aspose-words-foss/Aspose.Words-FOSS-for-.NET.git, bouw vervolgens Aspose.Words.sln in Release-configuratie met de .NET SDK en verwijs naar de resulterende Aspose.Words assembly vanuit je project. De bibliotheek richt zich op .NET Standard 2.0, dus draait hij op .NET Framework 4.6.2+ en .NET 6/8/10.


Stap 2: Importeer vereiste klassen

Voeg een using Aspose.Words; directive toe – Node, CompositeNode, NodeType, NodeCollection, NodeList, INodeChangingCallback en DocumentVisitor bevinden zich allemaal in de Aspose.Words namespace naast Document.


Stap 3: Begrijp de Node en CompositeNode Basis Klassen

Elk object in een documentboom is afgeleid van de abstracte Node klasse, die NodeType blootlegt (die aangeeft wat voor type node het is), ParentNode (de omvattende CompositeNode), Document (het eigenaar-document), en PreviousSibling / NextSibling voor het verplaatsen over nodes op hetzelfde niveau. Controleer Node.IsComposite om te achterhalen of een gegeven node kinderen kan bevatten voordat je deze cast. CompositeNode breidt Node uit voor container-elementen – FirstChild, LastChild en Count beschrijven de directe kinderen, en HasChildNodes meldt of er al dan niet welke bestaan.


Stap 4: Vraag kinderen op type op

Roep CompositeNode.GetChildNodes(nodeType, isDeep) aan om elk kind van een gegeven NodeType op te halen, waarbij isDeep: true wordt doorgegeven om de volledige subtree te doorzoeken in plaats van alleen directe kinderen, of NodeType.Any om elk node-type te matchen ongeacht het soort. CompositeNode.GetChild(nodeType, index, isDeep) haalt een enkel passend kind op basis van index op. Voor structurele node-types (Document, Section, Body, Paragraph, Table, Row, Cell), inline-content-types (Run, Shape, Comment), en veld-machinerietypes (FieldStart, FieldSeparator, FieldEnd, die de grenzen van een Word-veld en switch-tekst in de run-stroom markeren), geef de specifieke NodeType waarde door die aangeeft wat je zoekt.


Stap 5: Voer XPath-queries uit over een subtree

CompositeNode implementeert ook SelectNodes(xpath) en SelectSingleNode(xpath) voor op XPath gebaseerde queries over de subtree, en retourneert overeenkomsten als een NodeList (of een enkele Node). CompositeNode.GetEnumerator() ondersteunt een eenvoudige foreach over de directe kinderen van een node wanneer een XPath-query meer is dan de taak vereist.


Stap 6: Voeg toe, verplaats en verwijder nodes

Om de boom te wijzigen, roep je AppendChild(newChild) of PrependChild(newChild) aan om een node toe te voegen aan het begin of einde van de kinderen van een container, en InsertBefore(newChild, refChild) of InsertAfter(newChild, refChild) om in te voegen relatief ten opzichte van een bestaand kind. RemoveChild(oldChild) verwijdert één kind, en RemoveAllChildren() wist alle kinderen tegelijk; CompositeNode.IndexOf(child) meldt de positie van een kind. Op Node zelf, Clone(isCloneChildren) kopieert een node – optioneel inclusief zijn kinderen – en Remove() ontkoppelt de node van zijn ouder.


Stap 7: Nodes materialiseren vóór het muteren van een live collectie

Een collectie wijzigen terwijl een foreach-lus eroverheen itereert — of het nu een NodeCollection is of het resultaat van GetChildNodes — veroorzaakt een fout. Roep eerst ToArray() op de collectie aan om de nodes te materialiseren naar een vaste array, en itereer vervolgens over die array terwijl je Remove() aanroept of andere wijzigingen in de boom maakt.


Stap 8: Subboom scannen in documentvolgorde

Node.NextPreOrder(rootNode) en PreviousPreOrder(rootNode) doorlopen de boom in documentvolgorde, begrensd door een opgegeven knoop als wortel — een gebruikelijke manier om een volledige subboom knoop voor knoop te scannen zonder recursieve traversalcodes te schrijven.


Stap 9: Elk knooptype verwerken met DocumentVisitor

Om veel verschillende knooptypes op een gestructureerde manier te verwerken, maak een subklasse van de abstracte DocumentVisitor-klasse en overschrijf de Visit*Start / Visit*End-methoden voor de knooptypes die relevant zijn — bijvoorbeeld VisitParagraphStart / VisitParagraphEnd, VisitSectionStart / VisitSectionEnd, VisitBodyStart / VisitBodyEnd — roep vervolgens Node.Accept(visitor) aan op de wortel van de subboom om deze uit te voeren. Dit is het standaardpatroon voor het exporteren, transformeren of inspecteren van een document zonder aangepaste recursieve traversals te schrijven voor elk gebruiksgeval.


Stap 10: Reageer op structurele wijzigingen van andere code

Implementeer INodeChangingCallback wanneer code moet reageren op invoegingen of verwijderingen die door andere code zijn uitgevoerd — inclusief ingebouwde bewerkingen — niet alleen op directe wijzigingen. Zijn NodeInserting(args), NodeInserted(args), NodeRemoving(args) en NodeRemoved(args) methoden ontvangen elk een NodeChangingArgs die de getroffen Node beschrijft, zijn oude en nieuwe ouder, en de NodeChangingAction (Insert of Remove) die heeft plaatsgevonden.

Veelvoorkomende problemen en oplossingen

Het casten van een Node naar CompositeNode veroorzaakt een invalid-cast error De knoop is een bladtype – bijvoorbeeld Run or FieldStart – die geen kinderen kan bevatten. Controleer Node.IsComposite eerst, of gebruik NodeType om te bevestigen dat de knoop een containertype is voordat je cast.

GetChildNodes retourneert directe kinderen wanneer isDeep false is isDeep werd weggelaten false (of weggelaten waar de overload standaard ondiep is). Geef isDeep: true to GetChildNodes() om de volledige subboom te doorzoeken in plaats van directe kinderen.

Het wijzigen van een collectie tijdens het itereren erover veroorzaakt een fout Knooppunten werden toegevoegd of verwijderd binnen een foreach over een NodeCollection of het resultaat van GetChildNodes. Roep ToArray() eerst om de knooppunten die moeten worden gewijzigd te materialiseren, vervolgens over die array itereren terwijl de boom wordt gemuteerd.

Een DocumentVisitor subklasse wordt niet aangeroepen voor bepaalde inhoud De bezoeker werd aangeroepen via Accept() op een knooppunt dat de doelinhoud eigenlijk niet bevat, of de overeenkomstige Visit* methode niet was overschreven. Roep Accept() op een voorouder die de inhoud bevat, en overschrijf elke Visit*Start / Visit*End paar relevant voor de knooppunttypen die worden verwerkt.

INodeChangingCallback wordt niet op de hoogte gesteld van een wijziging De callback rapporteert alleen wijzigingen op de Document waartegen deze is geregistreerd. Bevestig dat de callback is gekoppeld aan de juiste Document instantie voordat de wijziging plaatsvindt, niet erna.

Veelgestelde vragen

Wat is het verschil tussen Node en CompositeNode?

Node is de basisklasse waar elk documenten element van afgeleid is. CompositeNode breidt Node uit voor elementen die kinderen kunnen bevatten (zoals Body, Paragraph en Table); blad-elementen zoals Run worden direct afgeleid van Node en kunnen geen kinderen bevatten.

Hoe vind ik alle nodes van een specifiek type in een document?

Roep CompositeNode.GetChildNodes(nodeType, isDeep) aan op de node die de zoekopdracht wortelt – vaak de Document zelf – en geef de doel-NodeType en isDeep: true door om de hele subboom te doorzoeken, niet alleen directe kinderen.

Hoe kan ik veilig nodes verwijderen tijdens het itereren?

Verzamel eerst de te verwijderen nodes in een array – bijvoorbeeld met NodeCollection.ToArray() – en iterereer vervolgens over die array en roep Remove() aan op elke node, in plaats van de live-collectie te wijzigen terwijl een foreach erdoorheen iterereert.

Wat zijn FieldStart, FieldSeparator en FieldEnd nodes?

Het zijn NodeType-waarden die de mechanismen van een Word-veld markeren dat in de run-stream is ingebed: FieldStart en FieldEnd binden het veld, en FieldSeparator scheidt de code van het veld van het momenteel weergegeven resultaat.

Hoe verwerk ik elke alinea, tabel en run in een document?

Subclass DocumentVisitor, overschrijf de Visit*Start / Visit*End methoden voor de benodigde knooptype, roep vervolgens Accept(visitor) aan op de Document (of een willekeurige subboomwortel) om deze uit te voeren.

Zie ook

 Nederlands