XStreamingElement Clase

Definición

Representa los elementos de un árbol XML que admite la salida de streaming diferida.

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

Ejemplos

En el ejemplo siguiente se crea primero un árbol XML de origen. A continuación, crea una transformación del árbol XML de origen mediante XElement. Esta transformación crea un nuevo árbol en memoria. A continuación, crea una transformación del árbol XML de origen mediante XStreamingElement. Esta transformación no ejecuta la consulta hasta que el árbol transformado se serializa en la consola. Su uso de memoria es menor.

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)

Este ejemplo produce el siguiente resultado:

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

Un enfoque para procesar un archivo de texto es escribir un método de extensión que transmite el archivo de texto una línea a la vez mediante la yield return construcción . A continuación, puede escribir una consulta LINQ que procese el archivo de texto de forma diferida. Si después usa para transmitir la XStreamingElement salida, puede crear una transformación desde el archivo de texto a XML que use una cantidad mínima de memoria, independientemente del tamaño del archivo de texto de origen.

El siguiente archivo de texto, People.txt, es el origen de este ejemplo.

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

El código siguiente contiene un método de extensión que transmite las líneas del archivo de texto de forma diferida.

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

Este ejemplo produce el siguiente resultado:

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

A veces, tiene que transformar archivos XML grandes y escribir la aplicación para que la superficie de memoria de la aplicación sea predecible. Si intenta rellenar un árbol XML con un archivo XML muy grande, el uso de memoria será proporcional al tamaño del archivo (es decir, excesivo). Por lo tanto, debe usar una técnica de streaming en su lugar.

Algunos operadores de consulta estándar, como OrderBy, iteran su origen, recopilan todos los datos, lo ordenan y, por último, producen el primer elemento de la secuencia. Tenga en cuenta que si usa un operador de consulta que materializa su origen antes de producir el primer elemento, no conservará una superficie de memoria pequeña para la aplicación.

Incluso si usa la técnica descrita en , si intenta ensamblar un árbol XML que contiene el documento transformado, el uso de memoria puede ser demasiado grande.

El ejemplo siguiente se basa en el ejemplo de Cómo transmitir fragmentos XML con acceso a la información de encabezado.

En este ejemplo se usan las funcionalidades de ejecución diferida de XStreamingElement para transmitir la salida.

Tenga en cuenta que el eje personalizado (StreamCustomerItem) se escribe específicamente para que espere un documento que tenga Customerelementos , Namey Item y que esos elementos se organizarán como en el siguiente documento de Source.xml. Sin embargo, una implementación más sólida validaría el documento de origen con un XSD o se prepararía para analizar un documento no válido.

A continuación se muestra el documento de origen, 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>

El código siguiente contiene un método que usa para XmlReader transmitir el XML de origen. Usa XStreamingElement para transmitir el nuevo 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

Este ejemplo produce el siguiente resultado:

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

Comentarios

Esta clase permite crear un árbol XML que admita la salida de streaming diferida. Use esta clase para crear un árbol XML de forma muy similar a la creación de un árbol XML mediante XElement. Sin embargo, hay una diferencia fundamental. Cuando se usa una consulta LINQ para especificar contenido al crear un árbol XML mediante XElement, la variable de consulta se itera en el momento de la construcción del árbol XML y los resultados de la consulta se agregan al árbol XML. Por el contrario, cuando se crea un árbol XML mediante XStreamingElement, se almacena una referencia a la variable de consulta en el árbol XML sin iteración. Las consultas solo se iteran tras la serialización. Esto le permite crear árboles XML más grandes al tiempo que mantiene una superficie de memoria más pequeña.

Si está transmitiendo desde un origen de entrada, como un archivo de texto, puede leer un archivo de texto muy grande y generar un documento XML muy grande mientras mantiene una superficie de memoria pequeña.

Otro escenario es que tiene un árbol XML grande que se ha cargado en memoria y desea crear una versión transformada del documento. Si crea un nuevo documento mediante XElement, tendrá dos árboles XML grandes en memoria tras la finalización de la transformación. Sin embargo, si crea el nuevo árbol XML mediante XStreamingElement, el conjunto de trabajo se cortará de forma eficaz a la mitad.

Tenga en cuenta que al depurar un programa que usa XStreamingElement, mostrar el valor de un objeto hace que se llame a su ToString método. Esto hace que el XML se serialice. Si la semántica de la consulta de elementos de streaming es tal que el elemento de streaming solo se puede transmitir una vez, esto puede provocar un comportamiento no deseado en la experiencia de depuración.

Constructores

Nombre Description
XStreamingElement(XName, Object)

Inicializa una nueva instancia de la XStreamingElement clase con el nombre y el contenido especificados.

XStreamingElement(XName, Object[])

Inicializa una nueva instancia de la XStreamingElement clase con el nombre y el contenido especificados.

XStreamingElement(XName)

Inicializa una nueva instancia de la XElement clase a partir del especificado XName.

Propiedades

Nombre Description
Name

Obtiene o establece el nombre de este elemento de streaming.

Métodos

Nombre Description
Add(Object)

Agrega el contenido especificado como elementos secundarios a este XStreamingElementobjeto .

Add(Object[])

Agrega el contenido especificado como elementos secundarios a este XStreamingElementobjeto .

Equals(Object)

Determina si el objeto especificado es igual al objeto actual.

(Heredado de Object)
GetHashCode()

Actúa como función hash predeterminada.

(Heredado de Object)
GetType()

Obtiene el Type de la instancia actual.

(Heredado de Object)
MemberwiseClone()

Crea una copia superficial del Objectactual.

(Heredado de Object)
Save(Stream, SaveOptions)

Genera esto XStreamingElement en el especificado Streamy, opcionalmente, especifica el comportamiento de formato.

Save(Stream)

Genera esto XStreamingElement en el especificado Stream.

Save(String, SaveOptions)

Serialice este elemento de streaming en un archivo, deshabilitando opcionalmente el formato.

Save(String)

Serialice este elemento de streaming en un archivo.

Save(TextWriter, SaveOptions)

Serialice este elemento de streaming en , TextWriterdeshabilitando opcionalmente el formato.

Save(TextWriter)

Serialice este elemento de streaming en un TextWriter.

Save(XmlWriter)

Serialice este elemento de streaming en un XmlWriter.

ToString()

Devuelve el XML con formato (con sangría) de este elemento de streaming.

ToString(SaveOptions)

Devuelve el XML de este elemento de streaming, deshabilitando opcionalmente el formato.

WriteTo(XmlWriter)

Escribe este elemento de streaming en un XmlWriter.

Se aplica a

Consulte también