Dom Sinclair
Dom Sinclair

Reputation: 2528

Linq To Xml Returning an alphebetically sorted distinct list of values

I have been playing around in Linqpad trying to get this right but I keep missing. Consider the following:

//<SpeciesSizes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
// < SpeciesSize >
//  < DisplayCode > CAT </ DisplayCode >
//  < EnglishName > Wolffishes(= Catfishes) nei </ EnglishName >
//      < State > FRE </ State >
//      < Presentation > BMS </ Presentation >
//      < Freshness > SO </ Freshness >
//      < Size > 9 </ Size >
//      < Description > Species not included in the common marketing standards</Description>
//       </SpeciesSize>
//  <SpeciesSize>
//    <DisplayCode>CAT</DisplayCode>
//         <EnglishName>Wolffishes(= Catfishes) nei </ EnglishName >
//          < State > FRE </ State >
//          < Presentation > FIL </ Presentation >
//          < Freshness > SO </ Freshness >
//          < Size > 9 </ Size >
//          < Description > Species not included in the common marketing standards</Description>
// </SpeciesSize>
//  < SpeciesSize >
//  < DisplayCode > FLE </ DisplayCode >
//  < EnglishName > European flounder </ EnglishName >
//     < State > FRE </ State >
//     < Presentation > GUT </ Presentation >
//     < Freshness > E </ Freshness >
//     < Size > 1 </ Size >
//     < Description > According to AnnexII of Council R. 2406 / 96 </ Description >
//      </ SpeciesSize >
// < SpeciesSize >
//       < DisplayCode > GUX </ DisplayCode >
//       < EnglishName > Gurnards, searobins nei</EnglishName>
//       <State>FRO</State>
//       <Presentation>ROE</Presentation>
//       <Freshness>SO</Freshness>
//       <Size>9</Size>
//       <Description>Species not included in the common marketing standards</Description>
//  </SpeciesSize>
//</SpeciesSizes>
static string path = @"C:\Users\dom\Documents\Speciescrossreference.xml";

void Main()
{
    XDocument doc = XDocument.Load(path);

    var names = from n in doc.Root.Descendants("SpeciesSizes")
    group n by n.Element("SpeciesSize") into g
    select new {
        name = g.Element("EnglishName").Distinct().ToList()
    };


    names.Dump();

}

There are approximately 4000 <SpeciesSize> elements, and of those around 150 unique English names.

I have read various answers here on SO and taken bits to from them to cobble together what I have here, but clearly I've failed to understand all of the syntax demonstrated in those answers.

Would someone be able to tell me what I am doing incorrectly such that I would later on be able to construct other queries (against the same xml) that might involve grouping on different elements.

Given the example xml at the top of the code sample I would be looking atr returning the following:

Upvotes: 0

Views: 52

Answers (2)

Dom Sinclair
Dom Sinclair

Reputation: 2528

For the sake of completeness if anyone else comes to this. The accepted answer pointed me in the correct direction, producing a list of unique English names. I needed that list sorted in alphabetical order though and after a bit of playing around this slight adaptation to the above answer gave me what I was after;

var names  = from n in doc.Root.Descendants("SpeciesSize")
            orderby n.Element("EnglishName").Value
            group n by  n.Element("EnglishName").Value  into g

            select new
            {
                name =  g.Key
            };

EDIT

Following the comment below about getting it right I was determined to figure out just how to do it.

This is the best I have come up with which just uses Distinct and avoids the group by clause entirely.

var names = (from n in doc.Root.Descendants("SpeciesSize")
            orderby n.Element("EnglishName").Value
            select new
            {
                name = n.Element("EnglishName").Value
            }).Distinct();

Upvotes: 0

PinBack
PinBack

Reputation: 2564

Without the spaces in your example you can use this:

var names = from n in doc.Root.Descendants("SpeciesSize")
            group n by n.Element("EnglishName").Value into g
            select new
            {
                name = g.Key
            };

UPDATE @CodingYoshi:
Yes, that's right. If it's just about reading the names, you can do the following:

var names = doc.Root.Descendants("EnglishName")
    .Select(item => item.Value)
    .Distinct()
    .OrderBy(item => item);

Upvotes: 2

Related Questions