I am using the XmlReader to parse XML data received over a socket. The data is sometimes broken into separate packets and when that happens, XmlReader will throw an XmlException for the incomplete XML. When this happens, I want to keep the partial XML message and concatenate it with the next data I receive which will contain the remaining XML. The problem I am having is keeping only the incomplete XML.
Here's sample XML (from Sample XML File) that illustrates the problem:
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<description>A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.</description>
</book>
<book id="bk103">
<author>Corets, Eva</author>
<title>Maeve Ascendant</title>
<description>After the collapse of a nanotechnology
society in England, the young survivors lay the
foundation for a new society.</description>
</book>
Imagine 100 books were sold in one transaction and that the XML was divided in two packets. The 1st packet could end like this:
<book id="bk103">
<author>Corets, Eva</author>
<title>Maeve Ascendant</title>
<description>After the collapse of a nano
and the following packet would contain the rest of the XML:
technology
society in England, the young survivors lay the
foundation for a new society.</description>
</book>
XmlReader will parse the first two books properly and I can get the XML using ReadOuterXml. It will then throw an exception on the 3rd book so I want to keep, from the original XML, only the substring starting at <book id="bk103">. XmlException gives me the LineNumber and LinePosition of the error but this is not the position I want. Instead, after each XML element XmlReader has read, I can cast my XmlReader as IXmlLineInfo and get the position of the reader after ReadOuterXml is called. This gives me a LineNumber and LinePosition again.
My question is: how can I convert LineNumber and LinePosition to an index within my original XML string. In the XML example I used, the XmlException would be at Line 17, Position 44. The position after the last valid element would be Line 13, Position 8. The position I am looking for is 440.
TL;DR
How do I get 440 from Line 13, Position 8. I am looking to use Substring on the original XML.
One simplistic way to do it is to loop to find the position of the 12th instance of System.Environment.NewLine, then add the value of LinePosition to that position:
In this code:
_bufferis a BlockingCollection of String data received from socket._xmlReaderSettingsis an XmlReaderSettings object with ValidationType set toValidationType.Noneand ConformanceLevel set toConformanceLevel.Fragment._buffer.Is there a better way to do this?