我每天早上都会收到大量以单独的 XML 文件形式接收的数据。我需要组合 XML 中的对象并从中生成报告。我正在寻找解决此问题的最佳解决方案。
为了证明我已经编造了以下示例:
有 2 个 XML 文件:
第一个是语言列表和使用它们的国家/地区。第二个是产品列表及其销售国家/地区。我生成的报告是产品名称,后跟包装必须使用的语言。
XML1:
<?xml version="1.0" encoding="utf-8"?>
<languages>
<language>
<name>English</name>
<country>8</country>
<country>9</country>
<country>3</country>
<country>11</country>
<country>12</country>
</language>
<language>
<name>French</name>
<country>3</country>
<country>6</country>
<country>7</country>
<country>13</country>
</language>
<language>
<name>Spanish</name>
<country>1</country>
<country>2</country>
<country>3</country>
</language>
</languages>
XML2:
<?xml version="1.0" encoding="utf-8"?>
<products>
<product>
<name>Screws</name>
<country>3</country>
<country>12</country>
<country>29</country>
</product>
<product>
<name>Hammers</name>
<country>1</country>
<country>13</country>
</product>
<product>
<name>Ladders</name>
<country>12</country>
<country>39</country>
<country>56</country>
</product>
<product>
<name>Wrenches</name>
<country>8</country>
<country>13</country>
<country>456</country>
</product>
<product>
<name>Levels</name>
<country>19</country>
<country>18</country>
<country>17</country>
</product>
</products>
示例程序输出:
Screws -> English, French, Spanish
Wrenches -> English, French
Hammer - > French, Spanish
Ladders-> English
目前我反序列化为一个数据集,然后使用 linq 跨数据集连接以生成所需的报告字符串。(如下所示 - 将文件的名称作为命令行参数传递)。
public static List<String> XMLCombine(String[] args)
{
var output = new List<String>();
var dataSets = new List<DataSet>();
//Load each of the Documents specified in the args
foreach (var s in args)
{
var path = Environment.CurrentDirectory + "\\" + s;
var tempDS = new DataSet();
try
{
tempDS.ReadXml(path);
}
catch (Exception ex)
{
//Custom Logging + Error Reporting
return null;
}
dataSets.Add(tempDS);
}
//determine order of files submitted
var productIndex = dataSets[0].DataSetName == "products" ? 0:1;
var languageIndex = dataSets[0].DataSetName == "products" ? 1:0;
var joined = from tProducts in dataSets[productIndex].Tables["product"].AsEnumerable()
join tProductCountries in dataSets[productIndex].Tables["country"].AsEnumerable() on (int)tProducts["product_id"] equals (int)tProductCountries["product_id"]
join tLanguageCountries in dataSets[languageIndex].Tables["country"].AsEnumerable() on (String)tProductCountries["country_text"] equals (String)tLanguageCountries["country_text"]
join tLanguages in dataSets[languageIndex].Tables["language"].AsEnumerable() on (int)tLanguageCountries["language_Id"] equals (int)tLanguages["language_Id"]
select new
{
Language = tLanguages["name"].ToString(),
Product = tProducts["name"].ToString()
};
var listOfProducts = joined.OrderByDescending(_ => _.Product).Select(_ => _.Product).Distinct().ToList();
foreach (var e in listOfProducts)
{
var e1 = e;
var languages = joined.Where(_ => _.Product == e1).Select(_ => _.Language).Distinct().ToList();
languages.Sort();
//Custom simple Array to text method
output.Add(String.Format("{0} {1}", e, ArrayToText(languages)));
}
return output;
}
这很好用,但我知道必须有更优化的解决方案来解决这个问题(特别是当 XML 文件在现实生活中很大时)。有没有人有替代方法(除了 linq)的经验或关于优化当前方法的建议,这将使我更接近最佳解决方案?
提前谢谢了。
解决方案 建议解决方案的实施:Casperah 使用字典的方法在 312 毫秒内处理数据集。yamen 的方法使用 Linq Lookup 在 452ms 内处理数据集。