如何使用C#解析XML字符串

3

我正在尝试将XML字符串解析为列表,但结果计数始终为零。

 string result = "";
            string address = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";

            // Create the web request  
            HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;

            // Get response  
            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                // Get the response stream  
                StreamReader reader = new StreamReader(response.GetResponseStream());

                // Read the whole contents and return as a string  
                result = reader.ReadToEnd();
            }

            XDocument doc = XDocument.Parse(result);

            var ListCurr = doc.Descendants("Cube").Select(curr => new CurrencyType() 
                    { Name = curr.Element("currency").Value, Value = float.Parse(curr.Element("rate").Value) }).ToList();

我想知道我做错了什么。


@BassamAlugili:这真的不是那个问题的重复。 - Jon Skeet
@Manish 我已经将它移除并投票给了你!当Jon回答一个问题时,那肯定是一个好问题!谢谢! - Bassam Alugili
2个回答

5
问题在于您正在寻找没有命名空间的元素,而XML文件中根元素包含了命名空间。
xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"

这个指定了任何元素的默认命名空间。此外,Cube元素内的currencyrate属性,它们不是子元素。

所以你想要像这样:

XNamespace ns = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";
var currencies = doc.Descendants(ns + "Cube")
                    .Select(c => new CurrencyType {
                                     Name = (string) c.Attribute("currency"),
                                     Value = (decimal) c.Attribute("rate")
                                 })
                    .ToList(); 

请注意,由于我将currency属性转换为string,对于没有指定该属性的任何货币,您最终会得到一个空的Name属性。如果您想跳过这些元素,则可以在Select之前或之后使用Where子句来实现。
此外,请注意,我已将Value的类型更改为decimal而不是float——您不应该使用float来处理与货币相关的值。(有关更多详细信息,请参见此问题。)
另外,您应该考虑使用XDocument.Load来加载XML。
XDocument doc = XDocument.Load(address);

那么就不需要自己创建WebRequest等内容了。

1
感谢您告诉我关于XDocument doc = XDocument.Load(address); - Manish
@Manish:我现在已经编辑过它,使用decimal而不是float - 请注意我的评论,因为如果当前线程文化使用,作为小数分隔符,则无法按原样工作。 - Jon Skeet

2
XDocument doc = XDocument.Parse(result);
XNamespace ns = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";

var ListCurr = doc.Descendants(ns + "Cube")
                    .Where(c=>c.Attribute("currency")!=null) //<-- Some "Cube"s do not have currency attr.
                    .Select(curr => new CurrencyType  
                    { 
                        Name = curr.Attribute("currency").Value, 
                        Value = float.Parse(curr.Attribute("rate").Value) 
                    })
                    .ToList();

2
最好是解释一下问题,而不仅仅是发布代码。我还建议使用强制转换而不是 float.Parse - 这段代码在使用逗号作为小数分隔符的文化中会失败。 - Jon Skeet
1
@JonSkeet 您说得对,但您已经解释得非常清楚了。 - I4V

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接