作法:從 XmlReader 串流 XML 片段 (C#)How to: Stream XML Fragments from an XmlReader (C#)

當您必須處理大型 XML 檔案時,可能無法將整個 XML 樹狀載入記憶體中。When you have to process large XML files, it might not be feasible to load the whole XML tree into memory. 這個主題顯示如何使用 XmlReader 串流片段。This topic shows how to stream fragments using an XmlReader.

使用 XmlReader 讀取 XElement 物件的其中一個最有效方式為,撰寫您自己自訂的座標軸方法。One of the most effective ways to use an XmlReader to read XElement objects is to write your own custom axis method. 座標軸方法通常會傳回集合,例如,IEnumerable<T>XElement,如本主題的範例中所示。An axis method typically returns a collection such as IEnumerable<T> of XElement, as shown in the example in this topic. 在自訂座標軸方法中,呼叫 ReadFrom 方法來建立 XML 片段後,使用 yield return 傳回集合。In the custom axis method, after you create the XML fragment by calling the ReadFrom method, return the collection using yield return. 這會將延後執行語意 (Semantics) 提供給您自訂的座標軸方法。This provides deferred execution semantics to your custom axis method.

當您從 XmlReader 物件建立 XML 樹狀結構時,XmlReader 必須定位在項目上。When you create an XML tree from an XmlReader object, the XmlReader must be positioned on an element. ReadFrom 方法在讀取項目的關閉標記前不會傳回。The ReadFrom method does not return until it has read the close tag of the element.

如果您要建立部分樹狀結構,您可以具現化 XmlReader、將讀取器定位在您要轉換為 XElement 樹狀結構的節點上,然後建立 XElement 物件。If you want to create a partial tree, you can instantiate an XmlReader, position the reader on the node that you want to convert to an XElement tree, and then create the XElement object.

如何:串流 XML 片段並存取標頭資訊 (C#) 主題包含如何串流更複雜文件的資訊與範例。The topic How to: Stream XML Fragments with Access to Header Information (C#) contains information and an example on how to stream a more complex document.

如何:執行大型 XML 文件的串流轉換 (C#) 主題包含範例,示範如何使用 LINQ to XML 來轉換超大型 XML 文件,同時將記憶體使用量維持在很小。The topic How to: Perform Streaming Transform of Large XML Documents (C#) contains an example of using LINQ to XML to transform extremely large XML documents while maintaining a small memory footprint.

範例Example

這個範例會建立自訂座標軸方法。This example creates a custom axis method. 您可以使用 LINQLINQ 查詢進行查詢。You can query it by using a LINQLINQ query. 自訂座標軸方法 StreamRootChildDoc 是一種方法,特別針對讀取具有重複 Child 項目的文件而設計。The custom axis method, StreamRootChildDoc, is a method that is designed specifically to read a document that has a repeating Child element.

static IEnumerable<XElement> StreamRootChildDoc(StringReader stringReader)  
{  
    using (XmlReader reader = XmlReader.Create(stringReader))  
    {  
        reader.MoveToContent();  
        // Parse the file and display each of the nodes.  
        while (reader.Read())  
        {  
            switch (reader.NodeType)  
            {  
                case XmlNodeType.Element:  
                    if (reader.Name == "Child") {  
                        XElement el = XElement.ReadFrom(reader) as XElement;  
                        if (el != null)  
                            yield return el;  
                    }  
                    break;  
            }  
        }  
    }  
}  
  
static void Main(string[] args)  
{  
    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);  
    }  
}  

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

bbb  
ccc  

在此範例中,來源文件很小。In this example, the source document is very small. 但是,即使有數百萬的 Child 元素,此範例的記憶體使用量還是很小。However, even if there were millions of Child elements, this example would still have a small memory footprint.