XStreamingElement 类

定义

表示 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
继承
XStreamingElement

示例

下面的示例首先创建一个源 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 流式传输输出,则可以创建从文本文件到 XML 的转换,该转换使用最少的内存量,而不管源文本文件的大小如何。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>  

注解

此类允许您创建支持延迟流输出的 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. 当使用 XElement在创建 XML 树时使用 LINQ 查询来指定内容时,将在构造 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.

构造函数

XStreamingElement(XName)

从指定的 XElement 初始化 XName 类的新实例。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.

属性

Name

获取或设置此流元素的名称。Gets or sets the name of this streaming element.

方法

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.

(继承自 Object)
GetHashCode()

用作默认哈希函数。Serves as the default hash function.

(继承自 Object)
GetType()

获取当前实例的 TypeGets the Type of the current instance.

(继承自 Object)
MemberwiseClone()

创建当前 Object 的浅表副本。Creates a shallow copy of the current Object.

(继承自 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.

适用于

另请参阅