tags:

views:

177

answers:

1

Hi All,

I'm getting a string returned from a website that looks like this

<?xml version=\"1.0\" encoding=\"UTF-8\"?><searchResponse requestID=\"500\" status=\"success\"><pso><psoID ID=\"61F2C644-F93A-11DE-8015-73A11AB14291\" targetID=\"mezeoAccount\"><data><email>[email protected]</email><quotaMeg>2048</quotaMeg><quotaUsed>1879736</quotaUsed><active>true</active><unlocked>true</unlocked><allowPublic>true</allowPublic><realm>mezeo</realm><bandwidthQuota>1000000000</bandwidthQuota><billingDay>1</billingDay></data></psoID></pso></searchResponse>"

I then try and create an XDocument from it so I can enumerate through the elements

XDocument doc = new XDocument();
doc = XDocument.Parse(respStr);

but if I query the elements or descendants everytime it returns null. I can't go

string s = doc.Element("email").Value;
// or
doc.Descendants("data"); // returns null as well

XDocument.Parse doesnt return an error, but I dont seem to have a searchable xDocument.

Can anyone see anything obviously wrong with what I am doing?

Cheers, Al

+1  A: 

You don't need to create a new XDocument before calling XDocument.Parse. This won't cause any problems, it's just pointless.

However, this line is wrong because email is not a child of the document root:

doc.Element("email").Value;

Your second example looks fine. This works for me:

string s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><searchResponse requestID=\"500\" status=\"success\"><pso><psoID ID=\"61F2C644-F93A-11DE-8015-73A11AB14291\" targetID=\"mezeoAccount\"><data><email>[email protected]</email><quotaMeg>2048</quotaMeg><quotaUsed>1879736</quotaUsed><active>true</active><unlocked>true</unlocked><allowPublic>true</allowPublic><realm>mezeo</realm><bandwidthQuota>1000000000</bandwidthQuota><billingDay>1</billingDay></data></psoID></pso></searchResponse>";
XDocument doc = XDocument.Parse(s);
foreach (XElement e in doc.Descendants("data"))
    Console.WriteLine(e);

Result:

<data>
  <email>[email protected]</email>
  <quotaMeg>2048</quotaMeg>
  <quotaUsed>1879736</quotaUsed>
  <active>true</active>
  <unlocked>true</unlocked>
  <allowPublic>true</allowPublic>
  <realm>mezeo</realm>
  <bandwidthQuota>1000000000</bandwidthQuota>
  <billingDay>1</billingDay>
</data>

In response to your second third question (see comments to this answer) try this:

using System;
using System.Xml.XPath;
using System.Xml.Linq;

class Program
{
    public static void Main()
    {
        string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><searchResponse requestID=\"500\" status=\"success\"><pso><psoID ID=\"61F2C644-F93A-11DE-8015-73A11AB14291\" targetID=\"mezeoAccount\"><data><email>[email protected]</email><quotaMeg>2048</quotaMeg><quotaUsed>1879736</quotaUsed><active>true</active><unlocked>true</unlocked><allowPublic>true</allowPublic><realm>mezeo</realm><bandwidthQuota>1000000000</bandwidthQuota><billingDay>1</billingDay></data></psoID></pso></searchResponse>";
        XDocument doc = XDocument.Parse(xml);
        foreach (XElement e in doc.XPathSelectElements("/searchResponse/pso/psoID/data/*"))
                Console.WriteLine(e);
    }
}

Output:

<email>[email protected]</email>
<quotaMeg>2048</quotaMeg>
<quotaUsed>1879736</quotaUsed>
<active>true</active>
<unlocked>true</unlocked>
<allowPublic>true</allowPublic>
<realm>mezeo</realm>
<bandwidthQuota>1000000000</bandwidthQuota>
<billingDay>1</billingDay>
Mark Byers
If I step through the same example, I get one statment outputting the text as you showed. How do I make it read me the value of the email field though for example. I thought I should be able to go doc.Element("email").Value;Is doc.Element("email").Value not correct?
Al Ashcroft
It's not correct because "email" isn't a child of the document root, it's a child of "data". Element fetches only direct children. If you want grandchildren too, use Descendants("email"). Or you could do it with XPath: `using System.Xml.XPath;` ... `foreach (XElement e in doc.XPathSelectElements("/searchResponse/pso/psoID/data/email"))`. Hint: you should have just asked this question in the first place, then you would have gotten the answer you wanted straight away instead of it taking two questions.
Mark Byers
Sorry, not really sure I understand. What is the correct way to read all the individual elements under data? I was trying var psoQuery = from pso in doc.Descendants("data") select new MezeoAccount { Email = pso.Element("email").Value, QuotaMeg = Convert.ToInt64(pso.Element("quotaMeg").Value)... but that wasnt returning anything. I can get values by Console.Write(doc.Element("searchResponse").Element("pso").Element("psoID").Element("data").Element("email").Value); just looks wrong.
Al Ashcroft
Again you changed your question... this site is not good for holding discussions. It is designed for getting answers to well-defined questions. You should think carefully first, and ask the question you want the answer to and try to avoid asking questions that you don't want the answer to. To try to answer your new question: Why not use XPath as I demonstrated above, but remove `email` from the XPath? It's a much cleaner solution than plain LINQ, IMHO.
Mark Byers
I've posted full source code for the XPath solution for your situation. You should just be able to copy and paste it in and it will work. If this isn't the answer you wanted, I suggest you think more carefully about what question to ask to get an answer will be useful to you. Try to describe the actual problem you are trying to solve in your question. I.e. 'How would I parse this document to get all the email addresses? I tried this, but it throws a null exception.' instead of 'Why does this code throw a null exception?' The second question tells us nothing about what you are trying to do.
Mark Byers
Thanks Mark, I'll have a crack with XPath and see if that can do what I want.
Al Ashcroft
@Al: I also looked back in your history and found another very similar question you asked. It seems that the answer you got there was wrong, and that's why you were having problems with getting Element() working here. I've added an answer to that question too, where I take the document and turn it into an object (tested on the XML doc you gave there, which is slightly different from this one). It seems that if you already plan to convert the XML into an object, you can just query the object for the information you need.
Mark Byers