XStreamingElement Klasse

Definition

Stellt Elemente in einer XML-Struktur dar, die die verzögerte Streamingausgabe unterstützt.

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

Beispiele

Im folgenden Beispiel wird zunächst eine XML-Quellstruktur erstellt. Anschließend wird mithilfe XElementvon eine Transformation der XML-Quellstruktur erstellt. Durch diese Transformation wird eine neue Struktur im Arbeitsspeicher erstellt. Anschließend wird mithilfe XStreamingElementvon eine Transformation der XML-Quellstruktur erstellt. Diese Transformation führt die Abfrage erst aus, wenn die transformierte Struktur in die Konsole serialisiert wurde. Die Arbeitsspeicherauslastung ist geringer.

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)

Dieses Beispiel erzeugt die folgende Ausgabe:

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

Ein Ansatz für die Verarbeitung einer Textdatei besteht darin, eine Erweiterungsmethode zu schreiben, die die Textdatei mit dem yield return-Konstrukt zeilenweise streamt. Anschließend können Sie eine LINQ-Abfrage schreiben, die die Textdatei verzögert verarbeitet. Wenn Sie dann zum XStreamingElement Streamen der -Ausgabe verwenden, können Sie eine Transformation aus der Textdatei in XML erstellen, die unabhängig von der Größe der Quelltextdatei eine minimale Arbeitsspeichermenge verwendet.

In diesem Beispiel wird die folgende Textdatei, People.txt, als Quelldatei verwendet:

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

Der folgende Code enthält eine Erweiterungsmethode, die die Zeilen der Textdatei verzögert streamt.

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

Dieses Beispiel erzeugt die folgende Ausgabe:

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

Es kann vorkommen, dass Sie große XML-Dateien transformieren und Ihre Anwendung so schreiben müssen, dass der Arbeitsspeicherbedarf der Anwendung vorhersehbar ist. Wenn Sie versuchen, eine XML-Struktur mit einer sehr großen XML-Datei zu füllen, ändert sich Ihre Speicherbeanspruchung proportional zur Größe der Datei, also exzessiv. Deshalb sollten Sie stattdessen ein Streamingverfahren verwenden.

Einige Standardabfrageoperatoren, wie OrderBy, durchlaufen ihre Quelle, erfassen alle Daten, sortieren sie und geben dann das erste Element in der Sequenz zurück. Beachten Sie, dass Sie bei der Verwendung eines Abfrageoperators, der seine Quelle vor der Rückgabe des ersten Elements materialisiert, keine minimale Speicherbeanspruchung für Ihre Anwendung aufrechterhalten können.

Selbst wenn Sie die in beschriebene Technik verwenden, wenn Sie versuchen, eine XML-Struktur zusammenzustellen, die das transformierte Dokument enthält, kann die Speicherauslastung zu groß sein.

Das folgende Beispiel baut auf dem Beispiel unter Streamen von XML-Fragmenten mit Zugriff auf Headerinformationen auf.

In diesem Beispiel wird die verzögerte Ausführung von XStreamingElement verwendet, um die Ausgabe zu streamen.

Beachten Sie, dass die benutzerdefinierte Achse (StreamCustomerItem) so geschrieben ist, dass sie über ein Dokument mit Customer-Elementen, Name-Elementen und Item-Elementen verfügt. Diese Elemente werden wie im folgenden Source.xml-Dokument angeordnet. Eine robustere Implementierung würde jedoch entweder das Quelldokument mit einer XSD prüfen oder darauf vorbereitet sein, ein ungültiges Dokument analysieren zu können.

Das Quelldokument (Source.xml) sieht wie folgt aus:

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

Der folgende Code enthält eine -Methode, die eine XmlReader verwendet, um die Quell-XML zu streamen. Wird verwendet XStreamingElement , um die neue XML-Datei zu streamen.

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

Dieses Beispiel erzeugt die folgende Ausgabe:

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

Hinweise

Mit dieser Klasse können Sie eine XML-Struktur erstellen, die verzögerte Streamingausgabe unterstützt. Sie verwenden diese Klasse, um eine XML-Struktur auf sehr ähnliche Weise wie das Erstellen einer XML-Struktur mit XElementzu erstellen. Es gibt jedoch einen grundlegenden Unterschied. Wenn Sie eine LINQ-Abfrage verwenden, um Inhalt beim Erstellen einer XML-Struktur mit XElementanzugeben, wird die Abfragevariable zum Zeitpunkt der Erstellung der XML-Struktur durchlaufen, und die Ergebnisse der Abfrage werden der XML-Struktur hinzugefügt. Wenn Sie dagegen eine XML-Struktur mit XStreamingElementerstellen, wird ein Verweis auf die Abfragevariable in der XML-Struktur gespeichert, ohne durchlaufen zu werden. Abfragen werden nur bei der Serialisierung durchlaufen. Dadurch können Sie größere XML-Strukturen erstellen und gleichzeitig einen geringeren Speicherbedarf beibehalten.

Wenn Sie das Streaming von einer Eingabequelle wie z. B. einer Textdatei ausführen, können Sie eine sehr große Textdatei lesen und ein sehr großes XML-Dokument generieren und gleichzeitig einen geringen Speicherbedarf beibehalten.

Ein weiteres Szenario besteht darin, dass Sie über eine große XML-Struktur verfügen, die in den Arbeitsspeicher geladen wurde, und Sie möchten eine transformierte Version des Dokuments erstellen. Wenn Sie ein neues Dokument mit XElementerstellen, verfügen Sie nach Abschluss der Transformation über zwei große XML-Strukturen im Arbeitsspeicher. Wenn Sie jedoch die neue XML-Struktur mit XStreamingElementerstellen, wird Ihr Arbeitssatz effektiv halbiert.

Beachten Sie, dass beim Debuggen eines Programms, das verwendet XStreamingElement, durch die Anzeige des Werts eines Objekts ToString dessen Methode aufgerufen wird. Dies bewirkt, dass die XML-Datei serialisiert wird. Wenn die Semantik Ihrer Streamingelementabfrage so ist, dass das Streamingelement nur einmal gestreamt werden kann, kann dies zu unerwünschtem Verhalten in Ihrer Debugumgebung führen.

Konstruktoren

XStreamingElement(XName)

Initialisiert eine neue Instanz der XElement-Klasse aus dem angegebenen XName.

XStreamingElement(XName, Object)

Initialisiert eine neue Instanz der XStreamingElement-Klasse mit dem angegebenen Namen und Inhalt.

XStreamingElement(XName, Object[])

Initialisiert eine neue Instanz der XStreamingElement-Klasse mit dem angegebenen Namen und Inhalt.

Eigenschaften

Name

Ruft den Namen des Streamingelements ab oder legt diesen fest.

Methoden

Add(Object)

Fügt diesem XStreamingElement den angegebenen Inhalt als untergeordnetes Element hinzu.

Add(Object[])

Fügt diesem XStreamingElement den angegebenen Inhalt als untergeordnetes Element hinzu.

Equals(Object)

Bestimmt, ob das angegebene Objekt gleich dem aktuellen Objekt ist.

(Geerbt von Object)
GetHashCode()

Fungiert als Standardhashfunktion.

(Geerbt von Object)
GetType()

Ruft den Type der aktuellen Instanz ab.

(Geerbt von Object)
MemberwiseClone()

Erstellt eine flache Kopie des aktuellen Object.

(Geerbt von Object)
Save(Stream)

Gibt diesen XStreamingElement an den angegebenen Stream aus.

Save(Stream, SaveOptions)

Gibt dieses XStreamingElement zum angegebenen Stream aus und gibt Formatierungsverhalten optional an.

Save(String)

Serialisiert dieses Streamingelement in einer Datei.

Save(String, SaveOptions)

Serialisiert dieses Streamingelement in eine Datei, wobei optional die Formatierung deaktiviert wird.

Save(TextWriter)

Serialisiert dieses Streamingelement in einen TextWriter.

Save(TextWriter, SaveOptions)

Serialisiert dieses Streamingelement in einen TextWriter, wobei optional die Formatierung deaktiviert wird.

Save(XmlWriter)

Serialisiert dieses Streamingelement in einen XmlWriter.

ToString()

Gibt das formatierte (eingezogene) XML für dieses Streamingelement zurück.

ToString(SaveOptions)

Gibt das XML für dieses Streamingelement zurück, wobei optional die Formatierung deaktiviert wird.

WriteTo(XmlWriter)

Schreibt dieses Streamingelement in einen XmlWriter.

Gilt für:

Weitere Informationen