2014-02-13 171 views
1

我正在從這個天氣鏈接「http://alerts.weather.gov/cap/us.php?x=0」解析這個XML。我發現了一個很好的示例代碼,它非常適合解析'tile'和'cap:event',但我需要解析'cap:geocode'並獲取其下的('value'&'valueName')元素列表。Linq to XML,用XNameSpace解析

<entry> 
    ... 
    <cap:geocode> 
<valueName>FIPS6</valueName> 
<value>002016</value> 
<valueName>UGC</valueName> 
<value>AKZ185</value> 
</cap:geocode> 
    ... 
</entry> 

這裏是我使用的代碼:

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; 
    } 
} 

當我運行的代碼中,el.Geocode元素包含空值。我不知道爲什麼它不給我價值。

這裏是weather.gov的XML:

 <?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> 

回答

2

我想你的第一個問題是,你缺少的命名空間中的代碼,這部分

val = gc.Element("value"), 
valName = gc.Element("valueName") 

我認爲你的第二個問題是您已將匿名類型的GeoCode屬性寫爲<cap:geocode>元素的列表,而您期望將其用作<cap:geocode>元素中valueName/value對的列表。至少這是我的假設。因此,這可能是更接近你想要什麼

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(); 
} 

注意,在最後一行我用元組,而不是匿名類型,因爲它不會讓我創建一個匿名類型有兩個屬性都命名爲「價值」 。我期望這只是一個開始(我不確定我的代碼是多麼健壯 - 比如,如果不是每個值都與valueName匹配,等等),並且可能有其他方法來解決這個問題。我只是想讓你更接近我認爲你想要做的事情。