[英]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. 我遇到的情况是,有多个xml文件都共享相同的根元素“ GroceryBag”,但这些文件中的子元素可能是任何类型或数量。 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. 我的具体问题是如何用来自所有xml文件的组合数据填充“ AllBagsEver” ...更好。 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.
最终的游戏是使用“ GroceryBag”上的每个对象列表作为DataGridView的数据源。
Also, the xml files Im working with belong to another program so changing the xml structure is not an option. 另外,Im使用的xml文件属于另一个程序,因此不能更改xml结构。 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文件的示例。
<?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. 以下是使用Linq To XML和列表集合的解决方案。
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.
您只需要运行一个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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.