XStreamingElement Klasa

Definicja

Reprezentuje elementy w drzewie XML, które obsługuje odroczone dane wyjściowe przesyłania strumieniowego.

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

Przykłady

Poniższy przykład najpierw tworzy źródłowe drzewo XML. Następnie tworzy przekształcenie źródłowego drzewa XML przy użyciu polecenia XElement. Ta transformacja tworzy nowe drzewo w pamięci. Następnie tworzy przekształcenie źródłowego drzewa XML przy użyciu polecenia XStreamingElement. Ta transformacja nie wykonuje zapytania, dopóki przekształcone drzewo nie zostanie zserializowane w konsoli programu . Użycie pamięci jest mniejsze.

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)

Ten przykład generuje następujące wyniki:

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

Jednym z podejść do przetwarzania pliku tekstowego jest napisanie metody rozszerzenia, która przesyła strumieniowo plik tekstowy wiersz w czasie przy użyciu yield return konstrukcji. Następnie można napisać zapytanie LINQ, które przetwarza plik tekstowy w leniwy sposób odroczone. Jeśli następnie użyjesz XStreamingElement elementu do przesyłania strumieniowego danych wyjściowych, możesz utworzyć przekształcenie z pliku tekstowego na XML, który używa minimalnej ilości pamięci, niezależnie od rozmiaru pliku tekstowego źródłowego.

Poniższy plik tekstowy, People.txt, jest źródłem tego przykładu.

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

Poniższy kod zawiera metodę rozszerzenia, która przesyła strumieniowo wiersze pliku tekstowego w sposób odroczony.

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

Ten przykład generuje następujące wyniki:

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

Czasami trzeba przekształcić duże pliki XML i napisać aplikację tak, aby ilość pamięci aplikacji jest przewidywalna. Jeśli spróbujesz wypełnić drzewo XML bardzo dużym plikiem XML, użycie pamięci będzie proporcjonalne do rozmiaru pliku (czyli nadmiernego). W związku z tym należy zamiast tego użyć techniki przesyłania strumieniowego.

Niektóre standardowe operatory zapytań, takie jak OrderBy, iterują swoje źródło, zbierają wszystkie dane, sortują je, a następnie w końcu dają pierwszy element w sekwencji. Pamiętaj, że jeśli używasz operatora zapytania, który zmaterializuje jego źródło przed uzyskaniem pierwszego elementu, nie zachowasz małej ilości pamięci dla aplikacji.

Nawet jeśli używasz techniki opisanej w temacie , jeśli spróbujesz utworzyć drzewo XML zawierające przekształcony dokument, użycie pamięci może być zbyt duże.

Poniższy przykład opiera się na przykładzie w temacie Jak przesyłać strumieniowo fragmenty XML z dostępem do informacji nagłówka.

W tym przykładzie użyto możliwości odroczonego XStreamingElement wykonywania w celu przesyłania strumieniowego danych wyjściowych.

Należy pamiętać, że oś niestandardowa (StreamCustomerItem) jest specjalnie napisana tak, aby oczekiwała dokumentu z Customerelementami , Namei Item , i że te elementy zostaną rozmieszczone tak, jak w poniższym dokumencie Source.xml. Bardziej niezawodna implementacja może jednak zweryfikować dokument źródłowy za pomocą XSD lub przygotować się do analizowania nieprawidłowego dokumentu.

Poniżej przedstawiono dokument źródłowy, 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>

Poniższy kod zawiera metodę, która używa elementu do XmlReader przesyłania strumieniowego kodu XML źródłowego. Używa XStreamingElement go do przesyłania strumieniowego nowego kodu 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

Ten przykład generuje następujące wyniki:

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

Uwagi

Ta klasa umożliwia utworzenie drzewa XML obsługującego odroczone dane wyjściowe przesyłania strumieniowego. Ta klasa służy do tworzenia drzewa XML w bardzo podobny sposób do tworzenia drzewa XML przy użyciu polecenia XElement. Istnieje jednak podstawowa różnica. W przypadku używania zapytania LINQ do określania zawartości podczas tworzenia drzewa XML przy użyciu XElementzmiennej kwerendy jest iterowane w czasie budowy drzewa XML, a wyniki zapytania są dodawane do drzewa XML. Natomiast podczas tworzenia drzewa XML przy użyciu metody XStreamingElementodwołanie do zmiennej kwerendy jest przechowywane w drzewie XML bez iteracji. Zapytania są iterowane tylko po serializacji. Dzięki temu można tworzyć większe drzewa XML przy zachowaniu mniejszego śladu pamięci.

Jeśli przesyłasz strumieniowo ze źródła wejściowego, takiego jak plik tekstowy, możesz odczytać bardzo duży plik tekstowy i wygenerować bardzo duży dokument XML przy zachowaniu niewielkiego rozmiaru pamięci.

Innym scenariuszem jest to, że masz duże drzewo XML załadowane do pamięci i chcesz utworzyć przekształconą wersję dokumentu. Jeśli utworzysz nowy dokument przy użyciu metody XElement, po zakończeniu transformacji będziesz mieć dwa duże drzewa XML w pamięci. Jeśli jednak utworzysz nowe drzewo XML przy użyciu polecenia XStreamingElement, zestaw roboczy będzie skutecznie wycinany w połowie.

Należy pamiętać, że podczas debugowania programu, który używa XStreamingElementmetody , wyświetlając wartość obiektu powoduje wywołanie jego ToString metody. Powoduje to serializacji kodu XML. Jeśli semantyka zapytania elementu przesyłania strumieniowego jest taka, że element przesyłania strumieniowego może być przesyłany strumieniowo tylko raz, może to spowodować niepożądane zachowanie w środowisku debugowania.

Konstruktory

XStreamingElement(XName)

Inicjuje XElement nowe wystąpienie klasy z określonego XNameelementu .

XStreamingElement(XName, Object)

Inicjuje XStreamingElement nowe wystąpienie klasy o określonej nazwie i zawartości.

XStreamingElement(XName, Object[])

Inicjuje XStreamingElement nowe wystąpienie klasy o określonej nazwie i zawartości.

Właściwości

Name

Pobiera lub ustawia nazwę tego elementu przesyłania strumieniowego.

Metody

Add(Object)

Dodaje określoną zawartość jako elementy podrzędne do tego XStreamingElementelementu .

Add(Object[])

Dodaje określoną zawartość jako elementy podrzędne do tego XStreamingElementelementu .

Equals(Object)

Określa, czy dany obiekt jest taki sam, jak bieżący obiekt.

(Odziedziczone po Object)
GetHashCode()

Służy jako domyślna funkcja skrótu.

(Odziedziczone po Object)
GetType()

Type Pobiera bieżące wystąpienie.

(Odziedziczone po Object)
MemberwiseClone()

Tworzy płytkią kopię bieżącego Objectelementu .

(Odziedziczone po Object)
Save(Stream)

Zwraca tę wartość XStreamingElement do określonego Streamelementu .

Save(Stream, SaveOptions)

Zwraca tę XStreamingElement wartość do określonego Streamelementu , opcjonalnie określając zachowanie formatowania.

Save(String)

Serializuj ten element przesyłania strumieniowego do pliku.

Save(String, SaveOptions)

Serializuj ten element przesyłania strumieniowego do pliku, opcjonalnie wyłączając formatowanie.

Save(TextWriter)

Serializuj ten element przesyłania strumieniowego do elementu TextWriter.

Save(TextWriter, SaveOptions)

Serializuj ten element przesyłania strumieniowego TextWriterdo elementu , opcjonalnie wyłączając formatowanie.

Save(XmlWriter)

Serializuj ten element przesyłania strumieniowego do elementu XmlWriter.

ToString()

Zwraca sformatowany (wcięcie) kod XML dla tego elementu przesyłania strumieniowego.

ToString(SaveOptions)

Zwraca kod XML dla tego elementu przesyłania strumieniowego, opcjonalnie wyłączając formatowanie.

WriteTo(XmlWriter)

Zapisuje ten element przesyłania strumieniowego do elementu XmlWriter.

Dotyczy

Zobacz też