3

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?

6
  • 5
    You're in the right direction...why'd you quit? Although I'd recommend using XDocument instead. Commented Apr 15, 2015 at 15:26
  • 1
    You can iterate over the childnodes of your Xml document with doc.ChildNodes. I guess you could use a LINQ query to get the correct node by using the name. Commented Apr 15, 2015 at 15:27
  • @Steven, can you please code to iterate Commented Apr 15, 2015 at 15:33
  • Or use XPath, there are tons of information on the internet about parsing xml in C#. Commented Apr 15, 2015 at 15:33
  • 2
    Please don't just ask us to solve the problem for you. Show us how you tried to solve the problem yourself, then show us exactly what the result was, and tell us why you feel it didn't work. See "What Have You Tried?" for an excellent article that you really need to read. Commented Apr 15, 2015 at 15:56

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

4 Comments

This won't work - the XML is in a CDATA segment, and XDocument.Load() expects a file name. You want XDocument.Parse()
@DanField Ahh! You're correct. My mistake. I've edited my answer to reflect that. Thanks
No problem - but this still won't work. The XML he wants to access is actually embedded in a CDATA node. It has to be extracted before it can be used.
@DanField That edit will take me slightly longer to address :). I've made a quick correction to refer OP to your answer while I correct mine. Thanks for pointing out my oversight. I completely missed the CDATA node on first look.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.