Extracting data from XML string using linq vs xmlDocument
I've done this a few times using the xmlDocument approach, but I wanted to use the more powerful linq to xml approach. However, it looks like I ran into a wall. I am getting data back from the soothing API from twillio / crmText. Here is a link to their site where their documents live: http://crmtext.com/api/docs
Here is my XML string:
<response op="getcustomerinfo" status="200" message="ok" version="1.0">
<customer>
<totalMsg>3</totalMsg>
<custId>9008281</custId>
<custName></custName>
<timestamp>2015-04-30 16:17:19</timestamp>
<optinStatus>3</optinStatus>
<custMobile>6185551212</custMobile>
<subacct>1st Choice Courier</subacct>
</customer>
</response>
I need to find out optinStatus. It should return 3. I am using the below which returns the above xml
XDocument xdoc = XDocument.Parse(result1);
I have tried about 4000 different things, including:
IEnumerable<XElement> otinStatus = from el in xdoc.Elements("customer") select el;
IEnumerable<XElement> otinStatus2 = from el in xdoc.Elements("cusotmer.optinStatus") select el;
IEnumerable<XElement> otinStatus3 = from el in xdoc.Elements("optinStatus") select el;
All of them return no results.
Please help, I know this is something simple that I am missing. Thanks in advance - Joe
source to share
Get item value
var status = xDoc
.Descendants("optinStatus") // get the optinStatus element
.Single() // we're expecting a single result
.Value; // get the XElement value
Example
Here's a working script for you. You can see that live is running here . Output signal 3
.
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
public class Program
{
public static void Main()
{
var xDoc = XDocument.Parse(xmlString);
var status = xDoc.Descendants("optinStatus").Single();
Console.WriteLine(status.Value);
}
private static string xmlString = @"
<response op=""getcustomerinfo"" status=""200"" message=""ok"" version=""1.0"">
<customer>
<totalMsg>3</totalMsg>
<custId>9008281</custId>
<custName></custName>
<timestamp>2015-04-30 16:17:19</timestamp>
<optinStatus>3</optinStatus>
<custMobile>6185312349</custMobile>
<subacct>1st Choice Courier</subacct>
</customer>
</response>
";
}
Explanation
Descendents()
is a method of instance axes (or just axes in shorthand). It returns IEnumerable<XElement>
all matching children. Based on its results, we call Single()
. This is a Linq method that returns a single element in a sequence. If there is more than one item, it will throw an error. We are left with one XElement
. This represents a whole XML element. Since we want its value not to be the entire element, we name the property Value
. Bingo, we're done.
Bit More
Axles are of two types:
- The instance axis methods that are listed here on MSDN are invokable members of the classes
XElement
,XDocument
andXNode
. - The extended axis methods that are listed on the MSDN list here are invokable in collections.
With one exception, the axes method returns a collection of the type IEnumerable<T>
. An exception is Element()
that which returns the first matching child object. This is what AmatuerDev used, and as in your question, if you only expect one result, this is a good, if not the best approach that Descendants()
.
Get attribute value
Once we have XElement
, we can extract one of its attributes instead of its value. We do this by calling the method Attributes()
. It returns a match XAttribute
. Since we only want the value of the attribute, we name the property Value
. Voila.
// for attribute
var response = xDoc.Descendants("response").Single();
var attr = response.Attribute("status");
General approach
Using Linq to XML is a two step process.
- Calling the axis method to get the result
IEnumerable<T>
. - Use Linq to query this.
see also
Below is the relevant MSDN documentation:
source to share