XStreamingElement Класс

Определение

Представляет элементы в дереве XML, поддерживающем отложенный потоковый выход.

public ref class XStreamingElement
public class XStreamingElement
type XStreamingElement = class
Public Class XStreamingElement
Наследование
XStreamingElement

Примеры

В следующем примере сначала создается исходное XML-дерево. Затем он создает преобразование исходного XML-дерева с помощью XElement. Это преобразование создает новое дерево в памяти. Затем он создает преобразование исходного XML-дерева с помощью XStreamingElement. Это преобразование не выполняет запрос, пока преобразованное дерево не сериализуется в консоль. Его использование памяти меньше.

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)  

В этом примере выводятся следующие данные:

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

Одним из вариантов обработки текстового файла является написание метода расширения, который обрабатывает текстовый файл построчно при помощи конструкции yield return. Затем можно будет написать запрос LINQ, обрабатывающий текстовый файл в отложенной манере. Если вы используете XStreamingElement для потоковой передачи выходных данных, можно создать преобразование из текстового файла в XML, использующий минимальный объем памяти, независимо от размера исходного текстового файла.

В качестве исходного для этого примера используется текстовый файл People.txt.

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

Следующий код содержит метод расширения, который обрабатывает строки текстового файла в отложенной манере.

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  

В этом примере выводятся следующие данные:

<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-файлы, при этом приложение должно быть написано так, чтобы используемый им объем памяти был прогнозируемым. Если вставить в XML-дерево очень большой XML-файл, то объем используемой памяти будет пропорциональным размеру файла (то есть чрезмерным). Поэтому следует вместо этого использовать потоки.

Некоторые стандартные операторы запросов, например OrderBy, проходят через источник, собирают все данные, сортируют их и выдают первый элемент последовательности. Отметим, что при использовании оператора запроса, который материализует свой источник перед тем, как выдать первый элемент, приложение снова будет использовать большой объем памяти.

Даже если вы используете описанный выше метод, при попытке собрать XML-дерево, содержащее преобразованный документ, использование памяти может оказаться слишком большим.

В следующем примере показано, как выполнять потоковую передачу фрагментов XML с доступом к сведениям заголовка.

В этом примере возможности отложенной обработки объекта XStreamingElement используются для создания выходного потока.

Заметьте, что пользовательская ось (StreamCustomerItem) специально написана таким образом, что ожидает документа с элементами Customer, Name и Item, упорядоченными, как в следующем документе Source.xml. Однако при более надежной реализации должна быть либо выполнена проверка правильности исходного документа с помощью XSD, либо проведена подготовка на тот случай, что при проведении синтаксического анализа встретится документ, не прошедший проверку правильности.

Далее показан исходный документ, 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-кода. Он используется для XStreamingElement потоковой передачи нового 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  

В этом примере выводятся следующие данные:

<?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-дерево, поддерживающее отложенные выходные данные потоковой передачи. Этот класс используется для создания XML-дерева очень похоже на создание XML-дерева с помощью XElement. Тем не менее, существует фундаментальное различие. При использовании запроса LINQ для указания содержимого при создании XML-дерева с помощью XElementпеременной запроса выполняется итерация во время создания дерева XML, а результаты запроса добавляются в XML-дерево. Напротив, при создании XML-дерева с помощью XStreamingElementссылки на переменную запроса сохраняется в XML-дереве без итерации. Запросы итерируются только при сериализации. Это позволяет создавать большие XML-деревья при сохранении меньшего объема памяти.

При потоковой передаче из источника входных данных, например текстового файла, можно прочитать очень большой текстовый файл и создать очень большой XML-документ, сохраняя небольшой объем памяти.

Другой сценарий заключается в том, что у вас есть большое XML-дерево, загруженное в память, и вы хотите создать преобразованную версию документа. Если вы создаете новый документ, XElementто после завершения преобразования у вас будет два больших XML-дерева в памяти. Однако если вы создаете новое XML-дерево с помощью XStreamingElement, рабочий набор будет эффективно вырезан в два раза.

Обратите внимание, что при отладке программы, которая использует XStreamingElement, отображение значения объекта приводит к вызову метода ToString . Это приводит к сериализации XML. Если семантика запроса элемента потоковой передачи такова, что потоковый элемент можно передавать только один раз, это может привести к нежелательному поведению в интерфейсе отладки.

Конструкторы

XStreamingElement(XName)

Инициализирует новый экземпляр класса XElement из указанного потока XName.

XStreamingElement(XName, Object)

Инициализирует новый экземпляр класса XStreamingElement с указанными именем и содержимым.

XStreamingElement(XName, Object[])

Инициализирует новый экземпляр класса XStreamingElement с указанными именем и содержимым.

Свойства

Name

Получает или задает имя данного потокового элемента.

Методы

Add(Object)

Добавляет указанное содержимое в качестве дочерних элементов в данный объект XStreamingElement.

Add(Object[])

Добавляет указанное содержимое в качестве дочерних элементов в данный объект XStreamingElement.

Equals(Object)

Определяет, равен ли указанный объект текущему объекту.

(Унаследовано от Object)
GetHashCode()

Служит хэш-функцией по умолчанию.

(Унаследовано от Object)
GetType()

Возвращает объект Type для текущего экземпляра.

(Унаследовано от Object)
MemberwiseClone()

Создает неполную копию текущего объекта Object.

(Унаследовано от Object)
Save(Stream)

Выводит этот документ XStreamingElement в указанный поток Stream.

Save(Stream, SaveOptions)

Выводит данный элемент XStreamingElement в указанный поток Stream, при необходимости задавая поведение форматирования.

Save(String)

Сериализует данный потоковый элемент в файл.

Save(String, SaveOptions)

Сериализует данный потоковый элемент в файл, дополнительно отключая форматирование.

Save(TextWriter)

Сериализует данный потоковый элемент в TextWriter.

Save(TextWriter, SaveOptions)

Сериализует данный потоковый элемент в объект TextWriter, дополнительно отключая форматирование.

Save(XmlWriter)

Сериализует данный потоковый элемент в объект XmlWriter.

ToString()

Возвращает форматированный (с отступом) XML для данного потокового элемента.

ToString(SaveOptions)

Возвращает XML для данного потокового элемента, дополнительно отключая форматирование.

WriteTo(XmlWriter)

Записывает данный потоковый элемент в объект XmlWriter.

Применяется к

См. также раздел