xml read issues

P

parez

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.
 
P

parez

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

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;
}

}
 
P

parez

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.
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 checkthe  
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.

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;
                }

            }- 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..
 
D

dbrueter

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 aproblem when trying to loop through all elements of a particular name, andthen .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...
 

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