views:

1533

answers:

2

Me again... I have an XML File that contains different categories which I would like to query for different attributes.

  <item>      
   <title>Industries</title>      
   <category type="Channel">Automotive</category>      
   <category type="Type">Cars</category>      
   <category type="Token">Article</category>      
   <category type="SpecialToken">News</category>      
   <guid>637f0dd7-57a0-4001-8272-f0fba60feba1</guid>
  </item>

IN SQL I would write something like.

select * from articles where channel = 'Automative' AND type = 'Cars' etc. etc.

How can I achieve this with linq? I tried the following query but it returns null. If I combine the two attributes with the "OR" || operator I would get the results, but with all double results if an item matches both criteria.

var articleList = (from item in doc.Descendants("item")

                         from _category in item.Elements("category")
                         where _category.Value == valueCboChannel && _category.Attribute("domain").Value == "Channel"
                         && (_category.Value == valueCboSubChannel && _category.Attribute("domain").Value == "SubChannel")

                         select new
                         {

                             Title = item.Element("title").Value,
                             Guid= item.Element("guid").Value,
                             description = item.Element("description").Value,
                             link = item.Element("link").Value
                         }).ToList();

            ListView1.DataSource = articleList;
            ListView1.DataBind();
+1  A: 

I'd simplify it with an extension method to do the tricky lookup:

(updated 12/02/09 to exclude empty elements)

static string CategoryValue(this XElement element, string type)
{
    var category = element.Elements("category").FirstOrDefault(
        c => (string)c.Attribute("type") == type
            && !string.IsNullOrEmpty(c.Value)); // UPDATE HERE
    return category == null ? null : category.Value;
}

static void Main()
{
    XDocument doc = XDocument.Parse(xml);
    var qry = from item in doc.Descendants("item")
              where item.CategoryValue("Channel") == "Automotive"
              && item.CategoryValue("Type") == "Cars"
              select item;
    foreach (var node in qry)
    {
        Console.WriteLine(node.Element("guid").Value);
    }
}
Marc Gravell
Thanks a lot Marc. It now works. Somehow I couldn't figure it out with the isNullOrEmpty.
Chris
A: 

Thanks for the tip, I managed somehow to get it to work but only with ".First" in the extension method.

The Problem I'm facing now is how to get all values where there are NULL values in the xml file. Basically the xml could look as follows. So if I use "First" then of course the first empty one will get selected, thus not displayed. Is there a way to skip the NULL values?

<item>
    <title>Industries</title>
    <category type="Channel"></category> 
    <category type="Channel">Automotive</category> 
    <category type="Type"></category>     
    <category type="Type">Cars</category>     
    <category type="Token">Article</category>       
    <category type="SpecialToken">News</category>       
    <guid>637f0dd7-57a0-4001-8272-f0fba60feba1</guid>  
</item>

Here the current extension method

    public static string CategoryValue(this XElement item, string type)
    {
        var category = item.Descendants("category").First(c => (string)c.Attribute("type") == type);
        return category == null ? null : category.Value;

    }
Chris
I'll update my previous answer to illustrate...
Marc Gravell
BTW - if you use First, you don't need the null check, as it will have already thrown an exception if it didn't find one
Marc Gravell