A dokumentum csomópontfa kezelése
A dokumentumcsomópont-fa kezelése
Ez az útmutató bemutatja, hogyan lehet a dokumentum szerkezetét közvetlenül a csomópont-fán keresztül navigálni és manipulálni – az objektummodellt, amelyen a Document, Section, Paragraph, Run, Table és minden egyéb dokumentumelem alapul. A dokumentum minden eleme a Node származik, és minden, gyermekeket tartalmazni képes elem a CompositeNode származik, ezért ezen két alaposztály megértése megmagyarázza, hogyan lehet olyan tartalommal dolgozni, amelyet még egy dedikált segítő API sem fed le.
A Node és a CompositeNode alaposztályok
Node az absztrakt alaposztály minden objektum számára egy dokumentumfában. Közreadja a NodeType (egy enum érték, amely azonosítja, milyen típusú csomópont ez), a ParentNode (a környező CompositeNode), a Document (a tulajdonos dokumentum), valamint a PreviousSibling/NextSibling metódusokat a szintén ugyanazon szinten lévő csomópontok közötti mozgáshoz. A Node.IsComposite jelzi, hogy egy adott csomópont tartalmazhat-e gyermekeket. A CompositeNode kiterjeszti a Node konténerelemekhez – a FirstChild, LastChild és Count leírják a közvetlen gyermekeket, a HasChildNodes pedig jelzi, hogy léteznek-e. A CompositeNode.GetChildNodes(nodeType, isDeep) visszaadja egy adott NodeType összes gyermekét, opcionálisan a teljes alfa (isDeep) keresésével, nem csak a közvetlen gyermekeket, és a CompositeNode.GetChild(nodeType, index, isDeep) egyetlen elemet ad vissza index alapján.
A NodeType Enum
NodeType felsorolja a dokumentummodell által definiált minden csomópont típust – strukturális típusok, mint például Document, Section, Body, Paragraph, Table, Row és Cell; beágyazott tartalomtípusok, mint Run, Shape és Comment; valamint mező-mechanizmus típusok, mint FieldStart, FieldSeparator és FieldEnd, amelyek a Word mező határait és kapcsoló szövegét jelölik a futásfolyamban. Egy NodeType érték átadása a GetChildNodes vagy GetChild függvénynek a keresést pontosan arra a típusra korlátozza, vagy a NodeType.Any átadása minden csomópont típusra illeszkedik.
A fa bejárása és módosítása
CompositeNode.GetEnumerator() lehetővé teszi, hogy egy csomópont közvetlen gyermekein iteráljunk, és CompositeNode emellett megvalósítja a SelectNodes(xpath) és SelectSingleNode(xpath) funkciókat XPath-alapú lekérdezésekhez a részfában. A fa módosításához a AppendChild(newChild) és PrependChild(newChild) egy csomópontot adnak a gyerekek elejéhez vagy végéhez, a InsertBefore(newChild, refChild) és InsertAfter(newChild, refChild) egy meglévő gyerechez viszonyítva szúrnak be, a RemoveChild(oldChild) vagy RemoveAllChildren() pedig eltávolítja a csomópontokat. A CompositeNode.IndexOf(child) visszaadja egy gyermek pozícióját. A Node esetén a Clone(isCloneChildren) másolatot készít — opcionálisan mély másolatot —, a Remove() pedig leválasztja a csomópontot a szülőjéről. A Node.NextPreOrder(rootNode) és PreviousPreOrder(rootNode) a fát dokumentumsorrendben járják be, egy adott gyökércsomópont által korlátozva, ami gyakori módja annak, hogy egy egész részfát csomópontonként beolvassunk rekurzív kód nélkül.
Csomópontgyűjtemények és változásértesítések
NodeCollection egy konkrét, módosítható csomópontgyűjtemény, amely támogatja a Add(node), Insert(index, node), Remove(node), RemoveAt(index), Clear(), Contains(node), IndexOf(node) és ToArray() műveleteket, valamint egy Count tulajdonságot. A NodeList és NodeEnumerator olvasási stílusú iterációt biztosítanak a lekérdezési eredmények felett, például a SelectNodes által visszaadott csomópontok esetén. A strukturális változások megfigyeléséhez, ahogy azok bekövetkeznek, valósítsd meg a INodeChangingCallback — annak NodeInserting(args), NodeInserted(args), NodeRemoving(args) és NodeRemoved(args) metódusai mindegyike kap egy NodeChangingArgs objektumot, amely leírja az érintett Node, annak OldParent/NewParent, és a bekövetkezett NodeChangingAction.
Csomópontok felkeresése a DocumentVisitor segítségével
A fa kézi bejárása nélkül, minden csomóponttípus strukturált feldolgozásához származtass DocumentVisitor osztályt, és írd felül a Visit*Start/Visit*End metódusokat azokhoz a csomóponttípusokhoz, amelyek érdekelnek — VisitParagraphStart/VisitParagraphEnd, VisitTableStart/VisitTableEnd, VisitRun stb. — majd hívd meg a Node.Accept(visitor) metódust a részfa gyökerén, hogy végrehajtsa. Ez a szabványos minta a dokumentum exportálásához, átalakításához vagy vizsgálatához anélkül, hogy minden esethez egyedi rekurzív bejárást kellene írni.
Tippek és bevált gyakorlatok
- Használd a
NodeType.Anyelemet aGetChildNodes(NodeType.Any, true)-vel, ha minden leszármazottat szükséges elérni típusfüggetlenül, ahelyett, hogy aGetChildNodes-t típusonként egyszer hívnád meg. - Részfák lapos, nem rekurzív beolvasásához részesítsd előnyben a
Node.NextPreOrder(rootNode)/PreviousPreOrder(rootNode)megoldást, ahelyett, hogy kézi rekurzív leereszkedést írnál. - Implementálja a
DocumentVisitorelemet az egyedi, fastruktúrán járó kód helyett, ha ugyanazt a feldolgozást sok különböző csomóponttípuson kell végrehajtani. - Ellenőrizze a
Node.IsCompositeértékét, mielőtt aCompositeNodetípusra konvertálna, ismeretlen típusú csomópont esetén. - Regisztráljon egy
INodeChangingCallbackelemet, ha reagálnia kell a más kód által (beleértve a beépített műveleteket) végrehajtott beszúrásokra vagy eltávolításokra, nem csak a saját kódja által közvetlenül végzett változásokra.
Gyakori problémák
| Probléma | Ok | Javítás |
|---|---|---|
A Node CompositeNode-ra történő átkonvertálása invalid-cast hibát eredményez | A csomópont egy levél típus (például Run vagy FieldStart), amely nem tarthat gyermekeket | Először ellenőrizze a Node.IsComposite-t, vagy használja a NodeType-t, hogy megerősítse, a csomópont tárolótípus-e, mielőtt átkonvertálná |
GetChildNodes csak közvetlen gyermekeket ad vissza | isDeep false maradt (vagy kihagyva, ahol a túlterhelés alapértelmezettként sekély) | Adja át a isDeep: true értéket a teljes alfa kereséséhez |
| A gyűjtemény módosítása iterálás közben hibát okoz | Csomópontok lettek hozzáadva vagy eltávolítva egy foreach NodeCollection vagy a GetChildNodes eredménye alatt | Először hozza létre a módosítandó csomópontokat a ToArray() segítségével, majd iteráljon a tömbön, miközben módosítja a fát |
Egy DocumentVisitor alosztály nem kerül meghívásra bizonyos tartalom esetén | A látogatót a Accept() útján hívták meg egy olyan csomóponton, amely nem tartalmazza a cél tartalmat, vagy a megfelelő Visit* metódust nem írták felül | Hívja meg a Accept() függvényt egy olyan ősön, amely tartalmazza a tartalmat, és írja felül az összes a feldolgozott csomóponttípusokhoz kapcsolódó Visit*Start/Visit*End párt |
FAQ
Mi a különbség a Node és a CompositeNode között?
Node az az alaposztály, amelyből minden dokumentumelem származik. CompositeNode kiterjeszti a Node osztályt olyan elemekhez, amelyek gyermekeket tudnak tartalmazni (például Body, Paragraph és Table); a levél elemek (például Run) közvetlenül a Node osztályból származnak, és nem tarthatnak gyermekeket.
Hogyan találhatom meg egy dokumentumban egy adott típusú összes csomópontot?
Hívd meg a(z) CompositeNode.GetChildNodes(nodeType, isDeep) függvényt azon a csomóponton, amely a keresésed gyökere (gyakran maga a Document), átadva a kívánt NodeType-t és a isDeep: true-t, hogy az egész részfa legyen keresve, nem csak a közvetlen gyermekek.
Hogyan tudok biztonságosan eltávolítani csomópontokat iterálás közben?
Gyűjtsd először egy tömbbe az eltávolítandó csomópontokat — például a(z) NodeCollection.ToArray() segítségével — majd iterálj végig azon a tömbön, és hívd meg a(z) Remove() függvényt minden egyes csomóponton, ahelyett, hogy a foreach iterálás közben módosítaná az élő gyűjteményt.
Mik azok a FieldStart, FieldSeparator és FieldEnd csomópontok?
Ezek NodeType értékek, amelyek a futási adatfolyamban beágyazott Word mező mechanikáját jelölik: a FieldStart és a FieldEnd kötik össze a mezőt, a FieldSeparator pedig elválasztja a mező kódját a jelenleg megjelenített eredménytől.
Hogyan dolgozom fel minden bekezdést, táblázatot és run-t egy dokumentumban?
Származtass le a(z) DocumentVisitor osztályból, felülírd a(z) VisitParagraphStart/VisitParagraphEnd, a(z) VisitTableStart/VisitTableEnd és a(z) VisitRun metódusokat a szükséges csomóponttípusokhoz, majd hívd meg a(z) Accept(visitor) függvényt a(z) Document (vagy bármely részfa gyöke) objektumon, hogy lefusson.
API Reference összefoglaló
| Osztály/Módszer | Leírás |
|---|---|
Node | Absztrakt alaposztály minden dokumentumfa csomóponthoz |
CompositeNode | Alaposztály azoknak a csomópontoknak, amelyek gyermekeket tartalmazhatnak |
CompositeNode.GetChildNodes(nodeType, isDeep) | Az adott típusú összes gyermek lekérése, opcionálisan a teljes részfán belül |
CompositeNode.AppendChild(newChild) / InsertBefore(newChild, refChild) | Csomópont hozzáadása egy konténerhez a végén, vagy egy meglévő gyermek előtt/után |
NodeType | Enum, amely meghatározza egy csomópont típusát (Paragraph, Table, Run, FieldStart, és így tovább) |
NodeCollection | Konkrét, módosítható Node objektumok gyűjteménye |
Node.Clone(isCloneChildren) | Másolj egy csomópontot, opcionálisan beleértve a gyermekeket |
Node.NextPreOrder(rootNode) / PreviousPreOrder(rootNode) | Haladj végig egy részfán a dokumentum sorrendjében |
INodeChangingCallback | Callback interfész, amely értesül, amikor csomópontok kerülnek beszúrásra vagy eltávolításra |
DocumentVisitor | Alaposztály strukturált, típus-alapú diszpécselésű bejáráshoz a Node.Accept(visitor) segítségével |