2009-02-23 16 views
11

Ho seguente file:interrogazione xmlnode utilizzando LINQ

<root> 
    <Product desc="Household"> 
    <Product1 desc="Cheap"> 
     <Producta desc="Cheap Item 1" category="Cooking" /> 
     <Productb desc="Cheap Item 2" category="Gardening" /> 
    </Product1> 
    <Product2 desc="Costly"> 
     <Producta desc="Costly Item 1" category="Decoration"/> 
     <Productb desc="Costly Item 2" category="Furnishing" /> 
     <Productc desc="Costly Item 3" category="Pool" /> 
    </Product2> 
    </Product> 
</root> 

io voglio scoprire informazioni come: Totale articoli in buon mercato e costosi, elenco di tutte le categorie (come cucina, giardinaggio, decorazione ...) , elenco della categoria ordinata e selezionare solo il prodotto che è 'Costoso'

Come posso utilizzare LINQ. ho fatto fino ad ora:

XElement xe = XElement.Load(Server.MapPath("~/product.xml")); 
???? 

risposta

9

tua struttura XML è un peccato in quanto utilizza un elemento del prodotto per tre livelli della gerarchia. Avete altri elementi simili a quello "domestico"?

Supponendo che vogliamo solo quelli per la casa, è possibile utilizzare:

articoli Count in ciascuno di basso costo/costosi

xe.Element("Product") // Select the Product desc="household" element 
    .Elements() // Select the elements below it 
    .Select(element => new { Name=(string) element.Attribute("desc"), 
          Count=element.Elements().Count() }); 

Lista tutte le categorie

xe.Descendants() // Select all descendant elements 
    .Attributes() // All attributes from all elements 
    // Limit it to "category" elements 
    .Where(attr => attr.Name == "category") 
    // Select the value 
    .Select(attr => attr.Value) 
    // Remove duplicates 
    .Distinct(); 

Per ordina questo, basta usare .OrderBy(x => x) alla fine.

Selezionare i prodotti 'costosi'

xe.Descendants() // Select all elements 
    // Only consider those with a "Costly" description 
    .Where(element => (string) element.Attribute("desc") == "Costly") 
    // Select the subelements of that element, and flatten the result 
    .SelectMany(element => element.Elements()); 
+1

Ho davvero bisogno di insegnare a me stesso LINQ ... suoni soooo facile in questo modo:) – balexandre

+0

Ho cambiato l'xml e funziona ... grazie per la risposta –

+1

Dubito che Jon intendesse rinominare i singoli elementi * entro * i dati; piuttosto di avere nomi diversi per ogni * livello * ... –

9

Bene, personalmente trovo più facile con XmlDocument:

XmlDocument root = new XmlDocument(); 
    root.LoadXml(xml); // or .Load(path); 

    var categories = root.SelectNodes(
     "/root/Product/Product/Product/@category") 
     .Cast<XmlNode>().Select(cat => cat.InnerText).Distinct(); 
    var sortedCategories = categories.OrderBy(cat => cat); 
    foreach (var category in sortedCategories) 
    { 
     Console.WriteLine(category); 
    } 

    var totalItems = root.SelectNodes(
     "/root/Products/Product/Product").Count; 
    Console.WriteLine(totalItems); 

    foreach (XmlElement prod in root.SelectNodes(
     "/root/Product/Product[@desc='Costly']/Product")) 
    { 
     Console.WriteLine(prod.GetAttribute("desc")); 
    }