XStreamingElement Klass

Definition

Representerar element i ett XML-träd som stöder uppskjutna strömmande utdata.

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

Exempel

I följande exempel skapas först ett XML-källträd. Sedan skapas en transformering av xml-källträdet med hjälp av XElement. Den här transformen skapar ett nytt träd i minnet. Sedan skapas en transformering av xml-källträdet med hjälp av XStreamingElement. Den här transformeringen kör inte frågan förrän det transformerade trädet serialiseras till konsolen. Minnesanvändningen är mindre.

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)

Det här exemplet genererar följande utdata:

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

En metod för att bearbeta en textfil är att skriva en tilläggsmetod som strömmar textfilen en rad i taget med hjälp av konstruktionen yield return . Sedan kan du skriva en LINQ-fråga som bearbetar textfilen på ett lat uppskjutet sätt. Om du sedan använder XStreamingElement för att strömma utdata kan du skapa en transformering från textfilen till XML som använder en minimal mängd minne, oavsett storleken på källtextfilen.

Följande textfil, People.txt, är källan för det här exemplet.

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

Följande kod innehåller en tilläggsmetod som strömmar textfilens rader på ett uppskjutet sätt.

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

Det här exemplet genererar följande utdata:

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

Ibland måste du transformera stora XML-filer och skriva ditt program så att programmets minnesfotavtryck är förutsägbart. Om du försöker fylla i ett XML-träd med en mycket stor XML-fil kommer minnesanvändningen att vara proportionell mot filens storlek (dvs. överdriven). Därför bör du använda en strömningsteknik i stället.

Vissa vanliga frågeoperatorer, till exempel OrderBy, itererar sin källa, samlar in alla data, sorterar dem och ger slutligen det första objektet i sekvensen. Observera att om du använder en frågeoperator som materialiserar källan innan du ger det första objektet behåller du inte ett litet minnesfotavtryck för ditt program.

Även om du använder den teknik som beskrivs i , om du försöker montera ett XML-träd som innehåller det transformerade dokumentet, kan minnesanvändningen vara för stor.

Följande exempel bygger på exemplet i Så här strömmar du XML-fragment med åtkomst till rubrikinformation.

I det här exemplet används funktionerna XStreamingElement för uppskjuten körning för att strömma utdata.

Observera att den anpassade axeln (StreamCustomerItem) är specifikt skriven så att den förväntar sig ett dokument med Customerelementen , Nameoch och Item att dessa element ordnas som i följande Source.xml dokument. En mer robust implementering skulle dock antingen validera källdokumentet med en XSD eller vara beredd att parsa ett ogiltigt dokument.

Följande är källdokumentet 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>

Följande kod innehåller en metod som använder en XmlReader för att strömma källans XML. Den använder XStreamingElement för att strömma den nya XML-koden.

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

Det här exemplet genererar följande utdata:

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

Kommentarer

Med den här klassen kan du skapa ett XML-träd som stöder uppskjutna direktuppspelningsutdata. Du använder den här klassen för att skapa ett XML-träd på ett liknande sätt som när du skapar ett XML-träd med .XElement Det finns dock en grundläggande skillnad. När du använder en LINQ-fråga för att ange innehåll när du skapar ett XML-träd med , XElementitereras frågevariabeln när XML-trädet byggs och resultatet av frågan läggs till i XML-trädet. När du däremot skapar ett XML-träd med , XStreamingElementlagras en referens till frågevariabeln i XML-trädet utan att itereras. Frågor itereras endast vid serialisering. På så sätt kan du skapa större XML-träd samtidigt som du behåller ett mindre minnesavtryck.

Om du strömmar från en indatakälla, till exempel en textfil, kan du läsa en mycket stor textfil och generera ett mycket stort XML-dokument samtidigt som du behåller ett litet minnesfotavtryck.

Ett annat scenario är att du har ett stort XML-träd som har lästs in i minnet och du vill skapa en transformerad version av dokumentet. Om du skapar ett nytt dokument med , XElementhar du två stora XML-träd i minnet när omvandlingen har slutförts. Men om du skapar det nya XML-trädet med kommer XStreamingElementarbetsuppsättningen att halveras effektivt.

Observera att när du felsöker ett program som använder XStreamingElementgör visning av värdet för ett objekt att dess ToString metod anropas. Detta gör att XML-koden serialiseras. Om semantiken i din strömningselementfråga är sådan att strömningselementet bara kan strömmas en gång kan detta orsaka oönskade beteenden i felsökningsmiljön.

Konstruktorer

Name Description
XStreamingElement(XName, Object)

Initierar en ny instans av XStreamingElement klassen med det angivna namnet och innehållet.

XStreamingElement(XName, Object[])

Initierar en ny instans av XStreamingElement klassen med det angivna namnet och innehållet.

XStreamingElement(XName)

Initierar en ny instans av XElement klassen från den angivna XName.

Egenskaper

Name Description
Name

Hämtar eller anger namnet på det här strömmande elementet.

Metoder

Name Description
Add(Object)

Lägger till det angivna innehållet som underordnade i detta XStreamingElement.

Add(Object[])

Lägger till det angivna innehållet som underordnade i detta XStreamingElement.

Equals(Object)

Avgör om det angivna objektet är lika med det aktuella objektet.

(Ärvd från Object)
GetHashCode()

Fungerar som standard-hash-funktion.

(Ärvd från Object)
GetType()

Hämtar den aktuella instansen Type .

(Ärvd från Object)
MemberwiseClone()

Skapar en ytlig kopia av den aktuella Object.

(Ärvd från Object)
Save(Stream, SaveOptions)

Matar ut detta XStreamingElement till angivet Stream, om du vill ange formateringsbeteende.

Save(Stream)

Matar ut detta XStreamingElement till den angivna Stream.

Save(String, SaveOptions)

Serialisera det här strömmande elementet till en fil, om du vill inaktivera formatering.

Save(String)

Serialisera det här strömmande elementet till en fil.

Save(TextWriter, SaveOptions)

Serialisera det här strömningselementet till en TextWriter, om du vill inaktivera formatering.

Save(TextWriter)

Serialisera det här strömmande elementet till en TextWriter.

Save(XmlWriter)

Serialisera det här strömmande elementet till en XmlWriter.

ToString()

Returnerar den formaterade (indragna) XML:en för det här strömmande elementet.

ToString(SaveOptions)

Returnerar XML för det här strömmande elementet, om du vill inaktivera formatering.

WriteTo(XmlWriter)

Skriver det här strömmande elementet till en XmlWriter.

Gäller för

Se även