Domanda

Ho un feed XML (che io non controllo) e sto cercando di capire come rilevare il volume di alcuni valori degli attributi all'interno del documento.

Sono anche parsing XML e separare gli attributi in array (per altre funzionalità)

Ecco un esempio del mio 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>

Voglio trovare i nodi volume basati su ogni valore ATT1. ATT1 valore cambierà. Una volta che so la frequenza dei valori ATT1 ho bisogno di tirare il valore ATT2 di quel nodo.

Ho bisogno di trovare i primi 4 articoli e tirare i valori dei loro attributi.

Tutto questo deve essere fatto in C # codice dietro.

Se stavo usando JavaScript vorrei creare un array associativo e hanno ATT1 essere la chiave e la frequenza al valore. Ma dal momento che io sono nuovo a C # non so come duplicare questo in C #.

Quindi credo, prima ho bisogno di trovare tutti i valori ATT1 uniche nel XML. Posso farlo utilizzando:

IEnumerable<string> uItems = uItemsArray.Distinct();
// Where uItemsArray is a collection of all the att1 values in an array

Poi mi si blocca su come mi confronto ogni valore ATT1 unica per l'intero documento per ottenere il volume memorizzato in una variabile o una matrice o qualsiasi insieme di dati.

Ecco il frammento di Ho finito per usare:

        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++;
        } 

Grazie per il vostro aiuto!

È stato utile?

Soluzione

Se si dispone dei valori, si dovrebbe essere in grado di utilizzare di 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);
        }

Altri suggerimenti

Stai usando .NET 3.5? (Sembra che basa su codice.) Se è così, ho il sospetto che questo è abbastanza facile con LINQ to XML e LINQ to Objects. Tuttavia, temo che non è chiaro dal vostro esempio ciò che si desidera. Fare tutti i valori con lo stesso ATT1 anche hanno lo stesso ATT2? Se è così, si tratta di qualcosa di simile a:

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

Non ho ancora testato, ma mi pensare dovrebbe funzionare ...

  • Si parte con tutti gli elementi voce
  • raggrupparli (ancora come elementi) dal loro valore ATT1
  • Abbiamo ordinare i gruppi per le loro dimensioni, scendendo così il più grande è il primo
  • Da ogni gruppo si prende il primo elemento di trovare il suo valore ATT2
  • Prendiamo le prime quattro di questi risultati

È possibile utilizzare LINQ / XLINQ per raggiungere questo obiettivo. Qui di seguito è un'applicazione di console di esempio che ho appena scritto, in modo che il codice non può essere ottimizzato, ma funziona.

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();
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top