XStreamingElement Clase
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Representa los elementos de un árbol XML que admite la salida de transmisión por secuencias 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 del procesamiento de un archivo de texto es escribir un método de extensión que transmita el archivo de texto por secuencias de línea en línea mediante la construcción yield return
. Después, puede escribir una consulta LINQ que procese el archivo de texto de forma aplazada y lenta. 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 siguiente código contiene un método de extensión que transmite las líneas del archivo de texto por secuencias 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 los archivos XML grandes y escribir la aplicación para que sea predecible la superficie en memoria de la aplicación. Si intenta rellenar un árbol XML con un archivo XML de gran tamaño, su utilización de memoria será proporcional al tamaño del archivo (es decir, excesivo). Por consiguiente, debe utilizar en su lugar una técnica de transmisión por secuencias.
Ciertos operadores de consulta estándar, como OrderBy, recorren en iteración su origen, recaban todos los datos, los ordenan y finalmente producen el primer elemento de la secuencia. Tenga en cuenta que si utiliza un operador de consulta que materializa su origen antes de producir el primer elemento, no retendrá 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.
Este ejemplo utiliza las funciones de ejecución aplazada de XStreamingElement para transmitir por secuencias el resultado.
Observe que se escribe el eje personalizado (StreamCustomerItem
) específicamente para que espere un documento que tiene los elementos Customer
, Name
e Item
, y que esos elementos se organizarán como en el documento Source.xml siguiente. Una implementación más sólida, sin embargo, validaría el documento de origen con 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. XStreamingElement Usa 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. Esta clase se usa 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, al crear 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 va a transmitir 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 la memoria tras la finalización de la transformación. Sin embargo, si crea el nuevo árbol XML mediante XStreamingElement, el espacio de trabajo se cortará eficazmente 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
XStreamingElement(XName) |
Inicializa una nueva instancia de la clase XElement a partir del XName especificado. |
XStreamingElement(XName, Object) |
Inicializa una nueva instancia de la clase XStreamingElement con el nombre y el contenido especificados. |
XStreamingElement(XName, Object[]) |
Inicializa una nueva instancia de la clase XStreamingElement con el nombre y el contenido especificados. |
Propiedades
Name |
Obtiene o establece el nombre de esta transmisión por secuencias. |
Métodos
Add(Object) |
Agrega el contenido especificado como elementos secundarios a este XStreamingElement. |
Add(Object[]) |
Agrega el contenido especificado como elementos secundarios a este XStreamingElement. |
Equals(Object) |
Determina si el objeto especificado es igual que el objeto actual. (Heredado de Object) |
GetHashCode() |
Sirve como la función hash predeterminada. (Heredado de Object) |
GetType() |
Obtiene el Type de la instancia actual. (Heredado de Object) |
MemberwiseClone() |
Crea una copia superficial del Object actual. (Heredado de Object) |
Save(Stream) |
Genera este XStreamingElement en el objeto Stream especificado. |
Save(Stream, SaveOptions) |
Genera este XStreamingElement en el objeto Stream especificado, especificando opcionalmente el comportamiento de formato. |
Save(String) |
Serialice este elemento de transmisión por secuencias en un archivo. |
Save(String, SaveOptions) |
Serialice este elemento de transmisión por secuencias en un archivo y, de modo opcional, deshabilite el formato. |
Save(TextWriter) |
Serialice este elemento de transmisión por secuencias en un TextWriter. |
Save(TextWriter, SaveOptions) |
Serialice este elemento de transmisión por secuencias en un TextWriter, de modo opcional, deshabilite el formato. |
Save(XmlWriter) |
Serialice este elemento de transmisión por secuencias en un XmlWriter. |
ToString() |
Devuelve el XML con formato (sangría) para este elemento de transmisión por secuencias. |
ToString(SaveOptions) |
Devuelve el XML de este elemento de transmisión por secuencias y, opcionalmente, se deshabilita el formato. |
WriteTo(XmlWriter) |
Escribe este elemento de transmisión por secuencias en un XmlWriter. |