tags:

views:

210

answers:

5
+1  Q: 

Parsing XML in C#

I am looking for a way to read the following XML

<Data>
  <MaxCount>10</MaxCount>
  <Points>
    <Point X="10" Y="10"/>
    <Point X="20" Y="10"/>
    <Point X="30" Y="10"/>
    <Point X="40" Y="10"/>
    <Point X="50" Y="10"/>
    <Point X="60" Y="10"/>
  </Points>
</Data>

Basically I want to read all the point values into an array of Point objects (My point object has 2 properties X and Y) and the MaxCount into an integer. What is the best way to pull out the Point values from the XML file using C#?

Thanks

+4  A: 

Well, you could easily read the file using the XMLDocument class.

http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx

Basically you'd just have the class read in the file and then then cycle through the XMLNodes that it creates. You would read in the MaxCount using the innerText property of the node, and when you reach cycle through its children and grab the data you need via the attribute property of the XMLNode.

Streklin
I'd prefer using LINQ-to-XML classes (XDocument) instead...
Arjan Einbu
+4  A: 
    class Point
    {
        public int X { get; set; }
        public int Y { get; set; }
    }

    static int Main(string[] args)
    {
        string xml = "<Data>  <MaxCount>10</MaxCount>  <Points>    <Point X=\"10\" Y=\"10\"/>    <Point X=\"20\" Y=\"10\"/>    <Point X=\"30\" Y=\"10\"/>    <Point X=\"40\" Y=\"10\"/>    <Point X=\"50\" Y=\"10\"/>    <Point X=\"60\" Y=\"10\"/>  </Points></Data>";

        XDocument doc = XDocument.Parse(xml);

        int maxCount = int.Parse(doc.Element("Data").Element("MaxCount").Value);

        var points = from e in doc.Element("Data").Element("Points").Elements("Point")
                     select new Point
                     {
                         X = int.Parse(e.Attribute("X").Value),
                         Y = int.Parse(e.Attribute("Y").Value)
                     };

        Console.WriteLine("MaxCount: {0}", maxCount);
        foreach (var item in points)
        {
            Console.WriteLine("Point: {0},{1}", item.X, item.Y);
        }
    }
bruno conde
+1, linq to xml is a great tool for this
chester89
+1  A: 

It can be done using XPath:

public void CreatePoints(string xml)
{
    XPathDocument doc = new XPathDocument(XmlReader.Create(new StringReader(xml)));
    var xPathNodeIterator = doc.CreateNavigator().Select("/Data/Points/Point");
    foreach (XPathNavigator node in xPathNodeIterator)
    {
        var x = node.SelectSingleNode("@X").ValueAsInt;
        var y = node.SelectSingleNode("@Y").ValueAsInt;

        new Point(x, y);
    }
}
Elisha
You can read XML in 1 go with doc.LoadXml(xml). On the doc variabele you can call doc.DocumentElement.SelectNodes("Data/Points/*") and iterate through each XmlNode.
Patrick Peters
@Patrick: XMLDocument is a very heavy weight object as compare to XPathDocument. Though it is bit cumbersome to use XPathDocument, its performance is far better than XMLDocumnet.
rauts
+8  A: 

I suggest you take a look at the XmlSerializer class. It lets you serialize and deserialize XML directly to objects.

First, the classes to represent your data:

[XmlRoot(Namespace = "")]
public class Data
{
    public int MaxCount;
    public Point[] Points;
}

public class Point
{
    [XmlAttribute]
    public int X;
    [XmlAttribute]
    public int Y;
}

Then you use the XmlSerializer:

Stream s = ... // Some code to open you file into a stream

var serializer = new XmlSerializer(typeof(Data));
Data d = (Data)serializer.Deserialize(s);

Article: http://msdn.microsoft.com/en-us/library/ms950721.aspx

Arjan Einbu
For a bonus, you can use xsd.exe to automagically create this class for you http://msdn.microsoft.com/en-us/library/x6c1kb0s%28VS.71%29.aspx
Lee
@Lee: Great tip. I had forgotten about that. (Haven't had the use for it for a while...)
Arjan Einbu
A: 

Create a Class Data with MaxCount integer property and one property Points of type List (Point is another class with X and Y properties). Mark these classes as Serializable.

Load the Xml in the XMLReader.

Deserialize the Xml Using the Xmlreader into the Data class.

Sorry for not providing a working example.

rauts
Overkill here I think. Use XPath for this simple scenario.
Patrick Peters
@Patrick: Not overkill ;-) There already is a point class he wants to populate. For readability/complexity and amount of code, see my answer above...
Arjan Einbu