XStreamingElement Class

Definition

代表 XML 樹狀中的元素,該樹狀支援延後的資料流輸出。Represents elements in an XML tree that supports deferred streaming output.

public ref class XStreamingElement
public class XStreamingElement
type XStreamingElement = class
Public Class XStreamingElement
Inheritance
XStreamingElement

Examples

下列範例會先建立來源 XML 樹狀結構。The following example first creates a source XML tree. 接著,它會使用 XElement建立來源 XML 樹狀結構的轉換。It then creates a transform of the source XML tree using XElement. 這項轉換會在記憶體中建立新的樹狀結構。This transform creates a new tree in memory. 接著,它會使用 XStreamingElement建立來源 XML 樹狀結構的轉換。It then creates a transform of the source XML tree using XStreamingElement. 在轉換的樹狀結構序列化至主控台之前,這種轉換不會執行查詢。This transform doesn't execute the query until the transformed tree is serialized to the console. 其記憶體使用量較少。Its memory usage is less.

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)  

這個範例會產生下列輸出:This example produces the following output:

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

處理文字檔的其中一個方法是撰寫擴充方法,該方法會使用 yield return 建構將文字檔一次串流一行。One approach to processing a text file is to write an extension method that streams the text file a line at a time using the yield return construct. 然後您可以撰寫利用延後的方式處理文字檔的 LINQ 查詢。You then can write a LINQ query that processes the text file in a lazy deferred fashion. 如果您接著使用 XStreamingElement 來串流輸出,則不論來源文字檔的大小為何,您都可以從文字檔建立轉換,使其使用最少的記憶體數量。If you then use the XStreamingElement to stream output, you then can create a transform from the text file to XML that uses a minimal amount of memory, regardless of the size of the source text file.

下列文字檔 People.txt 為這個範例的來源。The following text file, People.txt, is the source for this example.

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

下列程式碼包含的擴充方法可以用延緩的方式,串流文字檔的行。The following code contains an extension method that streams the lines of the text file in a deferred fashion.

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  

這個範例會產生下列輸出:This example produces the following output:

<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 檔案並撰寫您的應用程式,讓應用程式的記憶體使用量可以預測。Sometimes you have to transform large XML files, and write your application so that the memory footprint of the application is predictable. 如果您嘗試使用非常大的 XML 檔案填入 XML 樹狀結構,您的記憶體使用量將與檔案大小成正比 (也就是,變成過度)。If you try to populate an XML tree with a very large XML file, your memory usage will be proportional to the size of the file (that is, excessive). 因此,您應該改用資料流技術。Therefore, you should use a streaming technique instead.

特定的標準查詢運算子 (例如,OrderBy) 會反覆查看其來源、收集所有資料、排序這些資料,最後產生順序中的第一個項目。Certain standard query operators, such as OrderBy, iterate their source, collect all of the data, sort it, and then finally yield the first item in the sequence. 請注意,如果您在產生第一個項目前使用具體化其來源的查詢運算子,您將不會為應用程式保留小的記憶體使用量。Note that if you use a query operator that materializes its source before yielding the first item, you will not retain a small memory footprint for your application.

即使您使用中所述的技術,如果您嘗試組合包含已轉換之檔的 XML 樹狀結構,記憶體使用量可能會太大。Even if you use the technique described in , if you try to assemble an XML tree that contains the transformed document, memory usage may be too great.

下列範例是以如何:串流 XML 片段並存取標頭資訊中的範例為基礎。The following example builds on the example in How to: Stream XML Fragments with Access to Header Information.

這個範例會使用 XStreamingElement 的延後執行功能來串流輸出。This example uses the deferred execution capabilities of XStreamingElement to stream the output.

請注意,自訂座標軸 (StreamCustomerItem) 是特別撰寫的,讓它預備擁有 CustomerNameItem 項目的文件,並預期這些項目將會與下列 Source.xml 文件的排列方式相同。Note that the custom axis (StreamCustomerItem) is specifically written so that it expects a document that has Customer, Name, and Item elements, and that those elements will be arranged as in the following Source.xml document. 不過,較為複雜的實作方法將會使用 XSD 驗證來源文件,或做為剖析無效文件的準備。A more robust implementation, however, would either validate the source document with an XSD, or would be prepared to parse an invalid document.

下列是來源文件 Source.xml:The following is the source document, 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>  

下列程式碼包含使用 XmlReader 來串流來源 XML 的方法。The following code contains a method that uses an XmlReader to stream the source XML. 它會使用 XStreamingElement 來串流新的 XML。It uses XStreamingElement to stream the new XML.

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  

這個範例會產生下列輸出:This example produces the following output:

<?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>  

Remarks

這個類別可讓您建立支援延遲資料流程輸出的 XML 樹狀結構。This class allows you to create an XML tree that supports deferred streaming output. 您可以使用這個類別,以非常類似的方式建立 XML 樹狀結構,以使用 XElement建立 XML 樹狀結構。You use this class to create an XML tree in a very similar fashion to creating an XML tree using XElement. 不過,有一個基本的差異。However, there is a fundamental difference. 當您使用 LINQ 查詢來指定使用 XElement建立 XML 樹狀結構時的內容時,查詢變數會在架構的 XML 樹狀結構中逐一查看,而查詢的結果則會加入至 XML 樹狀結構。When you use a LINQ query to specify content when creating an XML tree using XElement, the query variable is iterated at the time of construction of the XML tree, and the results of the query are added to the XML tree. 相反地,當您使用 XStreamingElement建立 XML 樹狀結構時,查詢變數的參考會儲存在 XML 樹狀結構中,而不會進行反覆運算。In contrast, when you create an XML tree using XStreamingElement, a reference to the query variable is stored in the XML tree without being iterated. 查詢只會在序列化時反覆運算。Queries are iterated only upon serialization. 這可讓您建立較大的 XML 樹狀結構,同時維護較小的記憶體使用量。This allows you to create larger XML trees while maintaining a smaller memory footprint.

如果您是從輸入來源進行串流處理(例如文字檔),則可以讀取非常大的文字檔,並產生非常大的 XML 檔,同時維持小型的記憶體使用量。If you are streaming from an input source, such as a text file, then you can read a very large text file, and generate a very large XML document while maintaining a small memory footprint.

另一種情況是,您有一個已載入記憶體中的大型 XML 樹狀結構,而您想要建立已轉換的檔版本。Another scenario is that you have a large XML tree that has been loaded into memory, and you want to create a transformed version of the document. 如果您使用 XElement建立新檔,則在轉換完成時,記憶體中將會有兩個大型 XML 樹狀結構。If you create a new document using XElement, then you will have two large XML trees in memory upon completion of the transformation. 不過,如果您使用 XStreamingElement建立新的 XML 樹狀結構,您的工作集就會有效率地剪下一半。However, if you create the new XML tree using XStreamingElement, then your working set will be effectively cut in half.

請注意,在偵錯工具使用 XStreamingElement時,顯示物件的值會使其 ToString 方法被呼叫。Note that when debugging a program that uses XStreamingElement, displaying the value of an object causes its ToString method to be called. 這會導致 XML 序列化。This causes the XML to be serialized. 如果串流元素查詢的語義是讓串流元素只能進行資料流程處理一次,這可能會導致您的偵錯工具中出現不想要的行為。If the semantics of your streaming element query are such that the streaming element can only be streamed once, this may cause undesirable behavior in your debugging experience.

Constructors

XStreamingElement(XName)

從指定的 XName 初始化 XElement 類別的新執行個體。Initializes a new instance of the XElement class from the specified XName.

XStreamingElement(XName, Object)

使用指定的名稱和內容初始化 XStreamingElement 類別的新執行個體。Initializes a new instance of the XStreamingElement class with the specified name and content.

XStreamingElement(XName, Object[])

使用指定的名稱和內容初始化 XStreamingElement 類別的新執行個體。Initializes a new instance of the XStreamingElement class with the specified name and content.

Properties

Name

取得或設定這個資料流項目的名稱。Gets or sets the name of this streaming element.

Methods

Add(Object)

將指定的內容當做子系加入至這個 XStreamingElementAdds the specified content as children to this XStreamingElement.

Add(Object[])

將指定的內容當做子系加入至這個 XStreamingElementAdds the specified content as children to this XStreamingElement.

Equals(Object)

判斷指定的物件是否等於目前的物件。Determines whether the specified object is equal to the current object.

(Inherited from Object)
GetHashCode()

做為預設雜湊函式。Serves as the default hash function.

(Inherited from Object)
GetType()

取得目前執行個體的 TypeGets the Type of the current instance.

(Inherited from Object)
MemberwiseClone()

建立目前 Object 的淺層複製。Creates a shallow copy of the current Object.

(Inherited from Object)
Save(Stream)

將這個 XStreamingElement 輸出到指定的 StreamOutputs this XStreamingElement to the specified Stream.

Save(Stream, SaveOptions)

將這個 XStreamingElement 輸出至指定的 Stream,選擇性地指定格式化行為。Outputs this XStreamingElement to the specified Stream, optionally specifying formatting behavior.

Save(String)

將這個資料流項目序列化成檔案。Serialize this streaming element to a file.

Save(String, SaveOptions)

將這個資料流項目序列化成檔案 (可選擇是否停用格式設定)。Serialize this streaming element to a file, optionally disabling formatting.

Save(TextWriter)

將這個資料流項目序列化成 TextWriterSerialize this streaming element to a TextWriter.

Save(TextWriter, SaveOptions)

將這個資料流項目序列化成 TextWriter (可選擇是否停用格式設定)。Serialize this streaming element to a TextWriter, optionally disabling formatting.

Save(XmlWriter)

將這個資料流項目序列化成 XmlWriterSerialize this streaming element to an XmlWriter.

ToString()

傳回這個資料流項目之格式化 (縮排) 的 XML。Returns the formatted (indented) XML for this streaming element.

ToString(SaveOptions)

傳回這個資料流項目的 XML (可選擇是否停用格式設定)。Returns the XML for this streaming element, optionally disabling formatting.

WriteTo(XmlWriter)

將這個資料流項目寫入 XmlWriterWrites this streaming element to an XmlWriter.

Applies to

See also