@@ -24,6 +24,7 @@ public MiniXmlReader(ReadOnlySpan<char> xml)
2424 /// Skips a processing instruction.
2525 /// </summary>
2626 /// <returns>True if a processing instruction was skipped; otherwise, false.</returns>
27+ /// <exception cref="Exception">Something unexpected has failed.</exception>
2728 public bool SkipProcessingInstruction ( )
2829 {
2930 _ = SkipSpaces ( ) ;
@@ -50,6 +51,7 @@ public bool SkipProcessingInstruction()
5051 /// Skips a start element.
5152 /// </summary>
5253 /// <param name="name">The name of the element to skip.</param>
54+ /// <exception cref="Exception">Something unexpected has failed.</exception>
5355 public bool SkipStartElement ( ReadOnlySpan < char > name )
5456 {
5557 _ = SkipSpaces ( ) ;
@@ -108,9 +110,13 @@ public bool SkipStartElement()
108110 /// </summary>
109111 /// <param name="attributes">The attributes of the element.</param>
110112 /// <returns>The name of the element.</returns>
113+ /// <exception cref="Exception">Not a start element or something unexpected has failed.</exception>
111114 public ReadOnlySpan < char > ReadStartElement ( out Dictionary < string , string > attributes )
112115 {
113- var name = BeginReadStartElement ( ) ;
116+ if ( ! TryBeginReadStartElement ( out var name ) )
117+ {
118+ throw new Exception ( "Not a start element" ) ;
119+ }
114120
115121 attributes = ReadAttributes ( ) ;
116122
@@ -121,37 +127,84 @@ public ReadOnlySpan<char> ReadStartElement(out Dictionary<string, string> attrib
121127 /// Reads a start element.
122128 /// </summary>
123129 /// <returns>The name of the element.</returns>
130+ /// <exception cref="Exception">Not a start element or something unexpected has failed.</exception>
124131 public ReadOnlySpan < char > ReadStartElement ( )
125132 {
126- var name = BeginReadStartElement ( ) ;
133+ if ( ! TryBeginReadStartElement ( out var name ) )
134+ {
135+ throw new Exception ( "Not a start element" ) ;
136+ }
127137
128138 SkipAttributes ( ) ;
129139
130140 return name ;
131141 }
132142
133143 /// <summary>
134- /// Reads a start element.
144+ /// Tries reading a start element.
135145 /// </summary>
136- /// <param name="name">The name of the element to read .</param>
146+ /// <param name="name">The name of the element to match .</param>
137147 /// <param name="attributes">The attributes of the element.</param>
138148 /// <returns>True if a start element was read; otherwise, false.</returns>
139149 /// <exception cref="Exception">Something unexpected has failed.</exception>
140- public bool ReadStartElement ( ReadOnlySpan < char > name , [ NotNullWhen ( true ) ] out Dictionary < string , string > ? attributes )
150+ public bool TryReadStartElement ( ReadOnlySpan < char > name , [ NotNullWhen ( true ) ] out Dictionary < string , string > ? attributes )
141151 {
142152 SkipSpaces ( ) ;
143153
144154 var safePosition = position ;
145155
146- if ( ! SkipChar ( '<' ) )
156+ if ( ! SkipChar ( '<' ) || ! ValidateElementName ( name ) )
147157 {
148- throw new Exception ( "Not a start element" ) ;
158+ position = safePosition ;
159+ attributes = null ;
160+ return false ;
149161 }
150162
151- if ( ! ValidateElementName ( name ) )
163+ attributes = ReadAttributes ( ) ;
164+
165+ return true ;
166+ }
167+
168+ /// <summary>
169+ /// Tries reading a start element.
170+ /// </summary>
171+ /// <param name="name">The name of the element to match.</param>
172+ /// <returns>True if a start element was read; otherwise, false.</returns>
173+ /// <exception cref="Exception">Something unexpected has failed.</exception>
174+ public bool TryReadStartElement ( ReadOnlySpan < char > name )
175+ {
176+ SkipSpaces ( ) ;
177+
178+ var safePosition = position ;
179+
180+ if ( ! SkipChar ( '<' ) || ! ValidateElementName ( name ) )
152181 {
153182 position = safePosition ;
183+ return false ;
184+ }
185+
186+ SkipAttributes ( ) ;
187+
188+ return true ;
189+ }
190+
191+ /// <summary>
192+ /// Tries reading a start element.
193+ /// </summary>
194+ /// <param name="name">The returned name of the element.</param>
195+ /// <param name="attributes">The attributes of the element.</param>
196+ /// <returns>True if a start element was read; otherwise, false.</returns>
197+ /// <exception cref="Exception">Something unexpected has failed.</exception>
198+ public bool TryReadStartElement ( out ReadOnlySpan < char > name , [ NotNullWhen ( true ) ] out Dictionary < string , string > ? attributes )
199+ {
200+ SkipSpaces ( ) ;
201+
202+ var safePosition = position ;
203+
204+ if ( ! TryBeginReadStartElement ( out name ) )
205+ {
154206 attributes = null ;
207+ position = safePosition ;
155208 return false ;
156209 }
157210
@@ -160,6 +213,29 @@ public bool ReadStartElement(ReadOnlySpan<char> name, [NotNullWhen(true)] out Di
160213 return true ;
161214 }
162215
216+ /// <summary>
217+ /// Tries reading a start element.
218+ /// </summary>
219+ /// <param name="name">The returned name of the element.</param>
220+ /// <returns>True if a start element was read; otherwise, false.</returns>
221+ /// <exception cref="Exception">Something unexpected has failed.</exception>
222+ public bool TryReadStartElement ( out ReadOnlySpan < char > name )
223+ {
224+ SkipSpaces ( ) ;
225+
226+ var safePosition = position ;
227+
228+ if ( ! TryBeginReadStartElement ( out name ) )
229+ {
230+ position = safePosition ;
231+ return false ;
232+ }
233+
234+ SkipAttributes ( ) ;
235+
236+ return true ;
237+ }
238+
163239 /// <summary>
164240 /// Skips an end element.
165241 /// </summary>
@@ -239,6 +315,7 @@ public bool SkipEndElement()
239315 /// Reads content of an element.
240316 /// </summary>
241317 /// <returns>The content of the element.</returns>
318+ /// <exception cref="Exception">Something unexpected has failed.</exception>
242319 public ReadOnlySpan < char > ReadContent ( )
243320 {
244321 SkipSpaces ( ) ;
@@ -254,6 +331,7 @@ public ReadOnlySpan<char> ReadContent()
254331 /// Reads content of an element as a string.
255332 /// </summary>
256333 /// <returns>The content of the element as a string.</returns>
334+ /// <exception cref="Exception">Something unexpected has failed.</exception>
257335 public string ReadContentAsString ( )
258336 {
259337 return ReadContent ( ) . ToString ( ) ;
@@ -263,6 +341,7 @@ public string ReadContentAsString()
263341 /// Reads content of an element as a boolean.
264342 /// </summary>
265343 /// <returns>The content of the element as a boolean.</returns>
344+ /// <exception cref="Exception">Something unexpected has failed.</exception>
266345 public bool ReadContentAsBoolean ( )
267346 {
268347 var content = ReadContent ( ) ;
@@ -275,6 +354,7 @@ public bool ReadContentAsBoolean()
275354 } ;
276355 }
277356
357+ /// <exception cref="Exception">Something unexpected has failed.</exception>
278358 private bool ValidateElementName ( ReadOnlySpan < char > name )
279359 {
280360 for ( var i = 0 ; i < name . Length ; i ++ )
@@ -299,6 +379,7 @@ private bool ValidateElementName(ReadOnlySpan<char> name)
299379 return true ;
300380 }
301381
382+ /// <exception cref="Exception">Something unexpected has failed.</exception>
302383 private Dictionary < string , string > ReadAttributes ( bool expectsProcessingInstruction = false )
303384 {
304385 SkipSpaces ( ) ;
@@ -337,13 +418,15 @@ private Dictionary<string, string> ReadAttributes(bool expectsProcessingInstruct
337418 return attributes ;
338419 }
339420
340- private ReadOnlySpan < char > BeginReadStartElement ( )
421+ /// <exception cref="Exception">Something unexpected has failed.</exception>
422+ private bool TryBeginReadStartElement ( out ReadOnlySpan < char > name )
341423 {
342424 SkipSpaces ( ) ;
343425
344426 if ( ! SkipChar ( '<' ) )
345427 {
346- throw new Exception ( "Not a start element" ) ;
428+ name = default ;
429+ return false ;
347430 }
348431
349432 var start = position ;
@@ -360,10 +443,10 @@ private ReadOnlySpan<char> BeginReadStartElement()
360443 Advance ( ) ;
361444 }
362445
363- var name = xml [ start ..position ] ;
446+ name = xml [ start ..position ] ;
364447
365448 Debug . WriteLine ( $ "BeginReadStartElement({ name } )") ;
366- return name ;
449+ return true ;
367450 }
368451
369452 private bool SkipChar ( char c )
@@ -379,6 +462,7 @@ private bool SkipChar(char c)
379462 return true ;
380463 }
381464
465+ /// <exception cref="Exception">Something unexpected has failed.</exception>
382466 private void SkipUntilChar ( char c , bool includeSpaces = false )
383467 {
384468 do
@@ -409,6 +493,7 @@ private bool SkipSpaces()
409493 return skipped ;
410494 }
411495
496+ /// <exception cref="Exception">Something unexpected has failed.</exception>
412497 private void SkipAttributes ( bool expectsProcessingInstruction = false )
413498 {
414499 SkipSpaces ( ) ;
@@ -441,6 +526,7 @@ private void SkipAttributes(bool expectsProcessingInstruction = false)
441526 }
442527 }
443528
529+ /// <exception cref="Exception">Something unexpected has failed.</exception>
444530 private ReadOnlySpan < char > ReadUntilChar ( char expectedChar , bool includeSpaces = false )
445531 {
446532 var start = position ;
@@ -465,6 +551,7 @@ private ReadOnlySpan<char> ReadUntilChar(char expectedChar, bool includeSpaces =
465551 return xml [ start ..position ] ;
466552 }
467553
554+ /// <exception cref="Exception">Something unexpected has failed.</exception>
468555 private void Advance ( )
469556 {
470557 if ( position == xml . Length - 1 )
0 commit comments