1

I want to read XML like this.

<?xml version="1.0" encoding="utf-8" ?>
<parent>
  <path>
    <pathPoints>
     <point>
        2 0
      </point>
      <point>
        2 1
      </point>
        3 1
      <point>
        3 2
      </point>
      <point>
        4 2
      </point>
      <point>
        4 4
      </point>
      <point>
        3 4
      </point>
      <point>
        3 5
      </point>
      <point>
      2 5
      </point>
      <point>
        2 7
      </point>
      <point>
          7 7
      </point>
      <point>
          7 5
      </point>
      <point>
        10 5
      </point>
      <point>
        10 2
      <point>
      </point>
      15 2
      </point>
      <point>
        15 6
      </point>
      <point>
        16 6
      </point>
      <point>
        16 7
      </point>
      <point>
        17 7
      </point>
      <point>
        17 10
      </point>
      <point>
        19 10
      </point>
    </pathPoints>
  </parent>
</path>

And now I'm trying to read it:

        paths = (from path in doc.Descendants("path")
                 select new AIPath()
                 {
                     waypoints = (from i in path.Descendants("pathPoints")
                     {
                         int j = Convert.ToInt32(i.Element("point").Value),
                     }).ToList();
                 }
                 ).ToList();

My AIPath contains a list of vector2 called waypoints.

What I want to know is what I'm doing wrong. I want to create a new path everytime it changes which path it's looking at, which looks fine. What I'm confused about though is waht to do next. After the waypoints = (from i in path.Descendants("pathPoints"), I'm expecting i have to do something but I'm clueless as to what.

Any help would be greatly appreciated.

Edit

One or two details I forgot to add.

public class AIPath
{
    //public Vector2
    public List<Vector2> waypoints { get; set; }
    public int linkNumber { get; set; }
    public int[] potentialLinks { get; set; }
}
6
  • We don't know what your AIPath type looks like, which makes it hard to help. Also, you haven't told us what your current code does. (It looks like it's basically a syntax error...) Commented Sep 3, 2012 at 20:10
  • Also, you currently seem to be attempting to parse a point element as a single integer, when it clearly contains two integers. Are you able to change the XML format? It looks like it would be much cleaner if the two values were set as attributes of the point elements... Commented Sep 3, 2012 at 20:12
  • @JonSkeet yes i can change the format and I do need to get X and Y. It was more to illustrate what I've done before. I've added my AI path class. It basically doesn't work at the moment because I can't work out what I need to add to tell the xml parser to add all pathpoints elements it finds to the the AIPath waypoints table. Commented Sep 3, 2012 at 20:24
  • Okay, I'll write an answer including a different way of serializing and deserializing :) Commented Sep 3, 2012 at 20:29
  • I should add, this is for Windows phone which if i remember correctly doesn't allow use of XmlDocument. just in case you were thinking of that. Commented Sep 3, 2012 at 20:32

2 Answers 2

1

Currently, your XML output is relatively hard to parse. I would rewrite your code like this:

public sealed class AIPath
{
    // TODO: Consider trying to make this immutable, or
    // at least not exposing the collections so widely. Exposing an array
    // property is almost always a bad idea.
    public List<Vector2> Waypoints { get; set; }
    public int LinkNumber { get; set; }
    public int[] PotentialLinks { get; set; }

    public XElement ToElement()
    {
        return new XElement("path",
            WayPoints.Select(v2 => new XElement("point",
                                       new XAttribute("X", (int) v2.X),
                                       new XAttribute("Y", (int) v2.Y))));
    }

    public static AIPath FromXElement(XElement path)
    {
        return new AIPath
        {
            WayPoints = path.Elements("point")
                            .Select(p => new Vector2((int) p.Attribute("X"),
                                                     (int) p.Attribute("Y")))
                            .ToList();
        };
    }
}

Then:

paths = doc.Descendants("path")
           .Select(x => AIPath.FromXElement(x))
           .ToList();
Sign up to request clarification or add additional context in comments.

Comments

1

Jon Skeet's answer will probably work, but the XNA framework offers a much easier way of reading XML into your objects through the Content Pipeline.

Example XML:

<?xml version="1.0" encoding="utf-8"?>
<XnaContent>
  <Asset Type="MyDataTypes.CatData[]">
    <Item>
      <Name>Rhys</Name>
      <Weight>17</Weight>
      <Lives>9</Lives>
    </Item>
    <Item>
      <Name>Boo</Name>
      <Weight>11</Weight>
      <Lives>5</Lives>
    </Item>
  </Asset>
</XnaContent>

Example Class:

namespace MyDataTypes
{
    public class CatData
    {
        public string Name;
        public float Weight;
        public int Lives;
    }
}

The built in XML Importer and Processor of the Content Pipeline will associate the XML elements with the correctly named class members when building the .xnb files assuming that you've marked the Asset Type element correctly.

See: http://msdn.microsoft.com/en-us/library/ff604981.aspx

1 Comment

Using [XmlAttribute] and [XmlElement] is also helpful if you want more control over serialization of your XML files by element/attribute names.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.