tags:

views:

3879

answers:

4

I'm new to .net and c#, so I want to make sure i'm using the right tool for the job.

The XML i'm receiving is a description of a directory tree on another machine, so it go many levels deep. What I need to do now is to take the XML and create a structure of objects (custom classes) and populate them with info from the XML input, like File, Folder, Tags, Property...

The Tree stucture of this XML input makes it, in my mind, a prime candidate for using recursion to walk the tree.

Is there a different way of doing this in .net 3.5?

I've looked at XmlReaders, but they seem to be walking the tree in a linear fashion, not really what i'm looking for...

The XML i'm receiving is part of a 3rd party api, so is outside my control, and may change in the futures.

I've looked into Deserialization, but it's shortcomings (black box implementation, need to declare members a public, slow, only works for simple objects...) takes it out of the list as well.

Thanks for your input on this.

A: 

Load your XML into an XMLDocument. You can then walk the XMLDocuments DOM using recursion.

You might want to also look into the factory method pattern to create your classes, would be very useful here.

FlySwat
A: 

XmlReader isn't a particularly friendly API. If you can use .NET 3.5, then loading into LINQ to XML is likely to be your best bet. You could easily use recursion with that.

Otherwise, XmlDocument would still do the trick... just a bit less pleasantly.

Jon Skeet
+12  A: 

I would use the XLINQ classes in System.Xml.Linq (this is the namespace and the assembly you will need to reference). Load the XML into and XDocument:

XDocument doc = XDocument.Parse(someString);

Next you can either use recursion or a pseudo-recursion loop to iterate over the child nodes. You can choose you child nodes like:

//if Directory is tag name of Directory XML
//Note: Root is just the root XElement of the document
var directoryElements = doc.Root.Elements("Directory"); 

//you get the idea
var fileElements = doc.Root.Elements("File");

The variables directoryElements and fileElements will be IEnumerable types, which means you can use something like a foreach to loop through all of the elements. One way to build up you elements would be something like this:

List<MyFileType> files = new List<MyFileType>();

foreach(XElelement fileElement in fileElements)
{
  files.Add(new MyFileType()
    {     
      Prop1 = fileElement.Element("Prop1"), //assumes properties are elements
      Prop2 = fileElement.Element("Prop2"),
    });
}

In the example, MyFileType is a type you created to represent files. This is a bit of a brute-force attack, but it will get the job done.

If you want to use XPath you will need to using System.Xml.XPath.


A Note on System.Xml vs System.Xml.Linq

There are a number of XML classes that have been in .Net since the 1.0 days. These live (mostly) in System.Xml. In .Net 3.5, a wonderful, new set of XML classes were released under System.Xml.Linq. I cannot over-emphasize how much nicer they are to work with than the old classes in System.Xml. I would highly recommend them to any .Net programmer and especially someone just getting into .Net/C#.

Jason Jackson
+1 for stressing the difference between System.Xml and System.Xml.Linq.
James Skemp
+1  A: 

This is a problem which is very suitable for recursion.

To elaborate a bit more on what another poster said, you'll want to start by loading the XML into a System.Xml.XmlDocument, (using LoadXml or Load).

You can access the root of the tree using the XmlDocument.DocumentElement property, and access the children of each node by using the ChildNodes property. Child nodes returns a collection, and when the Collection is of size 0, you know you'll have reached your base case.

Using LINQ is also a good option, but I'm unable to elaborate on this solution, cause I'm not really a LINQ expert.

As Jon mentioned, XmlReader isn't very friendly. If you end up having perf issues, you might want to look into it, but if you just want to get the job done, go with XmlDocument/ChildNodes using recursion.

brad