Reputation: 11
I am working on parsing this XML from this weather link "http://alerts.weather.gov/cap/us.php?x=0". I found a good sample code and it works great for parsing 'tile' and 'cap:event' except I needed to parse the 'cap:geocode' and get a list of ('value' & 'valueName') elements underneath it.
<entry>
...
<cap:geocode>
<valueName>FIPS6</valueName>
<value>002016</value>
<valueName>UGC</valueName>
<value>AKZ185</value>
</cap:geocode>
...
</entry>
Here is the code I am using:
XDocument doc = XDocument.Parse(objText);
XNamespace ns = XNamespace.Get("http://www.w3.org/2005/Atom");
XNamespace nsCap = XNamespace.Get("urn:oasis:names:tc:emergency:cap:1.1");
var xlist = doc.Descendants(ns + "entry").Select(elem => new
{
Title = elem.Descendants(ns + "title").FirstOrDefault(),
AreaDesc = elem.Descendants(nsCap + "areaDesc").FirstOrDefault(),
Geocode = elem.Descendants(nsCap + "geocode").Select( gc => new
{
val = gc.Element("value"),
valName = gc.Element("valueName")
}).ToList()
});
foreach (var el in xlist)
{
System.Diagnostics.Debug.WriteLine(string.Format("title: {0}, AreaDesc: {1}",
el.Title != null ? el.Title.Value : string.Empty,
el.AreaDesc != null ? el.AreaDesc.Value : string.Empty));
foreach (var x in el.Geocode)
{
string value = x.val.Value;
string valueName = x.valName.Value;
}
}
When I ran the code, the el.Geocode elements contain null. I am not sure why it is not giving me values.
Here is the XML from weather.gov:
<?xml version = '1.0' encoding = 'UTF-8' standalone = 'yes'?>
<!--
This atom/xml feed is an index to active advisories, watches and warnings
issued by the National Weather Service. This index file is not the complete
Common Alerting Protocol (CAP) alert message. To obtain the complete CAP
alert, please follow the links for each entry in this index. Also note the
CAP message uses a style sheet to convey the information in a human readable
format. Please view the source of the CAP message to see the complete data
set. Not all information in the CAP message is contained in this index of
active alerts.
-->
<feed
xmlns = 'http://www.w3.org/2005/Atom'
xmlns:cap = 'urn:oasis:names:tc:emergency:cap:1.1'
xmlns:ha = 'http://www.alerting.net/namespace/index_1.0'
>
<!-- http-date = Thu, 13 Feb 2014 07:35:00 GMT -->
<id>http://alerts.weather.gov/cap/us.atom</id>
<logo>http://alerts.weather.gov/images/xml_logo.gif</logo>
<generator>NWS CAP Server</generator>
<updated>2014-02-13T14:35:00-05:00</updated>
<author>
<name>[email protected]</name>
</author>
<title>Current Watches, Warnings and Advisories for the United States Issued by the National Weather Service</title>
<link href='http://alerts.weather.gov/cap/us.atom'/>
<entry>
<id>http://alerts.weather.gov/cap/wwacapget.php?x=AK12514240A72C.BlizzardWarning.1251424FD8A0AK.AFCWSWALU.51c52d9702226c0667b44fead05cc33e</id>
<updated>2014-02-13T09:43:00-09:00</updated>
<published>2014-02-13T09:43:00-09:00</published>
<author>
<name>[email protected]</name>
</author>
<title>Blizzard Warning issued February 13 at 9:43AM AKST until February 14 at 9:00AM AKST by NWS</title>
<link href='http://alerts.weather.gov/cap/wwacapget.php?x=AK12514240A72C.BlizzardWarning.1251424FD8A0AK.AFCWSWALU.51c52d9702226c0667b44fead05cc33e'/>
<summary>...ARCTIC AIR RETURNING TO SOUTHWEST ALASKA... .VERY COLD AIR ACCOMPANIED BY BRISK NORTHERLY WINDS WILL MAKE FOR DANGEROUS WIND CHILLS ACROSS MUCH OF SOUTHWEST ALASKA THROUGH FRIDAY. THESE WIND CHILL VALUES WILL BE SOME OF THE COLDEST OF THE ENTIRE WINTER THUS FAR. STRENGTHENING WINDS WILL CONTINUE TO SURGE SOUTHWARD ALONG THE ALASKA PENINSULA AND EASTERN ALEUTIANS.</summary>
<cap:event>Blizzard Warning</cap:event>
<cap:effective>2014-02-13T09:43:00-09:00</cap:effective>
<cap:expires>2014-02-14T09:00:00-09:00</cap:expires>
<cap:status>Actual</cap:status>
<cap:msgType>Alert</cap:msgType>
<cap:category>Met</cap:category>
<cap:urgency>Expected</cap:urgency>
<cap:severity>Severe</cap:severity>
<cap:certainty>Likely</cap:certainty>
<cap:areaDesc>Eastern Aleutians</cap:areaDesc>
<cap:polygon></cap:polygon>
<cap:geocode>
<valueName>FIPS6</valueName>
<value>002016</value>
<valueName>UGC</valueName>
<value>AKZ185</value>
</cap:geocode>
<cap:parameter>
<valueName>VTEC</valueName>
<value>/X.UPG.PAFC.WW.Y.0009.140213T2300Z-140214T1800Z/
/X.EXB.PAFC.BZ.W.0007.140213T1843Z-140214T1800Z/</value>
</cap:parameter>
</entry>
<entry>
<id>http://alerts.weather.gov/cap/wwacapget.php?x=AK12514240A72C.BlizzardWarning.125142504DD0AK.AFCWSWALU.b6bd8b4269647f8f24176412e2248b93</id>
<updated>2014-02-13T09:43:00-09:00</updated>
<published>2014-02-13T09:43:00-09:00</published>
<author>
<name>[email protected]</name>
</author>
<title>Blizzard Warning issued February 13 at 9:43AM AKST until February 14 at 12:00PM AKST by NWS</title>
<link href='http://alerts.weather.gov/cap/wwacapget.php?x=AK12514240A72C.BlizzardWarning.125142504DD0AK.AFCWSWALU.b6bd8b4269647f8f24176412e2248b93'/>
<summary>...ARCTIC AIR RETURNING TO SOUTHWEST ALASKA... .VERY COLD AIR ACCOMPANIED BY BRISK NORTHERLY WINDS WILL MAKE FOR DANGEROUS WIND CHILLS ACROSS MUCH OF SOUTHWEST ALASKA THROUGH FRIDAY. THESE WIND CHILL VALUES WILL BE SOME OF THE COLDEST OF THE ENTIRE WINTER THUS FAR. STRENGTHENING WINDS WILL CONTINUE TO SURGE SOUTHWARD ALONG THE ALASKA PENINSULA AND EASTERN ALEUTIANS.</summary>
<cap:event>Blizzard Warning</cap:event>
<cap:effective>2014-02-13T09:43:00-09:00</cap:effective>
<cap:expires>2014-02-14T12:00:00-09:00</cap:expires>
<cap:status>Actual</cap:status>
<cap:msgType>Alert</cap:msgType>
<cap:category>Met</cap:category>
<cap:urgency>Expected</cap:urgency>
<cap:severity>Severe</cap:severity>
<cap:certainty>Likely</cap:certainty>
<cap:areaDesc>Alaska Peninsula</cap:areaDesc>
<cap:polygon></cap:polygon>
<cap:geocode>
<valueName>FIPS6</valueName>
<value>002013 002164</value>
<valueName>UGC</valueName>
<value>AKZ181</value>
</cap:geocode>
<cap:parameter>
<valueName>VTEC</valueName>
<value>/X.EXT.PAFC.BZ.W.0007.140213T1843Z-140214T2100Z/</value>
</cap:parameter>
</entry>
</entry>
</feed>
Upvotes: 1
Views: 970
Reputation: 475
I think your first problem is that you are missing the namespace in this part of the code
val = gc.Element("value"),
valName = gc.Element("valueName")
I think your second problem is that you have written the GeoCode property of your anonymous type to be a list of the <cap:geocode>
elements, while you were expecting to use it as a list of the valueName/value pairs within the <cap:geocode>
element. At least that's my assumption. Therefore, this is probably closer to what you want
var xlist = doc.Descendants(ns + "entry").Select(elem => new
{
Title = elem.Descendants(ns + "title").FirstOrDefault(),
AreaDesc = elem.Descendants(nsCap + "areaDesc").FirstOrDefault(),
GeocodeElements = elem.Descendants(nsCap + "geocode").Descendants()
});
foreach (var el in xlist)
{
System.Diagnostics.Debug.WriteLine(string.Format("title: {0}, AreaDesc: {1}",
el.Title != null ? el.Title.Value : string.Empty,
el.AreaDesc != null ? el.AreaDesc.Value : string.Empty));
var geoCodeValues = el.GeocodeElements
.Where(o => o.Name == ns + "value").ToList();
var geoCodeValueNames = el.GeocodeElements
.Where(o => o.Name == ns + "valueName").ToList();
var pairs = geoCodeValueNames.Zip(geoCodeValues, (vn, v) =>
new Tuple<String, String>(vn.Value, v.Value)).ToList();
}
Note that in that last line I used Tuples instead of anonymous types because it wouldn't let me create an anonymous type that had two properties both named "Value". I expect this is only a start (I'm not sure how robust my code is--like what if not every value is paired to a valueName? etc), and there are probably other ways to approach this problem. I was just trying to get you closer to what I think you're trying to do.
Upvotes: 2