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