From 6df6adb9a9f62c33eed8737ce6133797c0fa7e75 Mon Sep 17 00:00:00 2001 From: Konstantin Lepeshenkov <5447190+scale-tone@users.noreply.github.com> Date: Sat, 21 Dec 2024 20:05:55 +0100 Subject: [PATCH 1/4] Fixed incorrect logic in XmlReader's example (#43799) --- .../linq/stream-xml-fragments-xmlreader.md | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/docs/standard/linq/stream-xml-fragments-xmlreader.md b/docs/standard/linq/stream-xml-fragments-xmlreader.md index bc7312acae98c..b606243b5a1c2 100644 --- a/docs/standard/linq/stream-xml-fragments-xmlreader.md +++ b/docs/standard/linq/stream-xml-fragments-xmlreader.md @@ -33,18 +33,25 @@ static IEnumerable StreamRootChildDoc(StringReader stringReader) { reader.MoveToContent(); // Parse the file and display each of the nodes. - while (reader.Read()) + while (true) { switch (reader.NodeType) { case XmlNodeType.Element: if (reader.Name == "Child") { - XElement el = XElement.ReadFrom(reader) as XElement; + XElement? el = XNode.ReadFrom(reader) as XElement; if (el != null) yield return el; + + // Should only call reader.Read(), if XNode.ReadFrom() was NOT called, + // because XNode.ReadFrom() advances the reader to the next element by itself. + continue; } break; } + + if (!reader.Read()) + break; } } } @@ -144,15 +151,29 @@ Public Class StreamChildEnumerator End Property Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext - While _reader.Read() + + _reader.MoveToContent() + + While True 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 _reader.Name = "Child" Then + Dim el = TryCast(XNode.ReadFrom(_reader), XElement) + If el IsNot Nothing Then + _current = el + Return True + End If + + ' Should only call _reader.Read(), if XNode.ReadFrom() was NOT called, + ' because XNode.ReadFrom() advances the reader to the next element by itself. + Continue While End If End Select + + If Not _reader.Read() Then + Exit While + End If + End While Return False From bc312d40c5240358b60fb6a2ad32a484b037ffed Mon Sep 17 00:00:00 2001 From: "Andy (Steve) De George" <67293991+adegeo@users.noreply.github.com> Date: Tue, 31 Dec 2024 11:46:19 -0800 Subject: [PATCH 2/4] Refactor XML streaming example in C# and VB --- .../linq/stream-xml-fragments-xmlreader.md | 223 ++++++------------ 1 file changed, 73 insertions(+), 150 deletions(-) diff --git a/docs/standard/linq/stream-xml-fragments-xmlreader.md b/docs/standard/linq/stream-xml-fragments-xmlreader.md index b606243b5a1c2..c9ce1d85843c8 100644 --- a/docs/standard/linq/stream-xml-fragments-xmlreader.md +++ b/docs/standard/linq/stream-xml-fragments-xmlreader.md @@ -27,184 +27,107 @@ 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 (true) + // 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 = XNode.ReadFrom(reader) as XElement; - if (el != null) - yield return el; - - // Should only call reader.Read(), if XNode.ReadFrom() was NOT called, - // because XNode.ReadFrom() advances the reader to the next element by itself. - continue; - } - break; - } - - if (!reader.Read()) - break; + // Get the current node and advance the reader to the next + if (XNode.ReadFrom(reader) is XElement el) + yield return el; + else + continue; } + 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 = @" + aaafdafda + 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 - - _reader.MoveToContent() - - While True - Select Case _reader.NodeType - Case Xml.XmlNodeType.Element - If _reader.Name = "Child" Then - Dim el = TryCast(XNode.ReadFrom(_reader), XElement) - If el IsNot Nothing Then - _current = el - Return True - End If - - ' Should only call _reader.Read(), if XNode.ReadFrom() was NOT called, - ' because XNode.ReadFrom() advances the reader to the next element by itself. + If (el IsNot Nothing) Then + Yield el + Else Continue While End If - End Select - - If Not _reader.Read() Then - Exit While - End If - End While + ElseIf Not reader.Read() Then + Exit While + End If - Return False + 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: From 79295e0df5cd9cd03ca32e921e9f646aefa0e2bc Mon Sep 17 00:00:00 2001 From: "Andy (Steve) De George" <67293991+adegeo@users.noreply.github.com> Date: Tue, 31 Dec 2024 11:50:25 -0800 Subject: [PATCH 3/4] Format XML string for better readability --- .../linq/stream-xml-fragments-xmlreader.md | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/standard/linq/stream-xml-fragments-xmlreader.md b/docs/standard/linq/stream-xml-fragments-xmlreader.md index c9ce1d85843c8..8da48ead12818 100644 --- a/docs/standard/linq/stream-xml-fragments-xmlreader.md +++ b/docs/standard/linq/stream-xml-fragments-xmlreader.md @@ -53,14 +53,19 @@ static IEnumerable StreamRootChildDoc(StringReader stringReader) } } -string markup = @" - aaafdafda - bbb - - - ccc - -"; +string markup = """ + + + aaa + + + bbb + + + ccc + + + """; IEnumerable grandChildData = from el in StreamRootChildDoc(new StringReader(markup)) From e1815642db9eb36cb8e3730d8d8102364be582ba Mon Sep 17 00:00:00 2001 From: "Andy (Steve) De George" <67293991+adegeo@users.noreply.github.com> Date: Tue, 31 Dec 2024 11:51:32 -0800 Subject: [PATCH 4/4] Remove unnecessary else statements in XML reader doc --- docs/standard/linq/stream-xml-fragments-xmlreader.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/standard/linq/stream-xml-fragments-xmlreader.md b/docs/standard/linq/stream-xml-fragments-xmlreader.md index 8da48ead12818..cdaa877cb0323 100644 --- a/docs/standard/linq/stream-xml-fragments-xmlreader.md +++ b/docs/standard/linq/stream-xml-fragments-xmlreader.md @@ -45,8 +45,7 @@ static IEnumerable StreamRootChildDoc(StringReader stringReader) // Get the current node and advance the reader to the next if (XNode.ReadFrom(reader) is XElement el) yield return el; - else - continue; + } else if (!reader.Read()) break; @@ -96,8 +95,6 @@ Module Module1 If (el IsNot Nothing) Then Yield el - Else - Continue While End If ElseIf Not reader.Read() Then