From f463647760766341e0ed2a110a21dd5f8be089eb Mon Sep 17 00:00:00 2001 From: Konstantin Lepeshenkov <5447190+scale-tone@users.noreply.github.com> Date: Tue, 31 Dec 2024 20:56:26 +0100 Subject: [PATCH] Fixed incorrect logic in XmlReader's example (#43799) (#44054) * Fixed incorrect logic in XmlReader's example (#43799) * Refactor XML streaming example in C# and VB * Format XML string for better readability * Remove unnecessary else statements in XML reader doc --------- Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> --- .../linq/stream-xml-fragments-xmlreader.md | 208 +++++++----------- 1 file changed, 77 insertions(+), 131 deletions(-) diff --git a/docs/standard/linq/stream-xml-fragments-xmlreader.md b/docs/standard/linq/stream-xml-fragments-xmlreader.md index bc7312acae98c..cdaa877cb0323 100644 --- a/docs/standard/linq/stream-xml-fragments-xmlreader.md +++ b/docs/standard/linq/stream-xml-fragments-xmlreader.md @@ -27,163 +27,109 @@ The article [How to perform streaming transform of large XML documents](perform- This example creates a custom axis method. You can query it by using a LINQ query. The custom axis method `StreamRootChildDoc` can read a document that has a repeating `Child` element. ```csharp +using System.Xml; +using System.Xml.Linq; + static IEnumerable StreamRootChildDoc(StringReader stringReader) { - using (XmlReader reader = XmlReader.Create(stringReader)) + using XmlReader reader = XmlReader.Create(stringReader); + + reader.MoveToContent(); + + // Parse the file and display each of the nodes. + while (true) { - reader.MoveToContent(); - // Parse the file and display each of the nodes. - while (reader.Read()) + // If the current node is an element and named "Child" + if (reader.NodeType == XmlNodeType.Element && reader.Name == "Child") { - switch (reader.NodeType) - { - case XmlNodeType.Element: - if (reader.Name == "Child") { - XElement el = XElement.ReadFrom(reader) as XElement; - if (el != null) - yield return el; - } - break; - } + // Get the current node and advance the reader to the next + if (XNode.ReadFrom(reader) is XElement el) + yield return el; + } + else if (!reader.Read()) + break; } } -static void Main(string[] args) -{ - string markup = @" - - aaa - - - bbb - - - ccc - - "; - - IEnumerable 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); - } -} +string markup = """ + + + aaa + + + bbb + + + ccc + + + """; + +IEnumerable 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); ``` ```vb -Module Module1 - Sub Main() - Dim markup = "" & - " " & - " aaa" & - " " & - " " & - " bbb" & - " " & - " " & - " ccc" & - " " & - "" - - Dim grandChildData = - From el In New StreamRootChildDoc(New IO.StringReader(markup)) - Where CInt(el.@Key) > 1 - Select el..Value - - For Each s In grandChildData - Console.WriteLine(s) - Next - End Sub -End Module - -Public Class StreamRootChildDoc - Implements IEnumerable(Of XElement) +Imports System.Xml - 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 +Module Module1 - Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator - Return Me.GetEnumerator() - End Function -End Class + Public Iterator Function StreamRootChildDoc(stringReader As IO.StringReader) As IEnumerable(Of XElement) + Using reader As XmlReader = XmlReader.Create(stringReader) + reader.MoveToContent() -Public Class StreamChildEnumerator - Implements IEnumerator(Of XElement) + ' Parse the file and display each of the nodes. + While True - Private _current As XElement - Private _reader As Xml.XmlReader - Private _stringReader As IO.StringReader + ' If the current node is an element and named "Child" + If reader.NodeType = XmlNodeType.Element And reader.Name = "Child" Then - Public Sub New(ByVal stringReader As IO.StringReader) - _stringReader = stringReader - _reader = Xml.XmlReader.Create(_stringReader) - _reader.MoveToContent() - End Sub + ' Get the current node and advance the reader to the next + Dim el As XElement = TryCast(XNode.ReadFrom(reader), XElement) - 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 + If (el IsNot Nothing) Then + Yield el End If - End Select - End While - Return False + ElseIf Not reader.Read() Then + Exit While + End If + + End While + End Using End Function - Public Sub Reset() Implements IEnumerator.Reset - _reader = Xml.XmlReader.Create(_stringReader) - _reader.MoveToContent() - End Sub + Sub Main() -#Region "IDisposable Support" + Dim markup = " + + aaa + + + bbb + + + ccc + + " - Private disposedValue As Boolean ' To detect redundant calls + Dim grandChildData = + From el In StreamRootChildDoc(New IO.StringReader(markup)) + Where CInt(el.@Key) > 1 + Select el..Value - ' 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 + For Each s In grandChildData + Console.WriteLine(s) + Next - Public Sub Dispose() Implements IDisposable.Dispose - Dispose(True) - GC.SuppressFinalize(Me) End Sub -#End Region - -End Class +End Module ``` This example produces the following output: