큰 XML 파일을 처리해야 하는 경우 전체 XML 트리를 메모리에 로드하는 것이 가능하지 않을 수 있습니다. 이 문서에서는 C# 및 Visual Basic에서 XmlReader를 사용하여 조각을 스트리밍하는 방법을 보여 줍니다.
XmlReader를 사용하여 XElement 개체를 읽는 가장 효과적인 방법 중 하나는 사용자 지정 축 메서드를 직접 작성하는 것입니다. 일반적으로 축 메서드는 이 문서의 예에 나와 있는 대로 IEnumerable<T>의 XElement와 같은 컬렉션을 반환합니다. 사용자 지정 축 메서드에서는 ReadFrom 메서드를 호출하여 XML 조각을 만든 후 yield return
을 사용하여 컬렉션을 반환합니다. 이것은 사용자 지정 축 메서드에 지연된 실행 의미를 제공합니다.
XmlReader 개체에서 XML 트리를 만드는 경우 XmlReader가 요소에 배치되어야 합니다. ReadFrom 메서드는 요소의 닫기 태그를 읽을 때까지 반환되지 않습니다.
부분 트리를 만들려는 경우 XmlReader를 인스턴스화하고 XElement 트리로 변환할 노드에 판독기를 배치한 다음 XElement 개체를 만들 수 있습니다.
헤더 정보에 액세스하여 XML 조각을 스트리밍하는 방법 문서에는 더 복잡한 문서 스트리밍에 대한 정보가 포함되어 있습니다.
큰 XML 문서의 스트리밍 변환을 수행하는 방법 문서에는 LINQ to XML을 사용하여 작은 메모리 공간을 유지하면서 매우 큰 XML 문서를 변환하는 예가 포함되어 있습니다.
예: 사용자 지정 축 메서드 만들기
이 예제에서는 사용자 지정 축 메서드를 만듭니다. LINQ 쿼리를 사용하여 이 메서드를 쿼리할 수 있습니다. 사용자 지정 축 메서드 StreamRootChildDoc
는 반복되는 Child
요소가 있는 문서를 읽을 수 있습니다.
using System.Xml;
using System.Xml.Linq;
static IEnumerable<XElement> StreamRootChildDoc(StringReader stringReader)
{
using XmlReader reader = XmlReader.Create(stringReader);
reader.MoveToContent();
// Parse the file and display each of the nodes.
while (true)
{
// If the current node is an element and named "Child"
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Child")
{
// Get the current node and advance the reader to the next
if (XNode.ReadFrom(reader) is XElement el)
yield return el;
}
else if (!reader.Read())
break;
}
}
string markup = """
<Root>
<Child Key="01">
<GrandChild>aaa</GrandChild>
</Child>
<Child Key="02">
<GrandChild>bbb</GrandChild>
</Child>
<Child Key="03">
<GrandChild>ccc</GrandChild>
</Child>
</Root>
""";
IEnumerable<string> grandChildData =
from el in StreamRootChildDoc(new StringReader(markup))
where (int)el.Attribute("Key") > 1
select (string)el.Element("GrandChild");
foreach (string str in grandChildData)
Console.WriteLine(str);
Imports System.Xml
Module Module1
Public Iterator Function StreamRootChildDoc(stringReader As IO.StringReader) As IEnumerable(Of XElement)
Using reader As XmlReader = XmlReader.Create(stringReader)
reader.MoveToContent()
' Parse the file and display each of the nodes.
While True
' If the current node is an element and named "Child"
If reader.NodeType = XmlNodeType.Element And reader.Name = "Child" Then
' Get the current node and advance the reader to the next
Dim el As XElement = TryCast(XNode.ReadFrom(reader), XElement)
If (el IsNot Nothing) Then
Yield el
End If
ElseIf Not reader.Read() Then
Exit While
End If
End While
End Using
End Function
Sub Main()
Dim markup = "<Root>
<Child Key=""01"">
<GrandChild>aaa</GrandChild>
</Child>
<Child Key=""02"">
<GrandChild>bbb</GrandChild>
</Child>
<Child Key=""03"">
<GrandChild>ccc</GrandChild>
</Child>
</Root>"
Dim grandChildData =
From el In StreamRootChildDoc(New IO.StringReader(markup))
Where CInt(el.@Key) > 1
Select el.<GrandChild>.Value
For Each s In grandChildData
Console.WriteLine(s)
Next
End Sub
End Module
이 예제는 다음과 같은 출력을 생성합니다.
bbb
ccc
이 예에 사용된 기술은 수백만 개의 Child
요소에 대해서도 작은 메모리 공간을 유지합니다.
참고 항목
.NET