Search code examples
c#xmldeserializationxmlreader

c# XmlReader: reading attributes from start element


I am trying to save the state of a game in an xml file, so that it can be restored when the player loads the game. I am brand new to xml, but I did manage to succesfully store the state of the game in an xml file using the XmlWriter. The problem comes when I try to read this file. Here is the begin of the file as it is created by my program:

<?xml version="1.0" encoding="utf-16"?>
<level width="25" height="25">
  <count>0</count>
  <row>
    <tile type="ROOM" />
    <tile type="ROOM" />
    <tile type="ROOM" />
    <tile type="ROOM" />
    <tile type="ROOM" />
    <!-- More tiles and rows are defined, but the file is somewhat large to entirely copy-paste here-->

The elements are closed at the end of the file as it should. Now I try to read the data from this file using an XmlReader object:

public void LoadFromFile()
    {
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.IgnoreWhitespace = true;
        settings.IgnoreComments = true;

        using(XmlReader reader = XmlReader.Create(new StreamReader("Content/Saves/SaveFile.xml", Encoding.UTF8), settings))
        {
            reader.MoveToContent();
            reader.ReadStartElement("level");
            reader.MoveToAttribute("width");
            int w = int.Parse(reader.Value);
            reader.MoveToNextAttribute();
            int h = int.Parse(reader.Value);
            // More to be read when I understand this first part.
        }
    }

The exception I keep getting is that width attribute either has the value null or has the wrong format.

1: I didn't use the reader.MoveToContent() method before, and I discovered that the reader did not read to "level" when I executed reader.ReadStartElement(). The reader had no value. 2: After adding the reader.MoveToContent() method, it did find the level element. However, when I used reader.GetAttribute("width"), I did not get the width attribute, but a whitespace. Therefore, 3: I added settings.IgnoreWhitespace = true. I don't get a whitespace anymore, but something even stranger. I did not read the "width" attribute, but the "count" element.

These are the values that the reader had for each point in previous paragraph(Read from visual studio debug window):

1: {None}

2: {Whitespace, Value="\n "}

3: {Element, Value="count"}

I expected that point 3 would give me something like: {Attribute, Value="width"} or something similar.

Why does the reader not read the attribute, but the next element? Can someone give me an easy step-by-step example of how one should read Attributes and content from an xml file?

I try to keep things as simple as possible, since I have too little time to learn all concepts for xml. I got very confused when reading about Nodes and NodeReaders, so if possible, I would like to avoid them. Just Attributes, Elements and Content.


Solution

  • After you execute reader.ReadStartElement("level")your reader moves to the next element after "level", to the "count", that doesn't have expected attributes. (look here for the docu: https://msdn.microsoft.com/library/y7e4769a(v=vs.110).aspx) If you want to do serialization this way, just remvoe this line:

    using(XmlReader reader = XmlReader.Create(new StreamReader("Content/Saves/SaveFile.xml", Encoding.UTF8), settings))
    {
        reader.MoveToContent();
        reader.MoveToAttribute("width");
        int w = int.Parse(reader.Value);
        reader.MoveToNextAttribute();
        int h = int.Parse(reader.Value);
    }