Is it possible to save the current XMLReader Position for later use?
I work in a project where an external system writes xmls (without a defined namespace) and we need to read them to find nodes with some special values:
- When the value is not ready, we read again after a few minutes.
- In other case, we process the node (attributes, values, etc.)
So, I think this code can help you:
var input1 = @"<root> <ta> <XGLi6id90>774825484.1418393</XGLi6id90> <VAfrBVB> <EG60sk>1030847709.7303829</EG60sk> <XR>NOT_READY</XR> </VAfrBVB> </ta> <DxshpR>1123</DxshpR>
var input2 = @"<root> <ta> <XGLi6id90>774825484.1418393</XGLi6id90> <VAfrBVB> <EG60sk>1030847709.7303829</EG60sk> <XR>99999999</XR> </VAfrBVB> </ta> <DxshpR>1123</DxshpR>
var stream1 = new MemoryStream(Encoding.UTF8.GetBytes(input1));var stream2 = new MemoryStream(Encoding.UTF8.GetBytes(input2));stream1.Position = 0;stream2.Position = 0;var position1 = DoWork(stream1, new Position());var position2 = DoWork(stream2, position1); public static Position DoWork(Stream stream, Position position) { using (XmlTextReader xmlTextReader = new XmlTextReader(stream)) { using (XmlReader xmlReader = XmlReader.Create(xmlTextReader, xmlReaderSettings)) { // restores the last position xmlTextReader.SetPosition(position); System.Diagnostics.Debug.WriteLine(xmlReader.Value); // Second time prints 99999999 while (xmlReader.Value != "NOT_READY" && xmlReader.Read()) { // a custom logic to process nodes.... } // saves the position to process later ... position = xmlTextReader.GetPosition(); System.Diagnostics.Debug.WriteLine(xmlReader.Value); // First time prints NOT_READY } } return position; }}public class Position{ public int LinePosition { get; set; } public int LineNumber { get; set; }}public static class XmlReaderExtensions{ public static void SetPosition(this XmlTextReader xmlTextReader, Position position) { if (position != null) { while (xmlTextReader.LineNumber < position.LineNumber && xmlTextReader.Read()) { } while (xmlTextReader.LinePosition < position.LinePosition && xmlTextReader.Read()) { } } } public static Position GetPosition(this XmlTextReader xmlTextReader) { Position output; if (xmlTextReader.EOF) { output = new Position(); } else { output = new Position { LineNumber = xmlTextReader.LineNumber, LinePosition = xmlTextReader.LinePosition }; } return output; }}
Important and obviously, it will work only when the structure of the xml (line breaks, nodes, etc.) is always the same. In other case, it will not work.