다음을 통해 공유


XStreamingElement 클래스

정의

XML 트리에서 지연된 스트리밍 출력을 지원하는 요소를 나타냅니다.

public ref class XStreamingElement
public class XStreamingElement
type XStreamingElement = class
Public Class XStreamingElement
상속
XStreamingElement

예제

다음 예제에서는 먼저 원본 XML 트리를 만듭니다. 그런 다음 , 를 사용하여 XElement원본 XML 트리의 변환을 만듭니다. 이 변환은 메모리에 새 트리를 만듭니다. 그런 다음 , 를 사용하여 XStreamingElement원본 XML 트리의 변환을 만듭니다. 이 변환은 변환된 트리가 콘솔로 직렬화될 때까지 쿼리를 실행하지 않습니다. 메모리 사용량이 적습니다.

XElement srcTree = new XElement("Root",  
                       new XElement("Child", 1),  
                       new XElement("Child", 2),  
                       new XElement("Child", 3),  
                       new XElement("Child", 4),  
                       new XElement("Child", 5)  
                   );  

XElement dstTree1 = new XElement("NewRoot",  
                        from el in srcTree.Elements()  
                        where (int)el >= 3  
                        select new XElement("DifferentChild", (int)el)  
                    );  

XStreamingElement dstTree2 = new XStreamingElement("NewRoot",  
                        from el in srcTree.Elements()  
                        where (int)el >= 3  
                        select new XElement("DifferentChild", (int)el)  
                    );  

Console.WriteLine(dstTree1);  
Console.WriteLine("------");  
Console.WriteLine(dstTree2);  
Dim srcTree As XElement = _  
        <Root>  
            <Child>1</Child>  
            <Child>2</Child>  
            <Child>3</Child>  
            <Child>4</Child>  
            <Child>5</Child>  
        </Root>  

Dim dstTree1 As XElement = _  
    <NewRoot>  
        <%= From el In srcTree.Elements _  
            Where (el.Value >= 3) _  
            Select <DifferentChild><%= el.Value %></DifferentChild> %>  
    </NewRoot>  

Dim dstTree2 As XStreamingElement = New XStreamingElement("NewRoot", _  
                From el In srcTree.Elements _  
                Where el.Value >= 3 _  
                Select <DifferentChild><%= el.Value %></DifferentChild> _  
            )  

Console.WriteLine(dstTree1)  
Console.WriteLine("------")  
Console.WriteLine(dstTree2)  

이 예제는 다음과 같은 출력을 생성합니다.

<NewRoot>  
  <DifferentChild>3</DifferentChild>  
  <DifferentChild>4</DifferentChild>  
  <DifferentChild>5</DifferentChild>  
</NewRoot>  
------  
<NewRoot>  
  <DifferentChild>3</DifferentChild>  
  <DifferentChild>4</DifferentChild>  
  <DifferentChild>5</DifferentChild>  
</NewRoot>  

텍스트 파일을 처리하는 한 가지 방법은 yield return 구문을 사용하여 한 번에 한 줄씩 텍스트 파일을 스트리밍하는 확장 메서드를 작성하는 것입니다. 그런 다음 지연된 방식으로 텍스트 파일을 처리하는 LINQ 쿼리를 작성할 수 있습니다. 그런 다음 출력을 스트리밍하는 데 사용하는 XStreamingElement 경우 원본 텍스트 파일의 크기에 관계없이 최소한의 메모리를 사용하는 텍스트 파일에서 XML로 변환을 만들 수 있습니다.

아래에 있는 People.txt 텍스트 파일은 이 예제의 소스입니다.

#This is a comment  
1,Tai,Yee,Writer  
2,Nikolay,Grachev,Programmer  
3,David,Wright,Inventor  

다음 코드에는 지연된 방식으로 텍스트 파일의 줄을 스트림하는 확장 메서드가 포함되어 있습니다.

public static class StreamReaderSequence  
{  
    public static IEnumerable<string> Lines(this StreamReader source)  
    {  
        String line;  

        if (source == null)  
            throw new ArgumentNullException("source");  
        while ((line = source.ReadLine()) != null)  
        {  
            yield return line;  
        }  
    }  
}  

class Program  
{  
    static void Main(string[] args)  
    {  
        StreamReader sr = new StreamReader("People.txt");  
        XStreamingElement xmlTree = new XStreamingElement("Root",  
            from line in sr.Lines()  
            let items = line.Split(',')  
            where !line.StartsWith("#")  
            select new XElement("Person",  
                       new XAttribute("ID", items[0]),  
                       new XElement("First", items[1]),  
                       new XElement("Last", items[2]),  
                       new XElement("Occupation", items[3])  
                   )  
        );  
        Console.WriteLine(xmlTree);  
        sr.Close();  
    }  
}  
Module StreamReaderSequence  

    <Runtime.CompilerServices.Extension>  
    Public Iterator Function Lines(source As IO.StreamReader) As IEnumerable(Of String)  
        If source Is Nothing Then Throw New ArgumentNullException("source")  
        Dim line As String = source.ReadLine()  
        While (line <> Nothing)  
            Yield line  
            line = source.ReadLine()  
        End While  
    End Function  

End Module  

Module Module1  
    Sub Main()  
        Dim sr As New IO.StreamReader("People.txt")  
        Dim xmlTree As New XStreamingElement("Root",  
            From line In sr.Lines()  
            Let items = line.Split(","c)  
            Where Not line.StartsWith("#")  
            Select <Person ID=<%= items(0) %>>  
                       <First><%= items(1) %></First>  
                       <Last><%= items(2) %></Last>  
                       <Occupation><%= items(3) %></Occupation>  
                   </Person>)  
        Console.WriteLine(xmlTree)  
        sr.Close()  
    End Sub  
End Module  

이 예에서 생성되는 출력은 다음과 같습니다.

<Root>  
  <Person ID="1">  
    <First>Tai</First>  
    <Last>Yee</Last>  
    <Occupation>Writer</Occupation>  
  </Person>  
  <Person ID="2">  
    <First>Nikolay</First>  
    <Last>Grachev</Last>  
    <Occupation>Programmer</Occupation>  
  </Person>  
  <Person ID="3">  
    <First>David</First>  
    <Last>Wright</Last>  
    <Occupation>Inventor</Occupation>  
  </Person>  
</Root>  

큰 XML 파일을 변환하고 애플리케이션의 메모리 사용 공간이 예상 가능하도록 애플리케이션을 작성해야 하는 경우가 있습니다. XML 트리를 매우 큰 XML 파일로 채우려는 경우 메모리 사용은 파일 크기에 비례하므로 지나치게 증가하게 됩니다. 따라서 스트리밍 기법을 대신 사용해야 합니다.

OrderBy와 같은 특정 표준 쿼리 연산자는 자신의 소스를 반복하고 모든 데이터를 수집하여 정렬한 다음 시퀀스의 첫 번째 항목을 최종적으로 생성합니다. 첫 번째 항목을 반환하기 전에 소스를 유형화하는 쿼리 연산자를 사용하는 경우 애플리케이션에 대한 작은 메모리 사용 공간이 유지되지 않습니다.

설명된 기술을 사용하더라도 변환된 문서가 포함된 XML 트리를 어셈블하려고 하면 메모리 사용량이 너무 많을 수 있습니다.

다음 예제에서는 헤더 정보에 액세스할 수 있는 XML 조각을 스트리밍하는 방법의 예제를 기반으로 합니다.

이 예제에서는 XStreamingElement의 지연된 실행 기능을 사용하여 출력을 스트림합니다.

사용자 지정 축(StreamCustomerItem)은 문서에 Customer, NameItem 요소가 있고 이러한 요소가 다음 Source.xml 문서의 경우와 마찬가지로 정렬되어 있다고 가정하고 작성된 것입니다. 그러나 더욱 강력한 구현은 XSD를 사용하여 소스 문서의 유효성을 검사하거나, 잘못된 문서의 구문을 분석할 준비가 되어 있습니다.

다음은 소스 문서인 Source.xml입니다.

<?xml version="1.0" encoding="utf-8" ?>   
<Root>  
  <Customer>  
    <Name>A. Datum Corporation</Name>  
    <Item>  
      <Key>0001</Key>  
    </Item>  
    <Item>  
      <Key>0002</Key>  
    </Item>  
    <Item>  
      <Key>0003</Key>  
    </Item>  
    <Item>  
      <Key>0004</Key>  
    </Item>  
  </Customer>  
  <Customer>  
    <Name>Fabrikam, Inc.</Name>  
    <Item>  
      <Key>0005</Key>  
    </Item>  
    <Item>  
      <Key>0006</Key>  
    </Item>  
    <Item>  
      <Key>0007</Key>  
    </Item>  
    <Item>  
      <Key>0008</Key>  
    </Item>  
  </Customer>  
  <Customer>  
    <Name>Southridge Video</Name>  
    <Item>  
      <Key>0009</Key>  
    </Item>  
    <Item>  
      <Key>0010</Key>  
    </Item>  
  </Customer>  
</Root>  

다음 코드에는 원본 XML을 스트리밍하는 데 사용하는 XmlReader 메서드가 포함되어 있습니다. 새 XML을 스트리밍하는 데 사용됩니다 XStreamingElement .

static IEnumerable<XElement> StreamCustomerItem(string uri)  
{  
    using (XmlReader reader = XmlReader.Create(uri))  
    {  
        XElement name = null;  
        XElement item = null;  

        reader.MoveToContent();  

        // Parse the file, save header information when encountered, and yield the  
        // Item XElement objects as they are created.  

        // loop through Customer elements  
        while (reader.Read())  
        {  
            if (reader.NodeType == XmlNodeType.Element  
                && reader.Name == "Customer")  
            {  
                // move to Name element  
                while (reader.Read())  
                {  
                    if (reader.NodeType == XmlNodeType.Element &&  
                        reader.Name == "Name")  
                    {  
                        name = XElement.ReadFrom(reader) as XElement;  
                        break;  
                    }  
                }  

                // loop through Item elements  
                while (reader.Read())  
                {  
                    if (reader.NodeType == XmlNodeType.EndElement)  
                        break;  
                    if (reader.NodeType == XmlNodeType.Element  
                        && reader.Name == "Item")  
                    {  
                        item = XElement.ReadFrom(reader) as XElement;  
                        if (item != null)  
                        {  
                            XElement tempRoot = new XElement("Root",  
                                new XElement(name)  
                            );  
                            tempRoot.Add(item);  
                            yield return item;  
                        }  
                    }  
                }  
            }  
        }  
    }  
}  

static void Main(string[] args)  
{  
    XStreamingElement root = new XStreamingElement("Root",  
        from el in StreamCustomerItem("Source.xml")  
        select new XElement("Item",  
            new XElement("Customer", (string)el.Parent.Element("Name")),  
            new XElement(el.Element("Key"))  
        )  
    );  
    root.Save("Test.xml");  
    Console.WriteLine(File.ReadAllText("Test.xml"));  
}  
Iterator Function StreamCustomerItem(uri As String) As IEnumerable(Of XElement)  

    Dim name As XElement = Nothing  
    Dim item As XElement = Nothing  

    Dim reader As XmlReader = XmlReader.Create(uri)  
    reader.MoveToContent()  

    ' Parse the file, save header information when encountered, and yield the  
    ' Item XElement objects as they are created.  

    ' Loop through Customer elements.  
    While (reader.Read())  
        If (reader.NodeType = XmlNodeType.Element And reader.Name = "Customer") Then  
            While (reader.Read())  
                ' Move to Name element  
                If (reader.NodeType = XmlNodeType.Element And reader.Name = "Name") Then  
                    name = CType(XElement.ReadFrom(reader), XElement)  
                    Exit While  
                End If  
            End While  

            ' Loop through Item elements  
            While (reader.Read())  
                If (reader.NodeType = XmlNodeType.EndElement) Then  
                    Exit While  
                End If  

                If (reader.NodeType = XmlNodeType.Element And reader.Name = "Item") Then  
                    item = CType(XElement.ReadFrom(reader), XElement)  
                    If (Not (item Is Nothing)) Then  
                        Dim tempRoot = New XElement("Root",  
                            New XElement(name)  
                        )  
                        tempRoot.Add(item)  
                        Yield item  
                     End If  
                End If  
            End While  
        End If  
     End While  
    reader.Close()  
End Function  

Sub Main()  
    Dim root As New XStreamingElement("Root",  
        From el In StreamCustomerItem("c:\trash\Source.xml")  
        Select New XElement("Item",  
            New XElement("Customer", CStr(el.Parent.Element("Name"))),  
            New XElement(el.Element("Key"))))  
    root.Save("c:\trash\Test.xml")  
    Console.WriteLine(System.IO.File.ReadAllText("c:\trash\Test.xml"))  
End Sub  

이 예제는 다음과 같은 출력을 생성합니다.

<?xml version="1.0" encoding="utf-8"?>  
<Root>  
  <Item>  
    <Customer>A. Datum Corporation</Customer>  
    <Key>0001</Key>  
  </Item>  
  <Item>  
    <Customer>A. Datum Corporation</Customer>  
    <Key>0002</Key>  
  </Item>  
  <Item>  
    <Customer>A. Datum Corporation</Customer>  
    <Key>0003</Key>  
  </Item>  
  <Item>  
    <Customer>A. Datum Corporation</Customer>  
    <Key>0004</Key>  
  </Item>  
  <Item>  
    <Customer>Fabrikam, Inc.</Customer>  
    <Key>0005</Key>  
  </Item>  
  <Item>  
    <Customer>Fabrikam, Inc.</Customer>  
    <Key>0006</Key>  
  </Item>  
  <Item>  
    <Customer>Fabrikam, Inc.</Customer>  
    <Key>0007</Key>  
  </Item>  
  <Item>  
    <Customer>Fabrikam, Inc.</Customer>  
    <Key>0008</Key>  
  </Item>  
  <Item>  
    <Customer>Southridge Video</Customer>  
    <Key>0009</Key>  
  </Item>  
  <Item>  
    <Customer>Southridge Video</Customer>  
    <Key>0010</Key>  
  </Item>  
</Root>  

설명

이 클래스를 사용하면 지연된 스트리밍 출력을 지원하는 XML 트리를 만들 수 있습니다. 이 클래스를 사용하여 XML 트리를 만드는 것과 매우 유사한 방식으로 XML 트리를 만듭니다 XElement. 그러나 근본적인 차이점이 있습니다. LINQ 쿼리를 사용하여 XML 트리를 만들 때 콘텐츠를 지정하는 경우 XML 트리 XElement를 생성할 때 쿼리 변수가 반복되고 쿼리 결과가 XML 트리에 추가됩니다. 반면, 사용하여 XML 트리 XStreamingElement를 만들 때 쿼리 변수에 대한 참조는 반복되지 않고 XML 트리에 저장됩니다. 쿼리는 serialization 시만 반복됩니다. 이렇게 하면 더 작은 메모리 공간을 유지하면서 더 큰 XML 트리를 만들 수 있습니다.

텍스트 파일과 같은 입력 원본에서 스트리밍하는 경우 매우 큰 텍스트 파일을 읽고 작은 메모리 공간을 유지하면서 매우 큰 XML 문서를 생성할 수 있습니다.

또 다른 시나리오는 메모리에 로드된 큰 XML 트리가 있고 변환된 버전의 문서를 만들려는 경우입니다. 새 문서를 사용하여 XElement만드는 경우 변환이 완료되면 두 개의 큰 XML 트리가 메모리에 있습니다. 그러나 새 XML 트리를 사용하여 XStreamingElement만들면 작업 집합이 효과적으로 절반으로 줄어듭니다.

사용하는 XStreamingElement프로그램을 디버깅할 때 개체 값을 표시하면 ToString 메서드가 호출됩니다. 이렇게 하면 XML이 serialize됩니다. 스트리밍 요소 쿼리의 의미 체계가 스트리밍 요소를 한 번만 스트리밍할 수 있도록 하는 경우 디버깅 환경에서 바람직하지 않은 동작이 발생할 수 있습니다.

생성자

XStreamingElement(XName)

지정된 XName에서 XElement 클래스의 새 인스턴스를 초기화합니다.

XStreamingElement(XName, Object)

지정된 이름 및 콘텐츠를 사용하여 XStreamingElement 클래스의 새 인스턴스를 초기화합니다.

XStreamingElement(XName, Object[])

지정된 이름 및 콘텐츠를 사용하여 XStreamingElement 클래스의 새 인스턴스를 초기화합니다.

속성

Name

이 스트리밍 요소의 이름을 가져오거나 설정합니다.

메서드

Add(Object)

지정된 콘텐츠를 이 XStreamingElement에 자식으로 추가합니다.

Add(Object[])

지정된 콘텐츠를 이 XStreamingElement에 자식으로 추가합니다.

Equals(Object)

지정된 개체가 현재 개체와 같은지 확인합니다.

(다음에서 상속됨 Object)
GetHashCode()

기본 해시 함수로 작동합니다.

(다음에서 상속됨 Object)
GetType()

현재 인스턴스의 Type을 가져옵니다.

(다음에서 상속됨 Object)
MemberwiseClone()

현재 Object의 단순 복사본을 만듭니다.

(다음에서 상속됨 Object)
Save(Stream)

XStreamingElement를 지정된 Stream에 출력합니다.

Save(Stream, SaveOptions)

XStreamingElement를 지정된 Stream에 출력하고 선택적으로 형식 지정 동작을 지정합니다.

Save(String)

이 스트리밍 요소를 파일로 serialize합니다.

Save(String, SaveOptions)

이 스트리밍 요소를 파일로 serialize하고, 선택적으로 서식 지정을 해제합니다.

Save(TextWriter)

이 스트리밍 요소를 TextWriter로 serialize합니다.

Save(TextWriter, SaveOptions)

이 스트리밍 요소를 TextWriter로 serialize하고, 선택적으로 서식 지정을 해제합니다.

Save(XmlWriter)

이 스트리밍 요소를 XmlWriter로 serialize합니다.

ToString()

이 스트리밍 요소의 형식 지정(들여쓰기)된 XML을 반환합니다.

ToString(SaveOptions)

이 스트리밍 요소의 XML을 반환하고, 선택적으로 서식 지정을 해제합니다.

WriteTo(XmlWriter)

이 스트리밍 요소를 XmlWriter에 씁니다.

적용 대상

추가 정보