XML-töredékek streamelése XmlReaderből (LINQ-ból XML-be)
Ha nagy XML-fájlokat kell feldolgoznia, előfordulhat, hogy nem lehet betölteni a teljes XML-fát a memóriába. Ez a cikk bemutatja, hogyan streamelheti a töredékeket c XmlReader # és Visual Basic nyelven.
Az objektumok olvasásának XmlReaderXElement egyik leghatékonyabb módja a saját egyéni tengelymetódus írása. A tengelymetódusok általában olyan gyűjteményt adnak vissza, mint IEnumerable<T>XElementpéldául a jelen cikkben szereplő példában. Az egyéni tengely metódusában, miután létrehozta az XML-töredéket a ReadFrom metódus meghívásával, adja vissza a gyűjteményt a következővel yield return
: . Ez késleltetett végrehajtási szemantikát biztosít az egyéni tengely metódusához.
Amikor XML-fát hoz létre egy XmlReader objektumból, az XmlReader elemnek egy elemen kell lennie. A ReadFrom metódus csak akkor tér vissza, ha be nem olvassa az elem záró címkéjét.
Ha részleges fát szeretne létrehozni, létrehozhat egy XmlReaderpéldányt, elhelyezheti az olvasót azon a csomóponton, amelyet fává szeretne alakítani XElement , majd létrehozhatja az XElement objektumot.
Az XML-töredékek élőfej-információhoz való hozzáféréssel való streamelése című cikk egy összetettebb dokumentum streamelésére vonatkozó információkat tartalmaz.
A nagy XML-dokumentumok streamelési átalakításának végrehajtása című cikk egy példát tartalmaz arra, hogy a LINQ-t XML-ként használva rendkívül nagy XML-dokumentumokat alakíthat át, miközben kis memóriaigényt tart fenn.
Példa: Egyéni tengelymetódus létrehozása
Ez a példa létrehoz egy egyéni tengelymetódust. A lekérdezést LINQ-lekérdezéssel végezheti el. Az egyéni tengelymetódus StreamRootChildDoc
képes olvasni egy ismétlődő Child
elemet tartalmazó dokumentumot.
static IEnumerable<XElement> StreamRootChildDoc(StringReader stringReader)
{
using (XmlReader reader = XmlReader.Create(stringReader))
{
reader.MoveToContent();
// Parse the file and display each of the nodes.
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (reader.Name == "Child") {
XElement el = XElement.ReadFrom(reader) as XElement;
if (el != null)
yield return el;
}
break;
}
}
}
}
static void Main(string[] args)
{
string markup = @"<Root>
<Child Key=""01"">
<GrandChild>aaa</GrandChild>
</Child>
<Child Key=""02"">
<GrandChild>bbb</GrandChild>
</Child>
<Child Key=""03"">
<GrandChild>ccc</GrandChild>
</Child>
</Root>";
IEnumerable<string> grandChildData =
from el in StreamRootChildDoc(new StringReader(markup))
where (int)el.Attribute("Key") > 1
select (string)el.Element("GrandChild");
foreach (string str in grandChildData) {
Console.WriteLine(str);
}
}
Module Module1
Sub Main()
Dim markup = "<Root>" &
" <Child Key=""01"">" &
" <GrandChild>aaa</GrandChild>" &
" </Child>" &
" <Child Key=""02"">" &
" <GrandChild>bbb</GrandChild>" &
" </Child>" &
" <Child Key=""03"">" &
" <GrandChild>ccc</GrandChild>" &
" </Child>" &
"</Root>"
Dim grandChildData =
From el In New StreamRootChildDoc(New IO.StringReader(markup))
Where CInt(el.@Key) > 1
Select el.<GrandChild>.Value
For Each s In grandChildData
Console.WriteLine(s)
Next
End Sub
End Module
Public Class StreamRootChildDoc
Implements IEnumerable(Of XElement)
Private _stringReader As IO.StringReader
Public Sub New(ByVal stringReader As IO.StringReader)
_stringReader = stringReader
End Sub
Public Function GetEnumerator() As IEnumerator(Of XElement) Implements IEnumerable(Of XElement).GetEnumerator
Return New StreamChildEnumerator(_stringReader)
End Function
Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
Return Me.GetEnumerator()
End Function
End Class
Public Class StreamChildEnumerator
Implements IEnumerator(Of XElement)
Private _current As XElement
Private _reader As Xml.XmlReader
Private _stringReader As IO.StringReader
Public Sub New(ByVal stringReader As IO.StringReader)
_stringReader = stringReader
_reader = Xml.XmlReader.Create(_stringReader)
_reader.MoveToContent()
End Sub
Public ReadOnly Property Current As XElement Implements IEnumerator(Of XElement).Current
Get
Return _current
End Get
End Property
Public ReadOnly Property Current1 As Object Implements IEnumerator.Current
Get
Return Me.Current
End Get
End Property
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
While _reader.Read()
Select Case _reader.NodeType
Case Xml.XmlNodeType.Element
Dim el = TryCast(XElement.ReadFrom(_reader), XElement)
If el IsNot Nothing Then
_current = el
Return True
End If
End Select
End While
Return False
End Function
Public Sub Reset() Implements IEnumerator.Reset
_reader = Xml.XmlReader.Create(_stringReader)
_reader.MoveToContent()
End Sub
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
_reader.Close()
End If
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Ez a példa a következő kimenetet hozza létre:
bbb
ccc
Az ebben a példában használt technika még több millió elem esetében is kis memóriaigényt Child
tart fenn.
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: