[英]How to deserialize Xml with root than multiple child elements of the same type
[英]Deserialize multiple xml files with the same root but varying child elements into one with c#
我遇到的情況是,有多個xml文件都共享相同的根元素“ GroceryBag”,但這些文件中的子元素可能是任何類型或數量。 我已經知道所有可能的子元素類型。
我的具體問題是如何用來自所有xml文件的組合數據填充“ AllBagsEver” ...更好。 下面的代碼不是我的實際項目代碼,但是我已經寫了它來說明我的觀點。 最終的游戲是使用“ GroceryBag”上的每個對象列表作為DataGridView的數據源。
另外,Im使用的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和列表集合的解決方案。
現在,您將所有元素都包含在列表中。 您只需要運行一個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.