15

I've chosen the title here as my problem is I need to get the Item nodes mentioned in the example. I have the following XML and am having problems using LINQ to query it, I've been able to parse XML before - however I've been stuck on this for hours and hope someone can help. Here is my XML data below (example data):

<a:entry
    xmlns:a="http://www.w3.org/2005/Atom">
    <a:id>98765</a:id>
    <info>Data Catalogue</info>
    <data>
        <items>
            <item>
                <id>123456</id>
                <value>Item One</value>
            </item>
            <item>
                <id>654321</id>
                <value>Item Two</value>
            </item>
        </items>
    </data>
    <items>
        <item>
            <id>123456</id>
            <value>Item One</value>
        </item>
        <item>
            <id>654321</id>
            <value>Item Two</value>
        </item>
    </items>
    <a:author>
        <a:name>Catalogue</a:name>
    </a:author>
</a:entry>

I want to be able to extract the ID from the Item XML tag under Items, however there is an Items Tag with Item entries under data I DO NOT want these nodes at all - I want root/items/id/id if this were expressed as path. I've tried everything I know with LINQ so if someone could help, things to note although this is sample data it is based on the system - the format cannot be changed so that is not an acceptable solution.
I can't seem to determine where I'm going wrong - every LINQ expression I try returns nothing, I think the namespace is an issue and have tried to integrate this but I'm going in circles.
Solution must work in Silverlight and C#

I have tried the following:

IEnumerable<XElement> nodes =
    element.Elements().Where(e => e.Name.LocalName == "items")

However this gets me all the "items" including the ones under "data" I don't want those.


If I do the following on my XML I do see the Names of the Elements displayed:

XElement element = XElement.Parse(data);
foreach (XElement node in element.Elements())
{
  MessageBox.Show(node.Name.LocalName);
}

However when I do this I cannot see the node names under items at all - I've checked the XElement and it does have the node and when I output the names above it "items" shows up along with info and id!

foreach (XElement node in element.Elements("items"))
{
  MessageBox.Show(node.Name.LocalName);
}
RoguePlanetoid
  • 4,516
  • 7
  • 47
  • 64
  • 1
    I figured it out - there was an extra namespace declaration that was blank - adding an implied namespace to my XML, using the XNamespace for this and adding it to the Element Name solves the problem! – RoguePlanetoid Nov 09 '10 at 16:52

2 Answers2

29

Assuming element is your <a:entry> element:

var ids = element.Element("items")
                 .Elements("item")
                 .Select(item => item.Element("id").Value);

The Element and Elements methods return only direct children, not all descendants, so it doesn't return the <items> element which is under <data>

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • 1
    This does not work, although I thought it would as this is the kind of thijng I've used before - I find that I cannot get any Elements from the root at all there was a value node off the root I've left off in the example and I cannot read it either - if I query the descendants there are some there - just don't know what's going on. – RoguePlanetoid Nov 09 '10 at 16:27
  • 1
    This does work once I take the namespace into account like my own answer! – RoguePlanetoid Nov 09 '10 at 16:54
  • You didn't provide that information in your question... I tried it using the `` element as the root and it worked fine. – Thomas Levesque Nov 09 '10 at 17:03
  • I hadn't noticed it - nor did I think it was the issue until now, I had shortened the namespaces but didn't notice one was blank - so your answer was fine once I took this into account, and posted the version I used - which works, based on your answer, so thanks again it did help! – RoguePlanetoid Nov 09 '10 at 17:08
14

I had a blank Namespace Declaration in my XML I hadn't noticed once I added this into my code it worked - forgot LINQ is very NameSpace oriented!

XNamespace ns = "http://example.org/namespace";
var ids = element.Element(ns + "items") 
                 .Elements("item") 
                 .Select(item => item.Element("id").Value); 
RoguePlanetoid
  • 4,516
  • 7
  • 47
  • 64