.NET에서 노드 작업 방법

.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을(를) 클론한 뒤, .NET SDK를 사용하여 Release 구성으로 Aspose.Words.sln을 빌드하고, 결과물인 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는 모두 Aspose.Words 네임스페이스에 Document와 함께 존재합니다.


3단계: 노드 및 CompositeNode 기본 클래스 이해

문서 트리의 모든 객체는 추상 Node 클래스를 상속받으며, 이 클래스는 NodeType(노드 유형을 식별), ParentNode(포함하는 CompositeNode), Document(소유 문서), 그리고 동일 레벨의 노드를 이동하기 위한 PreviousSibling/NextSibling을 노출합니다. 노드를 캐스팅하기 전에 해당 노드가 자식을 가질 수 있는지 확인하려면 Node.IsComposite을 확인하십시오. CompositeNode은 컨테이너 요소를 위해 Node를 확장하며 — 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은 또한 서브트리 전체에 대한 XPath 기반 쿼리를 수행하기 위해 SelectNodes(xpath) 및 SelectSingleNode(xpath)를 구현하며, 일치 결과를 NodeList(또는 단일 Node) 형태로 반환합니다. XPath 쿼리가 필요 이상일 때, CompositeNode.GetEnumerator()는 노드의 직접 자식에 대해 단순 foreach을 지원합니다.


6단계: 노드 추가, 이동 및 제거

트리를 수정하려면, 컨테이너 자식의 시작이나 끝에 노드를 추가하기 위해 AppendChild(newChild) 또는 PrependChild(newChild)을 호출하고, 기존 자식에 상대적으로 삽입하려면 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)은 주어진 루트 노드에 의해 제한된 문서 순서대로 트리를 순회합니다 — 재귀 순회 코드를 작성하지 않고 전체 서브트리를 노드별로 스캔하는 일반적인 방법입니다.


Step 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) 메서드는 각각 영향을 받은 Node을 설명하는 NodeChangingArgs를 받아, 이전 및 새로운 부모와 발생한 NodeChangingAction(Insert 또는 Remove)를 전달합니다.

일반적인 문제 및 해결책

Node를 CompositeNode로 캐스팅하면 잘못된 캐스팅 오류가 발생합니다 노드는 leaf 타입입니다 – 예를 들어 Run or FieldStart – 자식 노드를 가질 수 없습니다. 확인하세요 Node.IsComposite 먼저, 또는 사용하세요 NodeType 노드가 컨테이너 타입인지 확인한 후 캐스팅합니다.

GetChildNodes는 isDeep가 false일 때 직접 자식을 반환합니다 isDeep 남겨졌습니다 false (또는 오버로드가 shallow를 기본값으로 할 때 생략됩니다). 전달하세요 isDeep: true to GetChildNodes() 즉시 자식 대신 전체 서브트리를 검색합니다.

컬렉션을 순회하면서 수정하면 오류가 발생합니다. 노드가 내부에서 추가되거나 제거되었습니다 a foreach over a NodeCollection 또는 결과 GetChildNodes. 호출 ToArray() 먼저 수정할 노드를 실체화하고, 그런 다음 트리를 변형하면서 해당 배열을 순회합니다.

A DocumentVisitor 서브클래스가 일부 콘텐츠에 대해 호출되지 않습니다. 방문자가 via 로 호출되었습니다. Accept() 실제로 대상 콘텐츠를 포함하고 있지 않은 노드에서, 또는 해당 Visit* 메서드가 재정의되지 않았습니다. 호출 Accept() 콘텐츠를 포함하는 상위 요소에서, 그리고 모든 Visit*Start / Visit*End 처리 중인 노드 유형과 관련된 쌍을.

INodeChangingCallback은 변경 사항에 대해 알림을 받지 않습니다 콜백은 해당 Document 등록된 대상에 대해서만 보고합니다. 콜백이 올바른 Document 인스턴스에 변경이 발생하기 전에 연결되어 있는지 확인하십시오, 이후가 아니라.

자주 묻는 질문

Node와 CompositeNode의 차이점은 무엇인가요?

Node은 모든 문서 요소가 파생되는 기본 클래스입니다. CompositeNode은 자식 요소를 포함할 수 있는 요소에 대해 Node를 확장합니다(예: Body, Paragraph, Table); Run와 같은 리프 요소는 Node에서 직접 파생되며 자식을 보유할 수 없습니다.

문서에서 특정 유형의 모든 노드를 찾으려면 어떻게 해야 하나요?

CompositeNode.GetChildNodes(nodeType, isDeep)을(를) 검색의 루트가 되는 노드에 호출하십시오 – 보통 Document 자체입니다 – 대상 NodeType와 isDeep: true을 전달하여 전체 서브트리를 검색하도록 하고, 직접 자식만 검색하지 않도록 합니다.

반복하면서 노드를 안전하게 제거하려면 어떻게 해야 하나요?

제거할 노드를 먼저 배열에 수집하십시오 – 예를 들어 NodeCollection.ToArray()을(를) 사용하여 – 그런 다음 해당 배열을 반복하면서 각 노드에 Remove()을(를) 호출합니다. foreach가 반복 중에 실시간 컬렉션을 수정하는 대신에.

FieldStart, FieldSeparator, 및 FieldEnd 노드는 무엇인가요?

그들은 실행 스트림에 삽입된 Word 필드의 메커니즘을 표시하는 NodeType 값입니다: FieldStart과 FieldEnd가 필드를 바인딩하고, FieldSeparator는 필드 코드와 현재 표시된 결과를 구분합니다.

문서에서 모든 단락, 표 및 실행을 어떻게 처리합니까?

DocumentVisitor을(를) 서브클래스화하고, 필요한 노드 유형에 대해 Visit*Start / Visit*End 메서드를 재정의한 다음, Accept(visitor)을(를) Document(또는 임의의 서브트리 루트)에 호출하여 실행합니다.

참조

 한국어