Como Trabalhar com Nós em .NET

Como Trabalhar com Nós em .NET

Este guia mostra como percorrer, consultar e modificar a árvore de nós de um documento Word diretamente em Aspose.Words FOSS para .NET, usando o Node and CompositeNode classes base que Document, Section, Paragraph, Table, e todos os demais elementos do documento são construídos sobre. Ele cobre a delimitação de uma pesquisa por NodeType, adicionando e removendo nós programaticamente, reagindo a mudanças estruturais e usando DocumentVisitor para travessia baseada em despacho de tipo.

Guia passo a passo

Etapa 1: Instalar o pacote

Aspose.Words FOSS for .NET ainda não publica um pacote NuGet – compile a biblioteca a partir do código-fonte em vez disso. Clone https://github.com/aspose-words-foss/Aspose.Words-FOSS-for-.NET.git, então compile Aspose.Words.sln na configuração Release com o SDK .NET e referencie a assembly Aspose.Words resultante no seu projeto. A biblioteca tem como alvo .NET Standard 2.0, portanto roda em .NET Framework 4.6.2+ e .NET 6/8/10.


Etapa 2: Importar classes necessárias

Adicione uma diretiva using Aspose.Words; – Node, CompositeNode, NodeType, NodeCollection, NodeList, INodeChangingCallback e DocumentVisitor estão todos no namespace Aspose.Words ao lado de Document.


Etapa 3: Entenda o Nó e as Classes Base CompositeNode

Todo objeto em uma árvore de documento deriva da classe abstrata Node, que expõe NodeType (identificando que tipo de nó é), ParentNode (o CompositeNode que o contém), Document (o documento proprietário) e PreviousSibling / NextSibling para mover-se entre nós no mesmo nível. Verifique Node.IsComposite para descobrir se um determinado nó pode conter filhos antes de convertê-lo. CompositeNode estende Node para elementos contêiner — FirstChild, LastChild e Count descrevem seus filhos imediatos, e HasChildNodes informa se algum existe.


Etapa 4: Consulte Filhos por Tipo

Chame CompositeNode.GetChildNodes(nodeType, isDeep) para recuperar cada filho de um determinado NodeType, passando isDeep: true para pesquisar toda a subárvore em vez de apenas filhos diretos, ou NodeType.Any para corresponder a todos os tipos de nó independentemente da categoria. CompositeNode.GetChild(nodeType, index, isDeep) recupera um único filho correspondente por índice. Para tipos de nó estruturais (Document, Section, Body, Paragraph, Table, Row, Cell), tipos de conteúdo inline (Run, Shape, Comment), e tipos de maquinaria de campo (FieldStart, FieldSeparator, FieldEnd, que marcam os limites de um campo Word e o texto de alternância no fluxo de execução), passe o valor específico NodeType que identifica o que você está procurando.


Etapa 5: Execute Consultas XPath em uma Subárvore

CompositeNode também implementa SelectNodes(xpath) e SelectSingleNode(xpath) para consultas baseadas em XPath atravessando a subárvore, retornando correspondências como um NodeList (ou um único Node). CompositeNode.GetEnumerator() suporta um simples foreach sobre os filhos diretos de um nó quando uma consulta XPath excede as necessidades da tarefa.


Etapa 6: Adicionar, Mover e Remover Nós

Para modificar a árvore, chame AppendChild(newChild) ou PrependChild(newChild) para adicionar um nó no início ou no final dos filhos de um contêiner, e InsertBefore(newChild, refChild) ou InsertAfter(newChild, refChild) para inserir em relação a um filho existente. RemoveChild(oldChild) remove um filho, e RemoveAllChildren() limpa todos os filhos de uma vez; CompositeNode.IndexOf(child) informa a posição de um filho. No próprio Node, Clone(isCloneChildren) copia um nó — opcionalmente incluindo seus filhos — e Remove() desanexa o nó de seu pai.


Etapa 7: Materializar nós antes de mutar uma coleção ao vivo

Modificar uma coleção enquanto um loop foreach está iterando sobre ela – seja um NodeCollection ou o resultado de GetChildNodes – gera um erro. Chame ToArray() na coleção primeiro para materializar os nós em um array fixo, então itere sobre esse array chamando Remove() ou fazendo outras alterações na árvore.


Etapa 8: Percorrer uma subárvore em ordem de documento

Node.NextPreOrder(rootNode) e PreviousPreOrder(rootNode) avançam pela árvore em ordem de documento, limitados por um nó raiz fornecido – uma forma comum de percorrer toda uma subárvore nó a nó sem escrever código de travessia recursiva.


Etapa 9: Processar cada tipo de nó com DocumentVisitor

Para processar muitos tipos diferentes de nós de forma estruturada, crie uma subclasse da classe abstrata DocumentVisitor e sobrescreva os métodos Visit*Start / Visit*End para os tipos de nó que importam – por exemplo VisitParagraphStart / VisitParagraphEnd, VisitSectionStart / VisitSectionEnd, VisitBodyStart / VisitBodyEnd – então chame Node.Accept(visitor) na raiz da subárvore para executá-lo. Este é o padrão usual para exportar, transformar ou inspecionar um documento sem escrever travessia recursiva personalizada para cada caso de uso.


Etapa 10: Reagir a alterações estruturais de outro código

Implemente INodeChangingCallback quando o código precisa reagir a inserções ou remoções feitas por outro código – incluindo operações internas – não apenas mudanças feitas diretamente. Seus métodos NodeInserting(args), NodeInserted(args), NodeRemoving(args) e NodeRemoved(args) recebem cada um um NodeChangingArgs descrevendo o Node afetado, seu pai antigo e novo, e o NodeChangingAction (Insert ou Remove) que ocorreu.

Problemas Comuns e Soluções

Converter um Node para CompositeNode lança um erro de conversão inválida O nó é do tipo folha – por exemplo Run or FieldStart – que não pode conter filhos. Verifique Node.IsComposite primeiro, ou use NodeType para confirmar que o nó é do tipo container antes de fazer o cast.

GetChildNodes retorna filhos diretos quando isDeep for false isDeep foi deixado false (ou omitido onde a sobrecarga tem padrão shallow). Passe isDeep: true to GetChildNodes() para pesquisar toda a subárvore em vez dos filhos imediatos.

Modificar uma coleção enquanto se itera sobre ela gera um erro Nós foram adicionados ou removidos dentro de um foreach sobre um NodeCollection ou o resultado de GetChildNodes. Chame ToArray() primeiro para materializar os nós a serem modificados, depois itere sobre esse array enquanto altera a árvore.

Uma subclasse DocumentVisitor não é chamada para algum conteúdo O visitante foi invocado via Accept() em um nó que realmente não contém o conteúdo alvo, ou o correspondente Visit* método não foi sobrescrito. Chame Accept() em um ancestral que contém o conteúdo, e sobrescreva todos os Visit*Start / Visit*End par relevante aos tipos de nó que estão sendo processados.

INodeChangingCallback não é notificado sobre uma alteração O callback apenas relata alterações no Document contra o qual foi registrado. Confirme se o callback está anexado ao correto Document instância antes que a alteração ocorra, não depois.

Perguntas Frequentes

Qual é a diferença entre Node e CompositeNode?

Node é a classe base da qual todo elemento de documento herda. CompositeNode estende Node para elementos que podem conter filhos (como Body, Paragraph e Table); elementos folha como Run derivam diretamente de Node e não podem conter filhos.

Como encontro todos os nós de um tipo específico em um documento?

Chame CompositeNode.GetChildNodes(nodeType, isDeep) no nó que origina a pesquisa — frequentemente o próprio Document — passando o NodeType e isDeep: true alvo para pesquisar toda a subárvore, não apenas os filhos diretos.

Como removo nós com segurança enquanto itero?

Colete os nós a serem removidos em um array primeiro — por exemplo com NodeCollection.ToArray() — depois itere sobre esse array e chame Remove() em cada nó, em vez de modificar a coleção ao vivo enquanto um foreach a itera.

O que são nós FieldStart, FieldSeparator e FieldEnd?

Eles são valores NodeType que marcam a mecânica de um campo Word incorporado no fluxo de execução: FieldStart e FieldEnd delimitam o campo, e FieldSeparator separa o código do campo de seu resultado atualmente exibido.

Como processar cada parágrafo, tabela e run em um documento?

Crie uma subclasse de DocumentVisitor, substitua os métodos Visit*Start / Visit*End para os tipos de nó necessários, então chame Accept(visitor) no Document (ou em qualquer raiz de subárvore) para executá-lo.

Ver também

 Português