Jump to content
  • Advertisement
Sign in to follow this  
Endar

C#, loading recursive data tree structure from XML file

This topic is 4237 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This is driving me a little nuts. I'm attempting to learn C# by creating a small app. Here is an example of the XML data:
<?xml version="1.0" standalone="no" ?>
<ToDoList version="1">

	<ToDoListGroup name="__root__">

		<ToDoListGroup name="Echo Graphics Engine v0.1" complete="false" date_created="30012007" date_updated="30012007" 

date_completed="none">

			<ToDoListItem name="Add Scene Graph" complete="false" date_created="29012007" date_updated="29012007" 

date_completed="none">Here is a paragraph or more of text describing what needs to be done for this list item.</ToDoListItem>

			<ToDoListGroup name="video" complete="false" date_created="29012007" date_updated="29012007" 

date_completed="none">
				<ToDoListItem name="add shadows" complete="false">Add shadows to video driver.</ToDoListItem>
			</ToDoListGroup>

		</ToDoListGroup>

	</ToDoListGroup>


	<!-- Only if a group is expanded in the TreeView control, will there be an entry present in the "ToDoListExpanded" group. -->
	<ToDoListExpanded name="__root__">

		<ToDoListExpanded name="Echo Graphics Engine v0.1">

			<ToDoListExpanded name="Add Scene Graph">

			</ToDoListExpanded>

		</ToDoListExpanded>

	</ToDoListExpanded>

</ToDoList>

And at the moment, I'm trying to get my head around loading the "ToDoListExpanded" tree of items. It is not clear from the example, but it is possible to have more than one ToDoListExpanded node at the same level. Here what I've got so far:
        /**
         * A small tree structure that will contain the names of nodes (ToDoGroup nodes)
         * that are expanded in the todo group tree.
         */
        public class ToDoListExpandedRecord
        {
            public ArrayList m_expandedList;    ///< The children of this node that are expanded
            public string m_name;               ///< The name of the node
            public bool m_isValid;              ///< If the record is a valid one
            
            /**
             * Default constructor
             * \param name The name of the group that is expanded
             */
            public ToDoListExpandedRecord(string name)
            {
                m_name = name;
                m_expandedList = new ArrayList();
                m_isValid = true;
            }

            /**
             * Add a subtree of expanded records to this subtree
             * \param r The subtree to add
             */
            public void addExpandedRecord(ToDoListExpandedRecord r)
            {
                m_expandedList.Add(r);
            }

            /**
             * Set the object to be invalid - contains no usable data
             */
            public void setInvalid()
            {
                m_isValid = false;
            }
        }


        /**
         * Load a rescursive structure that contains string to indicate which ToDo groups are currently
         * expanded in the TreeView.
         * \param xml_reader The Xml reader open to the xml file
         * \return A recursive data structure that shows, in each ToDo group, which groups are expanded in the TreeView (the
         * groups that are expanded, are the groups whose names are present in the structure).
         */ 
        public bool loadToDoListExpandedList(ref XmlTextReader xml_reader, ref ToDoListExpandedRecord rec)
        {
            // if there are more expanded records to read and it is the start of another element
            while( xml_reader.Read() ){
                // if we have the right tag name
                if( xml_reader.LocalName == "ToDoListExpanded"){
                    // if we've finished reading in a ToDoListExpanded subtree
                    if (xml_reader.NodeType == XmlNodeType.EndElement)
                        break;
                    // if we have a valid opening tag
                    else if (xml_reader.IsStartElement()){
                        ToDoListExpandedRecord temp;
                        // if we were able to load all the attributes for the expanded list record
                        if (loadToDoListExpandedListAttributes(ref xml_reader, out temp)){
                            rec.addExpandedRecord(temp);

                            // SHOULD I ATTEMPT TO LOAD ANOTHER LIST HERE?
                        }
                        // if there was an error in loading the attributes
                        else
                        {
                            MessageBox.Show("Could not load all attributes of node type ToDoListExpanded at line " +
                                xml_reader.LineNumber.ToString() + ", and position " + xml_reader.LinePosition.ToString(),
                                "Attribute Load Error", MessageBoxButtons.OK);
                            continue;
                        }

                    }// else if we have a valid opening tag

                    else{
                        MessageBox.Show("Invalid element of type " + xml_reader.NodeType.ToString() + " at line " +
                            xml_reader.LineNumber.ToString() + ", and position " + xml_reader.LinePosition.ToString(),
                            "Tag Error", MessageBoxButtons.OK);
                        continue;
                    }
                }// if node name == "ToDoListExpanded"
                // if we have an invalid opening tag
                else{
                    MessageBox.Show("Invalid open tag of " + xml_reader.LocalName + " on line " +
                        xml_reader.LineNumber.ToString() + ", and position " + xml_reader.LinePosition.ToString(),
                        "Tag Error", MessageBoxButtons.OK);
                    continue;
                }
            }

            // return the expanded list subtree
            return true;
        }

        /**
         * Read the attributes for a single ToDoListExpandedRecord item
         * \param xml_reader The reader to read the attributes from
         * \param rec The record to create and in which to store the attributes
         * \return Whether the loading was successful
         */
        public bool loadToDoListExpandedListAttributes(ref XmlTextReader xml_reader, out ToDoListExpandedRecord rec)
        {
            if (xml_reader.GetAttribute("name") == null){
                // Create a new item, but set it to be invalid, because the attribute wasn't there.
                // This should not be used.
                ToDoListExpandedRecord n = new ToDoListExpandedRecord("__empty__");
                n.setInvalid();
                rec = n;
                return false;

            }
            
            // else we have all the data we need
            rec = new ToDoListExpandedRecord(xml_reader.GetAttribute("name"));
            return true;
       }

My head is really confused. The code, as it is now, as far as I can see will simply load a single node and then break out of the loop. I'm having trouble finding where I should be recursively calling the load function to load nested nodes. I am attempting to get the single function to load a whole subtree, and I'm attempting to do it properly with all error messages and not adding an object if it wasn't filled with data, etc. I have, so far, failed.

Share this post


Link to post
Share on other sites
Advertisement
well, gee, I don't know, should I just keep bumping until I come to a solution?

Meh, why not? At the very least it will give me a tally of how many days it took me to straight out the code in my head.

[grin]

Share this post


Link to post
Share on other sites
I have not been able to work on this any due to my uni classes, but exams are over in 2 days, so I'll be back here.


Back to the problem: I haven't made any progress. I think my main problem is that the C# XMLTextReader class reads the nodes linearly, not heirarchically. In C++, I use tinyXML at the moment for some small things, and I really like how that works.

I just can't get my head around how to load a heirarchial data structure with an XML reader that reads linearly.

Share this post


Link to post
Share on other sites
To be true, I would suggest another aproach and would make use of the XMLSerializer provided. Google for it, c# and xmlserializer and you will find many good examples.

Share this post


Link to post
Share on other sites
I had not seen this thread before, sorry. I would have posted earlier!

I think you'll find the XmlDocument class much easier to work with; it loads an XML document and it breaks it into a tree of XmlNodes, each of which containing a series of ChildNodes.

As an aside, if you are using .NET 2.0 or higher you might like the List<> generic class (rather than the ArrayList). Your naming convention (lowercase characters on public methods, m_ prefix on member variables) is not consistent with the .NET guidelines, but I do realise that naming conventions are deeply personal things so it's only a heads-up if you ever wish to share your code with others.

EDIT: Furthermore, C# supports properties. That is, you don't need to create a setX and getX method, you can use the built-in mechanism;

private int someVariable;

public int SomeVariable {
get { return this.someVariable; }
set { this.someVariable = value; }
}


I'm not trying to be harsh on your code, just trying to point out some of the groovy features of C#/.NET you might not be aware of.

Share this post


Link to post
Share on other sites
Quote:
Original post by benryves
I'm not trying to be harsh on your code, just trying to point out some of the groovy features of C#/.NET you might not be aware of.


Be as harsh as you want, this is my project to learn C#.

Whatever you want, say it, it can only improve my knowledge. [grin]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!