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

本文关键字:文件 xml 反序列化 一个 元素 同根 使用 | 更新日期: 2023-09-27 18:09:20

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

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

另外,我使用的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>

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

下面是使用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;