使用相同的根反序列化多个xml文件,但使用c#将子元素变为一个

时间:2014-06-19 02:26:27

标签: c# xml datagridview

我的情况是,有多个xml文件都共享相同的根元素'GroceryBag',但这些文件中的子元素可以是任何类型或数量。我已经知道所有可能的子元素类型。

我的具体问题是如何使用来自所有xml文件的组合数据填充“AllBagsEver”...更好。下面的代码不是我的实际项目代码,但我写了它来说明我的观点。这里的最终游戏是使用'GroceryBag'上的每个对象列表作为DataGridView的DataSource。

此外,我正在使用的xml文件属于另一个程序,因此更改xml结构不是一个选项。另一方面,我的实施是可怕的,所以继续改变,欢呼。

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;
        }
    }
}

以下是要合并的各个xml文件的一些示例。

<?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>

1 个答案:

答案 0 :(得分:0)

以下是使用Linq To XML和List Collection的解决方案。

现在您拥有List中的所有元素。你只需要运行一个foreach循环并将其添加到一个单独的xml对象中。

  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;