简体   繁体   中英

Deserialize multiple xml files with the same root but varying child elements into one with c#

I have a situation where there are multiple xml files that all share the same root element 'GroceryBag' but the child elements in these files may be of any type or quantity. All the possible child element types are already known by me.

My specific question is how can I populate my 'AllBagsEver' with the combined data from all the xml files... better. The code below is not my actual project code but I have written it to illustrate my point. The end game here is using each object list on 'GroceryBag' as a DataSource for DataGridView.

Also, the xml files Im working with belong to another program so changing the xml structure is not an option. On the other hand my implementation is terrible so heres to changing that, cheers.

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;


namespace StackOverflow
{
    class Program
    {
        public static GroceryBag AllBagsEver = new GroceryBag();
        public static Random rng = new Random();

        static void Main(string[] args)
        {
            GoShopping();
            PopulateBigBag();
            string bagCount = 
                "Apples: " + AllBagsEver.Apples.Count + 
                "\nBreads: " + AllBagsEver.Breads.Count +
                "\nCheeses: " + AllBagsEver.Breads.Count +
                "\nMilks: " + AllBagsEver.Breads.Count +
                "\nChickens: " + AllBagsEver.Breads.Count;
            AllBagsEver.Serialize(Environment.CurrentDirectory, "MergedAll.xml");
            Console.WriteLine(bagCount);
            Console.ReadKey();
        }


        static void PopulateBigBag()
        {
            foreach (string file in Directory.EnumerateFiles(Environment.CurrentDirectory, "*.xml"))
            {
                GroceryBag tmp = GroceryBag.Deserialize(file);
                AllBagsEver.Apples.AddRange(tmp.Apples);
                AllBagsEver.Breads.AddRange(tmp.Breads);
                AllBagsEver.Cheeses.AddRange(tmp.Cheeses);
                AllBagsEver.Milks.AddRange(tmp.Milks);
                AllBagsEver.Chickens.AddRange(tmp.Chickens);
            }
        }


        static void GoShopping() //simulate variable data
        {
            GroceryBag tmpBag = new GroceryBag();
            if (rng.NextDouble() > 0.5)
            {
                Apple HoneyCrispApple = new Apple();
                HoneyCrispApple.Name = "HoneyCrisp";
                HoneyCrispApple.Price = 7;
                HoneyCrispApple.Weight = 1;
                tmpBag.Apples.Add(HoneyCrispApple);
            }
            if (rng.NextDouble() > 0.5)
            {
                Apple FujiApple = new Apple();
                FujiApple.Name = "Fuji";
                FujiApple.Price = 5;
                FujiApple.Weight = 1;
                tmpBag.Apples.Add(FujiApple);       
            }
            if (rng.NextDouble() > 0.5)
            {
                Bread BagelBread = new Bread();
                BagelBread.Name = "Bagel";
                BagelBread.Price = 3;
                BagelBread.Weight = 1;
                tmpBag.Breads.Add(BagelBread);
            }
            if (rng.NextDouble() > 0.5)
            {
                Bread CiabattaBread = new Bread();
                CiabattaBread.Name = "Ciabatta";
                CiabattaBread.Price = 10;
                CiabattaBread.Weight = 2;
                tmpBag.Breads.Add(CiabattaBread);
            }
            if (rng.NextDouble() > 0.5)
            {
                Cheese AbbotCheese = new Cheese();
                AbbotCheese.Name = "Abbot";
                AbbotCheese.Price = 4;
                AbbotCheese.Weight = 1;
                tmpBag.Cheeses.Add(AbbotCheese);
            }
            if (rng.NextDouble() > 0.5)
            {
                Cheese MaasdamCheese = new Cheese();
                MaasdamCheese.Name = "Maasdam";
                MaasdamCheese.Price = 4;
                MaasdamCheese.Weight = 1;
                tmpBag.Cheeses.Add(MaasdamCheese);
            }
            if (rng.NextDouble() > 0.5)
            {
                Milk VitaminDMilk = new Milk();
                VitaminDMilk.Name = "Vitamin D";
                VitaminDMilk.Price = 4;
                VitaminDMilk.Weight = 1;
                tmpBag.Milks.Add(VitaminDMilk);
            }

            string filename = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            tmpBag.Serialize(Environment.CurrentDirectory, filename);
        }
    }




    [Serializable, XmlRoot(ElementName = "GroceryBag")]
    public class GroceryBag //database 
    {
        [XmlElement("Apple")]
        public List<Apple> Apples { get; set; }

        [XmlElement("Bread")]
        public List<Bread> Breads { get; set; }

        [XmlElement("Cheese")]
        public List<Cheese> Cheeses { get; set; }

        [XmlElement("Milk")]
        public List<Milk> Milks { get; set; }

        [XmlElement("Chicken")]
        public List<Chicken> Chickens { get; set; }

        public GroceryBag()
        {
            Apples = new List<Apple>();
            Breads = new List<Bread>();
            Cheeses = new List<Cheese>();
            Milks = new List<Milk>();
            Chickens = new List<Chicken>();
        }

        public void Serialize(string path, string filename)
        {
            string writePath = path + "\\" + filename + ".xml";
            Console.WriteLine("Serializing to: " + writePath);
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            XmlSerializer xmlWriter = new XmlSerializer(typeof(GroceryBag));
            StreamWriter xmlStream = new StreamWriter(writePath);
            xmlWriter.Serialize(xmlStream, this);
            xmlStream.Close();
        }

        public static GroceryBag Deserialize(string filePath)
        {
            Console.WriteLine("Deserializing from " + filePath);
            TextReader txtReader = new StreamReader(filePath);
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(GroceryBag));
            GroceryBag bag = (GroceryBag)xmlSerializer.Deserialize(txtReader);
            txtReader.Close();
            return bag;
        }
    }


    [Serializable]
    [XmlType("Apple")]
    public class Apple
    {
        [XmlAttribute("Name")]
        public string Name { get; set; }

        [XmlElement("Price")]
        public int Price { get; set; }

        [XmlElement("Weight")]
        public int Weight { get; set; }

        public Apple()
        {
            Name = "GenericApple";
            Price = 0;
            Weight = 0;
        }
    }


    [Serializable]
    [XmlType("Bread")]
    public class Bread
    {
        [XmlAttribute("Name")]
        public string Name { get; set; }

        [XmlElement("Price")]
        public int Price { get; set; }

        [XmlElement("Weight")]
        public int Weight { get; set; }

        public Bread()
        {
            Name = "GenericBread";
            Price = 0;
            Weight = 0;
        }
    }


    [Serializable]
    [XmlType("Cheese")]
    public class Cheese
    {
        [XmlAttribute("Name")]
        public string Name { get; set; }

        [XmlElement("Price")]
        public int Price { get; set; }

        [XmlElement("Weight")]
        public int Weight { get; set; }


        public Cheese()
        {
            Name = "GenericCheese";
            Price = 0;
            Weight = 0;
        }
    }


    [Serializable]
    [XmlType("Milk")]
    public class Milk
    {
        [XmlAttribute("Name")]
        public string Name { get; set; }

        [XmlElement("Price")]
        public int Price { get; set; }

        [XmlElement("Weight")]
        public int Weight { get; set; }

        public Milk()
        {
            Name = "GenericMilk";
            Price = 0;
            Weight = 0;
        }
    }


    [Serializable]
    [XmlType("Chicken")]
    public class Chicken
    {
        [XmlAttribute("Name")]
        public string Name { get; set; }

        [XmlElement("Price")]
        public int Price { get; set; }

        [XmlElement("Weight")]
        public int Weight { get; set; }

        public Chicken()
        {
            Name = "GenericChicken";
            Price = 0;
            Weight = 0;
        }
    }
}

Here are some examples of what the individual xml files to merge look like.

<?xml version="1.0" encoding="utf-8"?>
<GroceryBag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Bread Name="Bagel">
    <Price>3</Price>
    <Weight>1</Weight>
  </Bread>
  <Cheese Name="Maasdam">
    <Price>4</Price>
    <Weight>1</Weight>
  </Cheese>
  <Milk Name="Vitamin D">
    <Price>4</Price>
    <Weight>1</Weight>
  </Milk>
</GroceryBag>



<?xml version="1.0" encoding="utf-8"?>
<GroceryBag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Apple Name="HoneyCrisp">
    <Price>7</Price>
    <Weight>1</Weight>
  </Apple>
  <Apple Name="Fuji">
    <Price>5</Price>
    <Weight>1</Weight>
  </Apple>
</GroceryBag>



<?xml version="1.0" encoding="utf-8"?>
<GroceryBag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Bread Name="Bagel">
    <Price>3</Price>
    <Weight>1</Weight>
  </Bread>
</GroceryBag>

Below is a solution using Linq To XML and List Collection.

Now you have all the elements in a List. you just need to run a foreach loop and add it to a separate xml object.

  XDocument xdoc = XDocument.Load(@"C:\Users\max\Desktop\xml_answer\ConsoleApplication1\ConsoleApplication1\XMLFile1.xml");
        var content1 = from root in xdoc.Descendants("GroceryBag")
                      select root.Elements();
        var list = content1.ToList();

        XDocument xdoc1 = XDocument.Load(@"C:\Users\max\Desktop\xml_answer\ConsoleApplication1\ConsoleApplication1\XMLFile2.xml");
        var content2 = from root in xdoc.Descendants("GroceryBag")
                       select root.Elements();
        var list2 = content2.ToList();

        XDocument xdoc3 = XDocument.Load(@"C:\Users\max\Desktop\xml_answer\ConsoleApplication1\ConsoleApplication1\XMLFile3.xml");
        var content3 = from root in xdoc.Descendants("GroceryBag")
                       select root.Elements();
        var list3 = content3.ToList();

        list.AddRange(list2);
        list.AddRange(list3);
        var tot = list;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM