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.
Előfordul, hogy tetszőlegesen nagy XML-fájlokat kell beolvasnia, és meg kell írnia az alkalmazást, hogy az alkalmazás memóriaigénye kiszámítható legyen. Ha egy XML-fát nagy XML-fájllal próbál feltölteni, a memóriahasználat arányos lesz a fájl méretével, vagyis túlzottan. Ezért inkább streamelési technikát kell használnia.
Az egyik lehetőség az alkalmazás írása a következővel XmlReader: . Előfordulhat azonban, hogy a LINQ használatával szeretné lekérdezni az XML-fát. Ha igen, megírhatja saját egyéni tengelymetódusát. További információ: LINQ írása XML-tengelyre.
Saját tengelymetódus írásához írjon egy kis metódust, amely a XmlReader csomópontok olvasására használja, amíg el nem éri az egyik csomópontot, amelyben érdekli. A metódus ezután meghívja a metódust ReadFrom, amely az XmlReader XML-töredékből olvas be és példányosít. Ezután az egyes töredékeket yield return az egyéni tengelymetódus számbavételét tartalmazó metódusba adja át. Ezután linq-lekérdezéseket írhat az egyéni tengely metódusára.
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. Ha olyan lekérdezési operátort használ, amely az első elem létrehozása előtt hasznosítja a forrását, nem fog kis memóriaigényt megőrizni.
Példa: Egyéni tengelymetódus implementálása és használata, amely xml-töredékeket streamel egy URI által megadott fájlból
Néha a probléma csak egy kicsit érdekesebb lesz. Az alábbi XML-dokumentumban az egyéni tengelymetódus fogyasztójának ismernie kell annak az ügyfélnek a nevét is, amelyhez az egyes elemek tartoznak.
<?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>
A példa módszere az, hogy a fejlécinformációkat is figyeli, menti a fejlécadatokat, majd létrehoz egy kis XML-fát, amely tartalmazza a fejlécadatokat és az enumerálandó részleteket is. A tengelymetódus ezután ezt az új, kis XML-fát adja meg. A lekérdezés ezután hozzáfér a fejlécadatokhoz és a részletes információkhoz.
Ez a megközelítés kis memóriaigényű. Mivel minden részlet XML-töredékét kihozták, a rendszer nem tartalmaz hivatkozásokat az előző töredékre, és a szemétgyűjtéshez is elérhető. Ez a technika sok rövid élettartamú objektumot hoz létre a halomon.
Az alábbi példa bemutatja, hogyan implementálhat és használhat olyan egyéni tengelymetódus-metódust, amely xml-töredékeket streamel az URI által megadott fájlból. Ez az egyéni tengely úgy van megírva, hogy olyan dokumentumot vár, amely tartalmazza Customer, Nameés Item elemeit, és hogy ezek az elemek a fenti Source.xml dokumentumhoz hasonlóan lesznek elrendezve. Ez egy egyszerű megvalósítás. Egy robusztusabb implementáció készen áll egy érvénytelen dokumentum elemzésére.
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)
{
XElement xmlTree = new XElement("Root",
from el in StreamCustomerItem("Source.xml")
where (int)el.Element("Key") >= 3 && (int)el.Element("Key") <= 7
select new XElement("Item",
new XElement("Customer", (string)el.Parent.Element("Name")),
new XElement(el.Element("Key"))
)
);
Console.WriteLine(xmlTree);
}
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 xmlTree = <Root>
<%=
From el In StreamCustomerItem("Source.xml")
Let itemKey = CInt(el.<Key>.Value)
Where itemKey >= 3 AndAlso itemKey <= 7
Select <Item>
<Customer><%= el.Parent.<Name>.Value %></Customer>
<%= el.<Key> %>
</Item>
%>
</Root>
Console.WriteLine(xmlTree)
End Sub
End Module
Ez a kód a következő kimenetet állítja elő:
<Root>
<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>
</Root>