像往常一样,我使用下面的代码来获取 Alexa 越南排名,越南排名位于元素中:
<COUNTRY CODE="VN" NAME="Vietnam" RANK="20"/>
这里只有一个元素
<COUNTRY>
。
private int GetAlexaRank(string domain)
{
var alexaRank = 0;
try
{
var url = string.Format("http://data.alexa.com/data?cli=10&dat=snbamz&url={0}", domain);
var doc = XDocument.Load(url);
var vnrank = doc.Descendants("COUNTRY").Select(node => node.Attribute("RANK").Value).FirstOrDefault();// Vietnam Rank
if (!int.TryParse(vnrank, out alexaRank))
alexaRank = -1;
}
catch (Exception e)
{
return -1;
}
return alexaRank;
}
但在这种情况下,它有两个要素: 越南排名在第二个元素,我怎样才能得到它?
alexaRank = doc.Descendants("COUNTRY")
.Select(c => (int?)c.Attribute("RANK"))
.Where(r => r.HasValue)
.FirstOrDefault() ?? -1;
它是如何工作的:所有
COUNTRY
后代都是从 xml 响应中选择的(无论这些元素位于 xml 中的哪个位置)。然后,从每个国家/地区元素中,我们选择属性 RANK
并将该属性转换为可空整数。如果国家/地区没有排名属性或该属性的值,则给出 null
。然后我们从排名属性值中选择第一个或默认值。如果什么也没找到,那么它会给我们一个null
。使用空合并运算符 ??
,我们分配 -1
而不是 null
。如果找到某些内容,则可空整数的值将分配给alexaRank
。
因此,如果未找到国家/地区节点,或者没有具有排名属性的国家/地区节点(好吧,仅当排名不是整数时),您将不会在这里遇到解析异常。但您仍然可能会遇到其他异常,例如网络不可用时出现错误。所以,你可以把
try catch
留在这里。但不要吞下异常!你应该记录它。
您也可以使用 XPath:
private int GetAlexaRank(string domain)
{
try
{
var doc = XDocument.Load(url);
var country = xdoc.XPathSelectElement("//COUNTRY[@RANK]");
if (country == null)
return 0;
return (int)country.Attribute("RANK");
}
catch (Exception e)
{
// Log exception here!
return -1;
}
}