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, Object)

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

XStreamingElement(XName, Object[])

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

XStreamingElement(XName)

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

Свойства

Имя Описание
Name

Возвращает или задает имя этого элемента потоковой передачи.

Методы

Имя Описание
Add(Object)

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

Add(Object[])

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

Equals(Object)

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

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

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

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

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

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

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

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

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

Save(Stream)

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

Save(String, SaveOptions)

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

Save(String)

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

Save(TextWriter, SaveOptions)

Сериализуйте этот элемент потоковой передачи в TextWriterрежиме автоматического отключения форматирования.

Save(TextWriter)

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

Save(XmlWriter)

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

ToString()

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

ToString(SaveOptions)

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

WriteTo(XmlWriter)

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

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

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