2

I have xml files that I need to load and create class objects from, however, these files are formatted in, what seems to me to be a ridiculously nested way. Sadly I can't have the xml files reformatted. Here's what they look like (assume there is only one purchase entry for every customer and the name can serve as a key):

<root>
<start>
   <customer>
      <store store = "a">
          <customer name = "Ted Johnson">
             <product product = "shampoo">
                <price price = "10">
                </ price>
             </ product>
          </customer>
       </store>
       <store store = "b">
           <customer name = "Janet Henry">
             <product product = "soda">
                <price price = "2">
                </ price>
             </ product>
          </ customer>
       </ store>
   </ customer>

   <tax>
      <store store = "a">
          <customer name = "Ted Johnson">
             <product product = "shampoo">
                <tax tax = "1">
                  <date date = "4/4/2014">
                  </date>
                </tax>
             </ product>
          </customer>
       </store>         
      <store store = "b">
          <customer name = "Janet Henry">
             <product product = "soda">
                <tax tax = "0.2">
                  <date date = "5/5/2014">
                  </date>
                </tax>
             </ product>
          </customer>
       </store>
   </tax>
</ start>
</ root>

Now I need to create class objects in c#/WPF, based on this kind of monstrosity. I've been trying a few things but keep running into hurdles, and I'm worried I might end up spending a long time forcing an inefficient solution. Is there an easy way to approach this?

My goal is to create something like the following:

var customerPurchases = (from e in xml.Descendants(ns + "start")                         
   select new customerPurchase
   {
     name = e.Attribute("name").Value,
     store = e.Attribute("store").Value,
     product = e.Attribute("product").Value,
     price = e.Attribute("price").Value,
     tax = e.Attribute("tax").Value,
     date = e.Attribute("date").Value,  

}).ToList();

Any help or insight on this mess would be greatly appreciated!

fyodorfranz
  • 476
  • 8
  • 25
  • Here's an idea, pass it through a transformer to get it into a sane format. That is just ridiculous, and any code that will attempt to process it directly will be just as ridiculous. – Jeff Mercado Jun 06 '15 at 19:44

3 Answers3

2

You can deserialize your XML string (or file) to C# objects. Find a sample here: https://blog.udemy.com/csharp-serialize-to-xml/

First, you must have classes associated to XML. To create classes, select your XML sample data and, in Visual Studio, go to Edit / Paste Special / Paste XML As Classes.

Next, use this sample.

        String xData = System.IO.File.ReadAllText(@"C:\Temp\MyFile.xml");
        XmlSerializer x = new XmlSerializer(typeof(root));
        root dataConverted = (root)x.Deserialize(new StringReader(xData));
        // root object contains all XML data.
Michael Kohne
  • 11,888
  • 3
  • 47
  • 79
Denis Voituron
  • 288
  • 1
  • 8
  • Unfortunately, it would be very difficult (if not impossible) to find an XML deserialiser that would convert this highly custom XML into the target class. – Contango Jun 06 '15 at 19:36
  • 1
    See my sample in my answer updated... First, you must have classes associated to XML. To create classes, select your XML sample data and, in Visual Studio, go to Edit / Paste Special / Paste XML As Classes (http://bit.ly/1cE0xlm). Cool, no? I've just made this sample (I can send you a copy if you want). – Denis Voituron Jun 06 '15 at 19:53
  • 1
    You should look at the data again. It's in a format that you cannot reasonably expect any serializer to handle without _a lot_ of custom code to deal with it. – Jeff Mercado Jun 06 '15 at 19:54
  • @Denis Voituron I stand corrected, this is an absolutely brilliant way to convert XML into C# classes. – Contango Jun 06 '15 at 20:07
  • @Denis Voituron Thanks a lot! This looks great. I'll give it a try. – fyodorfranz Jun 07 '15 at 01:44
0

If you're not worried too much about speed, I would use LINQ to XML.

See LINQ to XML Overview.

Contango
  • 76,540
  • 58
  • 260
  • 305
0

I would try converting the XML to a dynamic C# object. Then, the code to read the data out of the dynamic into your strongly typed POCO classes would be far more concise and a lot easier to write.

See Converting XML to a dynamic C# object.

Hint: If you wrap your entire parser in a try/catch, then any mismatch between the schema of the XML input, and the parsing code that uses dynamics, would be detected without bringing down the entire app.

Community
  • 1
  • 1
Contango
  • 76,540
  • 58
  • 260
  • 305