Sign in to follow this  
acid2

[.net] XML Loading woos

Recommended Posts

Hi there! If I have an xml document that is structured like the following:
<x>
   <y></y>
   <y></y>
   <y></y>
   <y></y>
</x>
how can I recurse all of those y's? I was hoping to do something like:
foreach(XmlNode n in xmlreader.MoveTo("x").GetNodes("y"))
{ ... }
Any ideas?

Share this post


Link to post
Share on other sites
Maybe something like this:

xmlreader.ReadStartElement("x");
while (xmlreader.Name == "y")
{
string contents = xmlreader.ReadElementString();
}
xmlreader.ReadEndElement();

Share this post


Link to post
Share on other sites
I guess that was a bad example. Here's what the real structure is, which may help more:


<?xml version="1.0" encoding="utf-8" ?>

<fsm>
<state type="state" id="1">
<name></name>
<location x="300" y="200" />

<codebehind>
<codeblock enabled="1">
<name>Weee</name>
</codeblock>
<codeblock enabled="1">
<name>I_So_Pro</name>
</codeblock>
<codeblock enabled="0">
<name>Im_not</name>
</codeblock>
</codebehind>
</state>
</fsm>


I need to loop all of the states, and in that loop, I need to loop all the code blocks. I guess this is not at all my initial post really - sorry for the confusion..

Share this post


Link to post
Share on other sites
Set specific methods for handling the blocks.

void parseFSM( XmlNode a_root );
void parseFSMState( XmlNode a_root );
void parseCodeBehind( XmlNode a_root );
void parseCodeBlock( XmlNode a_root );

etc...

So the implementation of parseFSM will scan for 'state' elements and recursively pass them as the 'root' to parseFSMState to handle the states. Likewise, within state you iterate through the 'CodeBehind' elements and pass them to parseCodeBehind and so on.

I tend to add a 'parseXml' method to my objects and recursively visit them with current Xml node. The objects effectively parse themselves.


In psudeocode:


FSM::parseXml( xmlNode )
{
for each node in xmlNode where node = "state"

State s = new State();
s.parseXml( node );

next
}


State::parseXml( xmlNode )
{
for each node in xmlNode where node = "codebehind"

CodeBehind cb = new CodeBehind ();
cb.parseXml( node );

next
}




etc

Share this post


Link to post
Share on other sites
If you have not already taken a look at the XPath stuff, you ought. I don't know about speed, but it is really simple to use.

Somehting like this:

XPathDocument doc = new XPathDocument(@"test.xml");
XPathNavigator nav = doc.CreateNavigator();
XPathNodeIterator ni = nav.Select("/fsm/location");

// get all the codeblocks in your document.
nav.Select("//codeblock");

//all the enabled codeblocks
nav.Select("//codeblock[@enabled='1']");

//all the names of the states
nav.Select("//state/@name");

//etc..



It should be fairly obvious how to use the XPathNodeIterator and to get a value form a node use XPathNavigator's ToString or one of its ValueAs* methods.

here is some more on XPath syntax.

Hope this helps.

Share this post


Link to post
Share on other sites
I believe there is also a getElementsByTagName method of the XmlDocument object that returns an XmlNodeList.


...
XmlDocument doc = new XmlDocument();
doc.LoadXML(xml);
XmlNodeList stateNodes = doc.documentElement.getElementsByTagName("state");

foreach(XmlNode stateNode in stateNodes)
{
//do something with stateNode
}
...

I think that is how it would work. It's been awhile since I have worked with Xml.

Share this post


Link to post
Share on other sites
Quote:

<x>
<y></y>
<y></y>
<y></y>
<y></y>
</x>



Here is how I do it:



XmlDocument doc = new XmlDocument();

doc.Load("xmlfile.xml");

foreach (XmlNode node in doc["x"].SelectNodes("y"))
DoSomethingWithY(node);





doc["x"] is an indexer that simply calls doc.SelectSingleNode("x")...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this