XMLTextReader.Name always returns ""

T

tomldn

Hi, I have the following code:

XmlTextReader reader = new XmlTextReader(@"C:\XMLTraining
\books.xml");
while (reader.Read())
{
if (reader.HasValue)
{
Debug.WriteLine("Name:" + reader.Name);
Debug.WriteLine("Depth:" + reader.Depth);
Debug.WriteLine("Value:" + reader.Value);
Debug.WriteLine("------");
}
}

Which reads this file:
<bookstore>
<book genre="autobiography" publicationdate="1981"
ISBN="1-861003-11-0">
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Franklin</last-name>
</author>
<price>8.99</price>
</book>
</bookstore>

But the Name is always "", never "book", "author" etc. I know I'm
doing something dumb - anyone know what???

Cheers,

Tom
 
M

Martin Honnen

But the Name is always "", never "book", "author" etc. I know I'm
doing something dumb - anyone know what???

Well the Xml(Text)Reader does not work as you seem to expect. If you
check the documentation of HasValue
http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.hasvalue.aspx
then you will see that the nodes that can have a value are nodes like
Text or CDATA or Attribute (and some others) but not Element nodes.
Thus in your sample when you get HasValue as true the reader is
positioned on a Text node and Text nodes don't have a name.

"book" and "author" are element nodes and don't have a value in terms of
the XmlReader API. You might want to use XPathNavigator to parse the
XML, then you can select an element node and access its string value.
 
T

tomldn

Well the Xml(Text)Reader does not work as you seem to expect. If you
check the documentation of HasValuehttp://msdn.microsoft.com/en-us/library/system.xml.xmlreader.hasvalue...
then you will see that the nodes that can have a value are nodes like
Text or CDATA or Attribute (and some others) but not Element nodes.
Thus in your sample when you get HasValue as true the reader is
positioned on a Text node and Text nodes don't have a name.

"book" and "author" are element nodes and don't have a value in terms of
the XmlReader API. You might want to use XPathNavigator to parse the
XML, then you can select an element node and access its string value.

Hi, thanks for the response.

Surely reader.Name should return "book" or "author" etc when it's on
those nodes?

Tom
 
M

Martin Honnen

Surely reader.Name should return "book" or "author" etc when it's on
those nodes?

On which nodes exactly? If it is positioned on a text node? No, a Text
node has a value but it does not have a name. An Element node has a name
but it does not have a value.
If you want to find element nodes then you need to check for the
NodeType e.g.

using (XmlReader reader =
XmlReader.Create(@"..\..\XMLFile2.xml"))
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
Console.WriteLine(
"Parsing element named \"{0}\"", reader.Name);
}
}
}

for your sample outputs

Parsing element named "bookstore"
Parsing element named "book"
Parsing element named "title"
Parsing element named "author"
Parsing element named "first-name"
Parsing element named "last-name"
Parsing element named "price"


As I said, I wouldn't bother with parsing such short XML documents with
the low level XmlReader API, use XPath (XPathNavigator) instead, or LINQ
to XML in .NET 3.5, both have Value properties that are closer to what
you seem to expect.

Here is an example with XPathNavigator:

XPathDocument doc = new XPathDocument(@"..\..\XMLFile2.xml");
foreach (XPathNavigator leafEl in
doc.CreateNavigator().Select("//*[not(*)]"))
{
Console.WriteLine(
"Element named \"{0}\" has value \"{1}\"", leafEl.Name, leafEl.Value);
}

Output for your sample is

Element named "title" has value "The Autobiography of Benjamin Franklin"
Element named "first-name" has value "Benjamin"
Element named "last-name" has value "Franklin"
Element named "price" has value "8.99"


Or in .NET 3.5 you could use LINQ to XML:

XDocument doc = XDocument.Load(@"..\..\XMLFile2.xml");
foreach (XElement leafEl in doc.Descendants().Where(d =>
!d.Elements().Any()))
{
Console.WriteLine(
"Element named \"{0}\" has value \"{1}\"", leafEl.Name, leafEl.Value);
}


Output is the same as above for the XPathNavigator sample.
 
T

tomldn

Output is the same as above for the XPathNavigator sample.


LOL, you're right. But it turns out it wasn't me being stupid, the
example I was following was using HasValue to check for "not null",
not.... HasValue.

Hey, thanks for your help on this.

Tom.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top