Skip to main content
gamedev.net
🔒 Locked

C# XML Reader not working...

Started by Toolmaker 6 replies 2.8k views
Original Post
Toolmaker
Toolmaker
I have a very odd problem in which my XMLReader shows all Element names but they contain no data. I wrote them with the XMLTextWriter and reading is done with the XMLTextReader.

This is the XML file I try to read:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE GotoBed.NET>
<!--GotoBed.NET configuration file! Do not change the contents manually!-->
<Gotobed>
  <AlertEnabled>True</AlertEnabled>
  <AutoShutdown>False</AutoShutdown>
  <AutoStart>False</AutoStart>
  <AlertTime>23:41</AlertTime>
  <AlertMessage>It's time for bed!</AlertMessage>
  <AlertSound />
</Gotobed>
And this is my XMLTextReader function:

        #region XML Reader
        public void ReadSettings(string fileName)
        {
            XmlTextReader reader = new XmlTextReader(fileName);

            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.DocumentType:
                        if (reader.Name != docType)
                            throw (new Exception("The file " + fileName + "is not a valid GotoBed.NET config file"));
                        break;

                    case XmlNodeType.Element:
                        do
                        {
                            switch (reader.Name)
                            {
                                case "AlertEnabled":
                                    this.Enabled = Convert.ToBoolean((reader.Value == "True" ? 1 : 0));
                                    break;

                                case "AutoShutdown":
                                    this.AutoShutdown = Convert.ToBoolean((reader.Value == "True" ? 1 : 0));
                                    break;

                                case "AutoStart":
                                    this.AutoStart = Convert.ToBoolean((reader.Value == "True" ? 1 : 0));
                                    break;

                                case "AlertTime":
                                    this.AlertTime = reader.Value;
                                    break;

                                case "AlertMessage":
                                    this.AlertMessage = reader.Value;
                                    break;

                                case "AlertSound":
                                    this.AlertSound = reader.Value;
                                    break;
                            }
                        }while (reader.MoveToNextAttribute());
                        break;
                }
            }
        }

        #endregion
All reader.Value fields are empty. Toolmaker
 
Stephen R
Stephen R
The tag element is seperate from the text element.
The next element after the tag will contain the text.

From MSDN:

Quote:

The value returned depends on the NodeType of the node. The following table lists node types that have a value to return. All other node types return String.Empty.

Node Type Value
Attribute The value of the attribute.
CDATA The content of the CDATA section.
Comment The content of the comment.
DocumentType The internal subset.
ProcessingInstruction The entire content, excluding the target.
SignificantWhitespace The white space within an xml:space= 'preserve' scope.
Text The content of the text node.
Whitespace The white space between markup.
XmlDeclaration The content of the declaration.


So the next node should contain you value.
Arild Fines
Arild Fines
I'm no expert on the XmlReader APIs, but I believe Element nodes don't contain the text directly. Instead they contain a Text node, which you have to use in order to get to the actual text. See this and this for some examples.

Any particular reason you're not using an XmlDocument instead?
--AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.[Project site] [IRC channel] [Blog]
Toolmaker
Toolmaker
From what I've read, XmlTextReader is pretty lightweight and it's not much data which I need to read.

Toolmaker
 
Mulligan
Mulligan
When parsing a document, the XmlReader reads a element, then on the next read() it reads the value. Thus you have to save the text of the XmlNodeType.Element so that when it reaches the case statement XmlNodeType.Value, you can look back at what the last element was. So for ive found it failsafe.

for instance, this is one method i use to read a simple file:

private bool ReadGroupFile( string strFile )        {            XmlTextReader reader = new XmlTextReader( strFile );            string strElement = null;            while( reader.Read() )            {                switch( reader.NodeType )                {                    case XmlNodeType.Element:                        if( reader.Name == "allcharacters" )                        {                            characters.Open( strFile, reader );                            continue;                        }                                                strElement = reader.Name;                        break;                    case XmlNodeType.Text:                        if( strElement == "version" )                        {                            if( reader.Value != "1.0" )                            {                                MessageBox.Show( "Incorrect Version" );                                return false;                            }                        }                        break;                }            }            reader.Close();            return true;        }


you can get the general idea of what im trying to say by looking at the strElement variable.
Toolmaker
Toolmaker
I will have to try this tonight. I went to bed last night and I got driving lessons in a few minutes. When I get back from work, I will try and see if the code works.

Toolmaker
 
markr
markr
Technically, in order to get the contents of an element's text, you need to

- Traverse all its children
- For each child which is a text node, concatenate its text
- Ignore all others

This is a pain, I normally write a util method to do it.

Having said that, it looks to me like what you're trying to do can be done in C# using XML serialisation / deserialisation. Just write a config class containing the relevant members, tie the Xml Attributes to them as you see fit (or not if you just want the defaults), and then use a small piece of code to serialise / deserialise it.

It really is the way to go, using serialisation. The code is about 6 lines or so, to read it from a file, but more importantly, IT NEVER GETS ANY BIGGER. That's to say, as you make your config more complex, the code to load / save it never needs to change.

Mark
Toolmaker
Toolmaker
Markr, do you have an example of the serialization/deserilization?

And I managed to fix my code. I had to use reader.ReadString() instead of reader.Value; The only problem is not, it skips the first field(AlertEnabled) in the XML file, any ideas? This is the revised function:

        #region XML Writer		public void SaveSettings(string fileName)		{			XmlTextWriter outputFile = new XmlTextWriter(fileName, null);			// Use indentation for readability			outputFile.Formatting = Formatting.Indented;			// Start XML document			outputFile.WriteStartDocument(true);			outputFile.WriteDocType(docType, null, null, null);			outputFile.WriteComment(docComment);			outputFile.WriteStartElement("Gotobed");				outputFile.WriteElementString("AlertEnabled", null, this.Enabled.ToString());				outputFile.WriteElementString("AutoShutdown", null, this.AutoShutdown.ToString());				outputFile.WriteElementString("AutoStart", null, this.AutoStart.ToString());				outputFile.WriteElementString("AlertTime", null, this.AlertTime.ToString());				outputFile.WriteElementString("AlertMessage", null, this.AlertMessage);				outputFile.WriteElementString("AlertSound", null, this.AlertSound);			outputFile.WriteEndElement();			// Write the file and close it			outputFile.Flush();			outputFile.Close();		}        #endregion


EDIT: I think I found an article on serialization. I am changing my code over now and see if that works. The link is http://www.devhood.com/Tutorials/tutorial_details.aspx?tutorial_id=236

Toolmaker

[Edited by - Toolmaker on June 28, 2004 2:39:50 PM]
 

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.