Compartir a través de


Cómo transmitir por secuencias fragmentos XML de XmlReader

Actualización: November 2007

Cuando tiene que procesar archivos XML de gran tamaño quizás no es factible cargar la totalidad del árbol XML en memoria. En este tema se muestra cómo transmitir por secuencias fragmentos usando XmlReader.

Una de las formas más efectivas de usar XmlReader para leer objetos XElement es escribir un método de eje personalizado propio. Un método de eje suele devolver una recopilación como IEnumerable<T> de XElement, tal y como se muestra en el ejemplo de este tema. En el método de eje personalizado, tras crear el fragmento XML llamando al método ReadFrom, devuelva la recopilación usando yield return. Esto proporciona semántica de ejecución aplazada al método de eje personalizado.

Cuando crea un árbol XML de un objeto XmlReader, XmlReader debe estar posicionado en un elemento. El método ReadFrom no vuelve hasta que ha leído la etiqueta de cierre del elemento.

Si desea crear un árbol parcial, puede crear una instancia de un XmlReader, colocar el lector en el nodo que desea convertir a un árbol XElement y después crear el objeto XElement.

El tema Cómo transmitir por secuencias fragmentos XML con acceso a la información de encabezado contiene información y un ejemplo de cómo transmitir por secuencias un documento más complejo.

El tema Cómo realizar una transformación de transmisión por secuencias de documentos XML grandes contiene un ejemplo del uso de LINQ to XML para transformar documentos XML extremadamente grandes manteniendo una superficie de memoria pequeña.

Ejemplo

Este ejemplo crea un método de eje personalizado. Puede consultarlo usando una consulta de LINQ. El método de eje personalizado, StreamRootChildDoc, es un método que está específicamente diseñado para leer un documento que tiene un elemento Child que se repite.

Nota:

En el ejemplo de código siguiente se utiliza la construcción yield return de C#. Puesto que no hay ninguna característica equivalente en Visual Basic 2008, este ejemplo sólo se proporciona en C#.

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);
    }
}

Este ejemplo genera el siguiente resultado:

bbb
ccc

En este ejemplo el documento de origen es muy pequeño. No obstante, aunque hubiera millones de elementos Child, este ejemplo seguiría teniendo una superficie de memoria pequeña.

Vea también

Conceptos

Analizar XML