Current line number from a System.Xml.XmlReader (C# & .Net)
Asked Answered
K

3

28

Does anyone know how I can get the current line number of an System.Xml.XmlReader? I am trying to record where in a file I find Xml elements.

Koblenz answered 7/3, 2009 at 0:58 Comment(0)
A
47

Take advantage of the IXmlLineInfo interface supported by an XmlReader:

IXmlLineInfo xmlInfo = (IXmlLineInfo)reader;
int lineNumber = xmlInfo.LineNumber;
Antiseptic answered 7/3, 2009 at 1:2 Comment(5)
Looks like bad practice. As XmlReader does not inherit IXmlLineInfo then implementations of this abstract class may not implement the interface. A check for support of the interface is needed.Unprecedented
Please Use IXmlLineInfo xmlInfo = reader as IXmlLineInfo; This good code practice. @shuvraPapilloma
I can confirm @Unprecedented 's comment because XmlNodeReader does not inherit IXmlLineInfoMissie
Got myself a nice null out of that. So it depends which XmlReader implementation you got. Not safe.Fawnfawna
What if LineNumber or LinePosition exceeds the maximum for a signed 32-bit integer? Yes, that is a problem I have at this time.Laurentium
D
3

Expanding on the IXmlLineInfo interface, the documentation for this is pretty bad; from doing a bit of digging, I can tell you the following:

1) System.Xml.XmlReader is abstract, so you're never going to be dealing with an instance of this, as such, the fact that it doesn't implement IXmlLineInfo isn't massively concerning (although, if it did, it would make everything just that little bit easier :) )

2) The System.Xml.IXmlLineInfo interface provides two properties: LineNumber and LinePosition (which are the things we care about), plus a method: HasLineInfo() which, according to the documentation, will let you know if an implementor can return the lineinfo.

3) Of the documented inheritors of System.Xml.XmlReader, we have:

System.Xml.XmlDictionaryReader - abstract, used by WCF for serialization, no IXmlLineInfo
System.Xml.XmlNodeReader - used when reading a node, no IXmlLineInfo
System.Xml.XmlTextReader - used when reading a stream of data, has IXmlLineInfo
System.Xml.XmlValidatingReader - used when reading a stream of data and validating, has IXmlLineInfo.

Looking at the above list, the XmlDictionaryReader is going to be used internally, the XmlNodeReader is going to be used when you've passed in a node to be read (which, having been parsed, is already untethered from its source document), the XmlTextReader and XmlValidtingReader (both of which implement IXmlLineInfo), are going to be used when you're reading from a document. So, the long and the short of it seems to be that if it's possible or useful to give you position information, the framework will do so.

That being said, the documentation seems to be very light. Having just done this, I ended up doing (with _xr being an unknown concrete implementation of System.Xml.XmlReader):

string position = "(unknown)";
    if (_xr != null && typeof(System.Xml.IXmlLineInfo).IsInstanceOfType(_xr) &&
((System.Xml.IXmlLineInfo)_xr).HasLineInfo())
    {
        System.Xml.IXmlLineInfo li = (System.Xml.IXmlLineInfo)_xr;
        position = "(" + li.LineNumber.ToString() + "," + li.LinePosition.ToString() + ")";
    }

With all of that being said, when I actually run the code above, the type of _xr ends up being System.Xml.XsdValidatingReader (good luck finding documentation on that!), which inherits from System.Xml.XmlReader, but doesn't inherit from System.Xml.XmlValidatingReader or System.Xml.XmlTextReader. As such, it's probably wise to use an approach like the above.

Doriadorian answered 19/7, 2017 at 6:6 Comment(0)
D
0

A small refinement on Daniel's long standing answer, using IXmlLineInfo and 'modern' c#:

int lineNumber = (reader is IXmlLineInfo xmlLine && xmlLine.HasLineInfo()) ? xmlLine.LineNumber : -1;
Daddy answered 10/4, 2024 at 6:14 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.