XmlTextReader - how find a particular node

G

Guest

I am reading an xml file from a URL. I was originally doing this using the
XmlDocument class. But this was very slow. The XmlTextReader is meant to be
much quicker for forward only retrieval of data.

I need to somehow access a particular list of nodes. e.g. I want to loop
through all the nodes called <item></item>. How is this possible using
XmlTextReader?
I can see that you can get the .Value property of XmlTextReader. But I want
to be able to specify the node I want to look at.

e.g.

<Group>
<Items>
<Item>content here</Item>
<Item>some more content here</Item>
<Items>
<Activity></Activity>
<Location></Location>
</Group>

thanks.

CR
 
M

Marc Gravell

you can use ReadToFollowing("Item") to jump to each Item - however, you need
to be careful, as the "intuitive" code might be (IIRC) wrong:

while(reader.ReadToFollowing("Item")) {
string content = reader.ReadElementContentAsString();
// do something with content
}

The reason this is wrong is that ReadElementContentAsString progresses
/past/ the [Item] element, so the next call to ReadToFollowing() might skip
the next row; you might be able-to do something with a sub-reader, else you
might need to check (after calling ReadElementContentAsString) if you are on
an Item element; if you are, it is the *next* one, so read it; if you
aren't, then ReadToFollowing

Marc
 
M

Michael Nemtsev

Hello CodeRazor,

http://msdn.microsoft.com/library/d...frlrfsystemxmlxmltextreaderclassnametopic.asp

use .Read() methods of XmlTextReader and then in switch (reader.NodeType)
check the case XmlNodeType.Element u want to find


C> I am reading an xml file from a URL. I was originally doing this
C> using the XmlDocument class. But this was very slow. The
C> XmlTextReader is meant to be much quicker for forward only retrieval
C> of data.
C>
C> I need to somehow access a particular list of nodes. e.g. I want to
C> loop
C> through all the nodes called <item></item>. How is this possible
C> using
C> XmlTextReader?
C> I can see that you can get the .Value property of XmlTextReader. But
C> I want
C> to be able to specify the node I want to look at.
C> e.g.
C>
C> <Group>
C> <Items>
C> <Item>content here</Item>
C> <Item>some more content here</Item>
C> <Items>
C> <Activity></Activity>
C> <Location></Location>
C> </Group>
C> thanks.
C>
C> CR
C>
---
WBR,
Michael Nemtsev :: blog: http://spaces.msn.com/laflour

"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsche
 
M

Marc Gravell

et voila (note your xml was malformed); also, generally (for large xml) I
wouldn't use a string and MemoryStream here unless I had to - but it was the
only 1-line way I could think of to initialise the reader. Loading directly
from the uri (or a file) would be an option, though...

Marc

using System;
using System.Xml;
using System.Text;
using System.IO;
namespace ReadSomeXml {
class Program {
static void Main(string[] args)
{
string xml = @"<Group>
<Items>
<Item>content here</Item>
<Item>some more content here</Item>
</Items>
<Activity></Activity>
<Location></Location>
</Group>";
using(XmlReader reader = XmlReader.Create(new
MemoryStream(Encoding.UTF8.GetBytes(xml)))) {

while(true) {
if(reader.NodeType == XmlNodeType.Element && reader.Name
== "Item") {
string content =
reader.ReadElementContentAsString();
Console.WriteLine(content);
} else {
if(!reader.ReadToFollowing("Item")) break;
}
}
}
}
}
}
Marc Gravell said:
you can use ReadToFollowing("Item") to jump to each Item - however, you
need to be careful, as the "intuitive" code might be (IIRC) wrong:

while(reader.ReadToFollowing("Item")) {
string content = reader.ReadElementContentAsString();
// do something with content
}

The reason this is wrong is that ReadElementContentAsString progresses
/past/ the [Item] element, so the next call to ReadToFollowing() might
skip the next row; you might be able-to do something with a sub-reader,
else you might need to check (after calling ReadElementContentAsString) if
you are on an Item element; if you are, it is the *next* one, so read it;
if you aren't, then ReadToFollowing

Marc

CodeRazor said:
I am reading an xml file from a URL. I was originally doing this using
the
XmlDocument class. But this was very slow. The XmlTextReader is meant to
be
much quicker for forward only retrieval of data.

I need to somehow access a particular list of nodes. e.g. I want to loop
through all the nodes called <item></item>. How is this possible using
XmlTextReader?
I can see that you can get the .Value property of XmlTextReader. But I
want
to be able to specify the node I want to look at.

e.g.

<Group>
<Items>
<Item>content here</Item>
<Item>some more content here</Item>
<Items>
<Activity></Activity>
<Location></Location>
</Group>

thanks.

CR
 
G

Guest

Thanks for your help, but I am still stumped.

I have found an inelegant way of retrieving each item's title and
description using string methods. See my code below. I would like to know how
I can retrieve the <title> and <description> nodes more directly using the
methods of the XmlTextReader.

My xml file looks somthing like:
<items>
<item><title>Title 1</title><description>Description 1</description></item>
<item><title>Title 2</title><description>Description 2</description></item>
</items>

My Hack:
XmlTextReader xmlTextReader = new XmlTextReader(myXmlUrl);

while(xmlTextReader.Read())
{
if(xmlTextReader.NodeType == XmlNodeType.Element && xmlTextReader.Name ==
"item" )
{
string itemContent = xmlTextReader.ReadOuterXml();
int headlineStart = itemContent.IndexOf("<title>") + "<title>".Length;
headlineLength = itemContent.IndexOf("</title>") - headlineStart;
descriptStart = itemContent.IndexOf("<description>") +
"<description>".Length;
int descriptLength = itemContent.IndexOf("</description>") - descriptStart;
string headline = itemContent.Substring(headlineStart,
headlineLength);
string description = itemContent.Substring(descriptStart, descriptLength);

Response.Write(headline + "<br>" + description + "<br><br>");
}

Many thanks,

CR
 

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