Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

xml read issues

138 views
Skip to first unread message

parez

unread,
Apr 3, 2009, 5:27:35 PM4/3/09
to
Hi All,

This is the xml that i am trying to read.

<Root>
<some />
<users>
<user>
//stuff
</user>
<user>
//stuff
</user>

<user>
//stuff
</user>
<user>
//stuff
</user>
<users>
</Root>


The following method reads only alternate user elements if xml is one
line.(no new lines in the xml)
but it works fine other wise.

public static IEnumerable<XElement> GetXmlElementsFromPath(this
XmlReader reader, params string[] matchTerms)
{


while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
{
if (matchTerms.Contains
(reader.Name))
{
XElement el = (XElement)
XElement.ReadFrom(reader);
if (el != null)
yield return el;
}
}
break;
}
}
}


Thanks in advance.

Peter Duniho

unread,
Apr 3, 2009, 5:50:53 PM4/3/09
to
On Fri, 03 Apr 2009 14:27:35 -0700, parez <psa...@gmail.com> wrote:

> Hi All,
>
>
>
> This is the xml that i am trying to read.
>
> <Root>
> <some />
> <users>

> [...]
> <users>
> </Root>

I assume that's not really your XML.

> The following method reads only alternate user elements if xml is one
> line.(no new lines in the xml)
> but it works fine other wise.

Off the top of my head, I'm guessing that the XNode.ReadFrom() method is
positioning the reader at the next XML node, which you then skip over
using the XmlReader.Read() method at the top of your loop. Looking at the
implementation using Reflector, that seems to be true. The last thing
XNode does before returning is call XmlReader.Read(), advancing the
position of the reader.

The code you posted is practically identical to the code in MSDN, so you
seem to have inherited the bug from there. If my theory is correct, you
should be able to remove the call to XmlReader.Read(), and just repeatedly
call XNode.ReadFrom() instead. Note, of course, you'll have to check the
actual type of the node, and ignore any that aren't XElement instances.

If you do this and confirm the bug in the MSDN code, please submit
feedback to Microsoft regarding the problem in their documentation.

Pete

parez

unread,
Apr 3, 2009, 6:14:02 PM4/3/09
to
On Apr 3, 5:50 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:

Thank Pete ....

That is exactly what the problem was..

And that is not the xml that i am using.

Changed to following.. and it looks good for now. I will spend more
time on it on monday to make sure everythingis good..


while (!reader.EOF)


{
switch (reader.NodeType)
{
case XmlNodeType.Element:
{
if (matchTerms.Contains(reader.Name))

//if (reader.Name == tagname)


{
XElement el = (XElement)
XElement.ReadFrom(reader);
if (el != null)
yield return el;
}

else
reader.Read();
}
break;
default:
{
reader.Read();
}
break;
}

}


parez

unread,
Apr 3, 2009, 6:18:47 PM4/3/09
to
>             }- Hide quoted text -
>
> - Show quoted text -

And i got the code from

http://blogs.msdn.com/xmlteam/archive/2007/03/24/streaming-with-linq-to-xml-part-2.aspx

I will submit feedback..

Peter Duniho

unread,
Apr 3, 2009, 6:41:11 PM4/3/09
to
On Fri, 03 Apr 2009 15:14:02 -0700, parez <psa...@gmail.com> wrote:

> [...]


> Changed to following.. and it looks good for now. I will spend more
> time on it on monday to make sure everythingis good..

I haven't tried it myself, but it seems like this would work (and would be
more elegant):

while (!reader.EOF)
{
XElement el = XNode.ReadFrom(reader) as XElement;

if (el != null && matchTerms.Contains(el.Name.ToString()))
{
yield return el;
}
}

Pete

dbru...@gmail.com

unread,
Jul 6, 2013, 7:16:16 PM7/6/13
to
I know this thread is quite old, but I found it helpful today.

To review the problem: XNode.ReadFrom advances the position of the XmlReader to the subsequent element that follows the node it reads. This causes a problem when trying to loop through all elements of a particular name, and then .ReadFrom only those nodes, such as:

while (fieldsXMLReader.ReadToFollowing("Field")) {
XElement thisFieldNode = (XElement)XNode.ReadFrom(fieldsXMLReader);

//do something with thisFieldNode that we read
}

The symptom is that only every other element gets read...because the .ReadFrom advances to the next element but then the .ReadToFollowing immediately skips that element and reads to the next one.

One way to avoid the problem is to use a second reader, like this:

while (fieldsXMLReader.ReadToFollowing("Field")) {
XmlReader thisSubtreeXMLReader = fieldsXMLReader.ReadSubtree();
thisSubtreeXMLReader.MoveToContent();

XElement thisFieldNode = (XElement)XNode.ReadFrom(thisSubtreeXMLReader);

//do something with thisFieldNode that we read
}

In this way, the XNode.ReadFrom will advance the second reader only...leaving the position of the first reader used by the loop intact.

Note that the .MoveToContent() call is necessary to avoid an error "The XmlReader state should be Interactive."

This approach of using a second reader allows the loop code to remain uncluttered with tests for the node type and element name.

Just thought I'd pass on what I learned...
0 new messages