3

I'm trying to find the inner text value of an element using LINQ-to-XML (an XElement object). I make my service call and get an XML response back that I've successfully loaded into an XElement object. I want to extract the inner text of one of the elements - however, every time I try to do this, I get a null result.

I feel like I'm missing something super-simple, but I'm fairly new to LINQ-to-XML. Any help is appreciated.

I'm trying to get the inner text value of the StatusInfo/Status element. Here's my XML document that's returned:

<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
  <title type="text">My Response</title>
  <id>tag:foo.com,2012:/bar/06468dfc-32f7-4650-b765-608f2b852f22</id>
  <author>
    <name>My Web Services</name>
  </author>
  <link rel="self" type="application/atom+xml" href="http://myServer/service.svc/myPath" />
  <generator uri="http://myServer" version="1">My Web Services</generator>
  <entry>
    <id>tag:foo.com,2012:/my-web-services</id>
    <title type="text" />
    <updated>2012-06-27T14:22:42Z</updated>
    <category term="tag:foo.com,2008/my/schemas#system" scheme="tag:foo.com,2008/my/schemas#type" />
    <content type="application/vnd.my.webservices+xml">
      <StatusInfo xmlns="tag:foo.com,2008:/my/data">
        <Status>Available</Status>  <!-- I want the inner text -->
      </StatusInfo>
    </content>
  </entry>
</feed>

Here's a snippet of code that I'm using to extract the value (which doesn't work):

    XElement root = XElement.Load(responseReader);
    XNamespace tag = "tag:foo.com,2008:/my/data";
    var status = (from s in root.Elements(tag + "Status")
                 select s).FirstOrDefault();

My status variable is always null. I've tried several variations on this, but to no avail. The part that's confusing me is the namespace -- tag and 2008 are defined. I don't know if I'm handling this correctly or if there's a better way to deal with this.

Also, I don't have control over the XML schema or the structure of the XML. The service I'm using is out of my control.

Thanks for any help!

David Hoerster
  • 28,421
  • 8
  • 67
  • 102
  • 1
    Are you sure you want to query `root.Elements`? Based on the documentation, it seems to me that `root.Elements` only returns (direct) children of `root`, whereas your `` element is more deeply nested. – O. R. Mapper Jun 27 '12 at 15:42
  • @O.R.Mapper stupid mistake on my part. If you add as an answer, I'll mark it as correct. Thanks! – David Hoerster Jun 27 '12 at 16:14
  • ebpower has already added a suitable answer with a workaround :-) – O. R. Mapper Jun 27 '12 at 18:27

2 Answers2

2

Try Descendants() instead of Elements():

XElement x = XElement.Load(responseReader);
XNamespace ns = "tag:foo.com,2008:/my/data";
var status = x.Descendants(ns + "Status").FirstOrDefault().Value;
Ed Power
  • 8,310
  • 3
  • 36
  • 42
0

There are 2 Namespaces in the feed:

  1. the Atom namespace
  2. the tag namespace

The outer xml needs to use the Atom namespace, while a portion of the inner xml needs to use the tag namespace. i.e.,

var doc = XDocument.Load(responseReader);
XNamespace nsAtom = "http://www.w3.org/2005/Atom";
XNamespace nsTag = "tag:foo.com,2008:/my/data";

// get all entry nodes / use the atom namespace
var entry = doc.Root.Elements(nsAtom + "entry");

// get all StatusInfo elements / use the atom namespace
var statusInfo = entry.Descendants(nsTag + "StatusInfo");

// get all Status / use the tag namespace
var status = statusInfo.Elements(nsTag + "Status");

// get value of all Status
var values = status.Select(x => x.Value.ToString()).ToList();
Metro Smurf
  • 37,266
  • 20
  • 108
  • 140