Fakhar uz zaman
Fakhar uz zaman

Reputation: 341

Extract data from XML using XmlDocument

I am consuming a weather web service in c#. I am passing it Lat-Long and it returns forecasted maximum & minimum temperature of that area. Following is code that i am using

 var response = client.ndfdGen(latlong);
 XmlDocument doc = new XmlDocument();
 doc.LoadXml(response);

And the following is the response data, that I get i.e. xml response In this response, there is Latitude and Longitude. I have to extract this.

<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Body>
      <ns1:NDFDgenResponse xmlns:ns1="http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl">
         <dwmlOut xsi:type="xsd:string"><![CDATA[<?xml version="1.0"?>
<dwml version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.nws.noaa.gov/forecasts/xml/DWMLgen/schema/DWML.xsd">
  <head>
    <product srsName="WGS 1984" concise-name="time-series" operational-mode="official">
      <title>NOAA's National Weather Service Forecast Data</title>
      <field>meteorological</field>
      <category>forecast</category>
      <creation-date refresh-frequency="PT1H">2015-04-15T15:13:07Z</creation-date>
    </product>
    <source>
      <more-information>http://www.nws.noaa.gov/forecasts/xml/</more-information>
      <production-center>Meteorological Development Laboratory<sub-center>Product Generation Branch</sub-center></production-center>
      <disclaimer>http://www.nws.noaa.gov/disclaimer.html</disclaimer>
      <credit>http://www.weather.gov/</credit>
      <credit-logo>http://www.weather.gov/images/xml_logo.gif</credit-logo>
      <feedback>http://www.weather.gov/feedback.php</feedback>
    </source>
  </head>
  <data>
    <location>
      <location-key>point1</location-key>
      <point latitude="39.01" longitude="-77.02"/>
    </location>
    <moreWeatherInformation applicable-location="point1">http://forecast.weather.gov/MapClick.php?textField1=39.01&amp;textField2=-77.02</moreWeatherInformation>
    <time-layout time-coordinate="local" summarization="none">
      <layout-key>k-p24h-n2-1</layout-key>
      <start-valid-time>2015-04-17T08:00:00-04:00</start-valid-time>
      <end-valid-time>2015-04-17T20:00:00-04:00</end-valid-time>
      <start-valid-time>2015-04-18T08:00:00-04:00</start-valid-time>
      <end-valid-time>2015-04-18T20:00:00-04:00</end-valid-time>
    </time-layout>
    <parameters applicable-location="point1">
      <temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n2-1">
        <name>Daily Maximum Temperature</name>
        <value>68</value>
        <value>71</value>
      </temperature>
    </parameters>
  </data>
</dwml>]]></dwmlOut>
      </ns1:NDFDgenResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

I want to extract information in <time-layout time-coordinate="local" summarization="none"> like start-valid-time,end-valid-time and temperature from <temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n2-1"> tags.

How can I reach out to these nodes and iterate over it?

Upvotes: 3

Views: 878

Answers (2)

LiamK
LiamK

Reputation: 815

As suggested in the comments, using XDocument will get you access to a number of LINQ-to-XML methods built for just such a purpose:

// load up the xml into an XDocument
var response = client.ndfdGen(latlong);
var originalDocument = XDocument.Parse(response);

// extract cdata
var cdata = originalDocument.DescendantNodes().OfType<XCData>().First().Value;
var cdataDocument = XDocument.Parse(cdata);

// find the right element via xpath
var myElement = cdataDocument.Root.XPathSelectElement("//dwml/data/location/point");
return myElement.Attribute("latitude").Value;

Note that using the "//" operator in xPath doesn't have great performance. Try nailing down an absolute path once you get the proof of concept working. An explanation of the xPath operations available can be found on MSDN

Upvotes: 1

Dan Field
Dan Field

Reputation: 21641

You're going to have to extract the CDATA first, that's really the only special challenge here - then you can use XmlDocument or XDocument or XmlReader. I'd recommend doing it this way:

var response = client.ndfdGen(latlong);
XDocument xd = null;

using (XmlReader xr = XmlReader.Create(new StringReader(response))) // load the response into an XmlReader
{
    xr.ReadToDescendant("dwmlOut"); // go to the dwmlOut node
    xr.Read(); // move to the CDATA in that node
    xd = XDocument.Parse(xr.Value); // load **that** XML into your XDocument
}

string startTime = xd.Descendants("start-valid-time").First().Value;

and so on.

If you insist on using XmlDocument, you could use the same method here and just do XmlDocument.LoadFrom(xr.Value), but the XDocument API is a bit more flexible and will certianly perform better.

Upvotes: 1

Related Questions