我有一个XML提要(我无法控制),我试图弄清楚如何检测文档中某些属性值的数量。
我也在解析XML并将属性分离为Arrays(用于其他功能)
以下是我的XML
示例<items>
<item att1="ABC123" att2="uID" />
<item att1="ABC345" att2="uID" />
<item att1="ABC123" att2="uID" />
<item att1="ABC678" att2="uID" />
<item att1="ABC123" att2="uID" />
<item att1="XYZ123" att2="uID" />
<item att1="XYZ345" att2="uID" />
<item att1="XYZ678" att2="uID" />
</items>
我想根据每个att1值找到卷节点。 Att1值会改变。一旦我知道att1值的频率,我需要拉出该节点的att2值。
我需要找到TOP 4项并提取其属性的值。
所有这些都需要在C#代码后面完成。
如果我使用的是Javascript,我会创建一个关联数组,并将att1作为键,频率为值。但由于我是c#的新手,我不知道如何在c#中复制它。
所以我相信,首先我需要在XML中找到所有唯一的att1值。我可以这样做:
IEnumerable<string> uItems = uItemsArray.Distinct();
// Where uItemsArray is a collection of all the att1 values in an array
然后我不知道如何将每个唯一的att1值与整个文档进行比较,以获得存储在变量或数组或任何数据集中的音量。
以下是我最终使用的代码段:
XDocument doc = XDocument.Load(@"temp/salesData.xml");
var topItems = from item in doc.Descendants("item")
select new
{
name = (string)item.Attribute("name"),
sku = (string)item.Attribute("sku"),
iCat = (string)item.Attribute("iCat"),
sTime = (string)item.Attribute("sTime"),
price = (string)item.Attribute("price"),
desc = (string)item.Attribute("desc")
} into node
group node by node.sku into grp
select new {
sku = grp.Key,
name = grp.ElementAt(0).name,
iCat = grp.ElementAt(0).iCat,
sTime = grp.ElementAt(0).sTime,
price = grp.ElementAt(0).price,
desc = grp.ElementAt(0).desc,
Count = grp.Count()
};
_topSellers = new SalesDataObject[4];
int topSellerIndex = 0;
foreach (var item in topItems.OrderByDescending(x => x.Count).Take(4))
{
SalesDataObject topSeller = new SalesDataObject();
topSeller.iCat = item.iCat;
topSeller.iName = item.name;
topSeller.iSku = item.sku;
topSeller.sTime = Convert.ToDateTime(item.sTime);
topSeller.iDesc = item.desc;
topSeller.iPrice = item.price;
_topSellers.SetValue(topSeller, topSellerIndex);
topSellerIndex++;
}
感谢您的帮助!
答案 0 :(得分:4)
您使用的是.NET 3.5吗? (看起来它基于你的代码。)如果是这样,我怀疑使用LINQ to XML和LINQ to Objects这很容易。但是,我担心你的例子不清楚你想要什么。具有相同att1 的所有值是否具有相同的att2?如果是这样,它就像:
var results = (from element in items.Elements("item")
group element by element.Attribute("att1").Value into grouped
order by grouped.Count() descending
select grouped.First().Attribute("att2").Value).Take(4);
我还没有测试过,但是我认为它应该有用......
答案 1 :(得分:1)
如果你有这些值,你应该能够使用LINQ的GroupBy ......
XDocument doc = XDocument.Parse(xml);
var query = from item in doc.Descendants("item")
select new
{
att1 = (string)item.Attribute("att1"),
att2 = (string)item.Attribute("att2") // if needed
} into node
group node by node.att1 into grp
select new { att1 = grp.Key, Count = grp.Count() };
foreach (var item in query.OrderByDescending(x=>x.Count).Take(4))
{
Console.WriteLine("{0} = {1}", item.att1, item.Count);
}
答案 2 :(得分:1)
您可以使用LINQ / XLINQ来完成此任务。下面是我刚刚编写的示例控制台应用程序,因此代码可能没有进行优化,但它可以正常工作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Text;
namespace FrequencyThingy
{
class Program
{
static void Main(string[] args)
{
string data = @"<items>
<item att1=""ABC123"" att2=""uID"" />
<item att1=""ABC345"" att2=""uID"" />
<item att1=""ABC123"" att2=""uID"" />
<item att1=""ABC678"" att2=""uID"" />
<item att1=""ABC123"" att2=""uID"" />
<item att1=""XYZ123"" att2=""uID"" />
<item att1=""XYZ345"" att2=""uID"" />
<item att1=""XYZ678"" att2=""uID"" />
</items>";
XDocument doc = XDocument.Parse(data);
var grouping = doc.Root.Elements().GroupBy(item => item.Attribute("att1").Value);
foreach (var group in grouping)
{
var groupArray = group.ToArray();
Console.WriteLine("Group {0} has {1} element(s).", groupArray[0].Attribute("att1").Value, groupArray.Length);
}
Console.ReadKey();
}
}
}