2

我有一个 XML 提要(我无法控制),我试图弄清楚如何检测文档中某些属性值的数量。

我还在解析 XML 并将属性分成数组(用于其他功能)

这是我的 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 值。

我需要找到前 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++;
        } 

感谢你的帮助!

4

3 回答 3

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);

我还没有测试它,但我认为它应该可以工作......

  • 我们从所有项目元素开始
  • 我们按它们的 att1 值对它们(仍然作为元素)进行分组
  • 我们按组的大小对组进行排序,降序排列,所以最大的排在第一位
  • 从每个组中,我们取第一个元素来找到它的 att2 值
  • 我们将这些结果中的前四名
于 2008-12-17T20:47:24.787 回答
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);
        }
于 2008-12-17T20:47:01.120 回答
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();
        }
    }
}
于 2008-12-17T20:52:13.153 回答