Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Néha át kell alakítania a nagy XML-fájlokat, és meg kell írnia az alkalmazást, hogy az alkalmazás memóriaigénye kiszámítható legyen. Ha nagyon nagy XML-fájllal próbál feltölteni egy XML-fát, a memóriahasználat arányos lesz a fájl méretével (azaz túlzott). Ezért inkább streamelési technikát kell használnia.
A streamelési technikák akkor alkalmazhatók a legjobban, ha a forrásdokumentumot csak egyszer kell feldolgoznia, és az elemeket dokumentumsorrendben is feldolgozhatja. Bizonyos szabványos lekérdezési operátorok, például OrderBya forrás iterálása, az összes adat összegyűjtése, rendezése, majd végül a sorozat első eleme. Vegye figyelembe, hogy ha olyan lekérdezési operátort használ, amely az első elem létrehozása előtt a forrását hasznosítja, nem fog kis memóriaigényt megőrizni az alkalmazás számára.
Még akkor is, ha az XML-töredékek fejlécadatokhoz való hozzáféréssel való streameléséhez leírt technikát használja, ha megpróbál összeállítani egy XML-fát, amely tartalmazza az átalakított dokumentumot, a memóriahasználat túl nagy lesz.
Két fő megközelítés létezik. Az egyik módszer a halasztott feldolgozási jellemzők XStreamingElementhasználata. Egy másik megközelítés egy XmlWriter, és használja a képességek LINQ XML-hez írni elemeket egy XmlWriter. Ez a cikk mindkét módszert bemutatja.
Példa: A kimenet streameléséhez XStreamingElement használja a késleltetett végrehajtási képességeket
Az alábbi példa az XML-töredékek streamelése fejlécadatokhoz való hozzáféréssel című példán alapul.
Ez a példa a kimenet streameléséhez XStreamingElement a késleltetett végrehajtási képességeket használja. Ez a példa átalakíthat egy nagyon nagy dokumentumot, miközben kis memóriaigényt tart fenn.
Vegye figyelembe, hogy az egyéni tengely (StreamCustomerItem) kifejezetten úgy van megírva, hogy olyan dokumentumot várjon, amely rendelkezik Customer, Nameés Item elemeket tartalmaznak, és hogy ezek az elemek az alábbi Source.xml dokumentumban leírtak szerint lesznek elrendezve. Egy robusztusabb implementáció azonban készen áll egy érvénytelen dokumentum elemzésére.
A forrásdokumentum Source.xml a következő:
<?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>
static IEnumerable<XElement> StreamCustomerItem(string uri)
{
using XmlReader reader = XmlReader.Create(uri);
reader.MoveToContent();
// Parse the file, save header information when encountered, and yield the
// Item XElement objects as they're created.
// Loop through Customer elements
do
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Customer")
{
// Move to Name element
XElement? name = null;
do
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Name")
{
name = XNode.ReadFrom(reader) as XElement;
break;
}
}
while (reader.Read());
// Loop through Item elements
while (reader.NodeType != XmlNodeType.EndElement)
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Item")
{
if (XNode.ReadFrom(reader) is XElement item && name != null)
{
XElement tempRoot = new XElement("Root",
new XElement(name),
item
);
yield return item;
}
}
else if (!reader.Read())
break;
}
}
}
while (reader.Read());
}
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"));
}
Imports System.IO
Imports System.Xml
Module Module1
Public Iterator Function StreamCustomerItem(uri As String) As IEnumerable(Of XElement)
Using reader As XmlReader = XmlReader.Create(uri)
reader.MoveToContent()
' Parse the file, save header information when encountered, And yield the
' Item XElement objects as they're created.
' Loop through Customer elements
Do
If reader.NodeType = XmlNodeType.Element And reader.Name = "Customer" Then
' Move to Name element
Dim name As XElement = Nothing
Do
If reader.NodeType = XmlNodeType.Element And reader.Name = "Name" Then
name = TryCast(XNode.ReadFrom(reader), XElement)
Exit Do
End If
Loop While reader.Read()
' Loop through Item elements
While reader.NodeType <> XmlNodeType.EndElement
If reader.NodeType = XmlNodeType.Element And reader.Name = "Item" Then
Dim item = TryCast(XNode.ReadFrom(reader), XElement)
If name IsNot Nothing AndAlso item IsNot Nothing Then
Dim tempRoot = <Root>
<Name><%= name.Value %></Name>
<%= item %>
</Root>
Yield item
End If
ElseIf Not reader.Read() Then
Exit While
End If
End While
End If
Loop While reader.Read()
End Using
End Function
Sub Main()
Dim root = New XStreamingElement("Root",
From el In StreamCustomerItem("Source.xml")
Select <Item>
<Customer><%= el.Parent.<Name>.Value %></Customer>
<%= el.<Key> %>
</Item>
)
root.Save("Test.xml")
Console.WriteLine(File.ReadAllText("Test.xml"))
End Sub
End Module
Ez a példa a következő kimenetet hozza létre:
<?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>
Példa: Elemek xml-íróba írása a LINQ használatával XML-hez
Az alábbi példa az XML-töredékek streamelése fejlécadatokhoz való hozzáféréssel című példára is épül.
Ez a példa a LINQ xml-hez való képességét használja elemek írására egy XmlWriter. Ez a példa átalakíthat egy nagyon nagy dokumentumot, miközben kis memóriaigényt tart fenn.
Vegye figyelembe, hogy az egyéni tengely (StreamCustomerItem) kifejezetten úgy van megírva, hogy olyan dokumentumot várjon, amely rendelkezik Customer, Nameés Item elemeket tartalmaznak, és hogy ezek az elemek az alábbi Source.xml dokumentumban leírtak szerint lesznek elrendezve. Egy robusztusabb implementáció azonban vagy egy XSD-vel ellenőrzi a forrásdokumentumot, vagy készen áll egy érvénytelen dokumentum elemzésére.
Ez a példa ugyanazt a forrásdokumentumot használja, Source.xml, mint az előző példában. Emellett pontosan ugyanazt a kimenetet állítja elő.
A kimeneti XML-fájl streamelésére való használata XStreamingElement előnyben részesíti az írást egy XmlWriter.
static IEnumerable<XElement> StreamCustomerItem(string uri)
{
using XmlReader reader = XmlReader.Create(uri);
reader.MoveToContent();
// Parse the file, save header information when encountered, and yield the
// Item XElement objects as they're created.
// Loop through Customer elements
do
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Customer")
{
// Move to Name element
XElement? name = null;
do
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Name")
{
name = XNode.ReadFrom(reader) as XElement;
break;
}
}
while (reader.Read());
// Loop through Item elements
while (reader.NodeType != XmlNodeType.EndElement)
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Item")
{
if (XNode.ReadFrom(reader) is XElement item && name != null)
{
XElement tempRoot = new XElement("Root",
new XElement(name),
item
);
yield return item;
}
}
else if (!reader.Read())
break;
}
}
}
while (reader.Read());
}
static void Main(string[] args)
{
IEnumerable<XElement> srcTree =
from el in StreamCustomerItem("Source.xml")
select new XElement("Item",
new XElement("Customer", (string)el.Parent.Element("Name")),
new XElement(el.Element("Key"))
);
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Indent = true;
using (XmlWriter xw = XmlWriter.Create("Output.xml", xws)) {
xw.WriteStartElement("Root");
foreach (XElement el in srcTree)
el.WriteTo(xw);
xw.WriteEndElement();
}
string str = File.ReadAllText("Output.xml");
Console.WriteLine(str);
}
Imports System.IO
Imports System.Xml
Module Module1
Public Iterator Function StreamCustomerItem(uri As String) As IEnumerable(Of XElement)
Using reader As XmlReader = XmlReader.Create(uri)
reader.MoveToContent()
' Parse the file, save header information when encountered, And yield the
' Item XElement objects as they're created.
' Loop through Customer elements
Do
If reader.NodeType = XmlNodeType.Element And reader.Name = "Customer" Then
' Move to Name element
Dim name As XElement = Nothing
Do
If reader.NodeType = XmlNodeType.Element And reader.Name = "Name" Then
name = TryCast(XNode.ReadFrom(reader), XElement)
Exit Do
End If
Loop While reader.Read()
' Loop through Item elements
While reader.NodeType <> XmlNodeType.EndElement
If reader.NodeType = XmlNodeType.Element And reader.Name = "Item" Then
Dim item = TryCast(XNode.ReadFrom(reader), XElement)
If name IsNot Nothing AndAlso item IsNot Nothing Then
Dim tempRoot = <Root>
<Name><%= name.Value %></Name>
<%= item %>
</Root>
Yield item
End If
ElseIf Not reader.Read() Then
Exit While
End If
End While
End If
Loop While reader.Read()
End Using
End Function
Sub Main()
Dim srcTree =
From el In StreamCustomerItem("Source.xml")
Select <Item>
<Customer><%= el.Parent.<Name>.Value %></Customer>
<%= el.<Key> %>
</Item>
Dim xws = New Xml.XmlWriterSettings()
xws.OmitXmlDeclaration = True
xws.Indent = True
Using xw = Xml.XmlWriter.Create("Output.xml", xws)
xw.WriteStartElement("Root")
For Each el In srcTree
el.WriteTo(xw)
Next
xw.WriteEndElement()
End Using
Dim s = File.ReadAllText("Output.xml")
Console.WriteLine(s)
End Sub
End Module
Ez a példa a következő kimenetet hozza létre:
<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>