C#循环遍历XML节点

5

我正在尝试将XML文件中的所有节点添加到listView中,但我做错了什么,即使查看了很多示例,也无法找出解决方法。这是XML片段:

<queue>
<slots>
<slot>
<status>Downloading</status>
<filename>file1</filename>
<size>1 GB</size>
</slot>
<slot>
<status>Downloading</status>
<filename>file2</filename>
<size>2 GB</size>
</slot>
</slots>
</queue>

这是代码:

        XDocument xDoc = XDocument.Load(xmlFilePath);

        List<Download> list = new List<Download>();

        foreach (var download in xDoc.Descendants("slots"))
        {
            string filename = download.Element("filename").Value;
            string size = download.Element("size").Value;
            string status = download.Element("status").Value;
            list.Add(new Download { Filename = filename, Size = size, Status = status });              
        }

一如既往地感谢您的帮助。

编辑:为了澄清,我在以下代码中遇到了NullReferenceException:

string filename = download.Element("filename").Value;

我知道ListView还没有完成,我还没有处理这一部分 :)


1
你是在使用WPF还是Winforms?我看到你正在创建一个列表。这个列表是如何绑定到listview的?还有什么问题吗?你是否遇到了异常?列表是否没有填充?listview中没有任何内容吗?Decendents中没有任何内容吗? - JMarsch
抱歉,我现在已经让它更加清晰了! - JoeBeez
1
请尝试使用 xDoc.Descendants("slots")。 - Oskar Kjellin
抱歉,Oskar,“slots”是导致空值错误的原因,“slot”只返回第一个下载。 - JoeBeez
"slot" 是正确的,看我的回答。 - Necros
3个回答

3
var list = (from download in xDoc.Descendats("slot")
            select new Download
                    {
                        Filename = (string) download.Element("filename"),
                        Size = (string) download.Element("size"),
                        Status = (string) download.Element("status")
                    }).ToList();

这看起来更好,由于你没有说清楚代码哪里出了问题,这大概是我能做的全部。

更新:我刚刚测试了一下,这个修复了你的异常。


非常准确,而且看起来更漂亮! - JoeBeez
通过忽略可能格式不正确的XML并插入文件名为空值,解决了NullReferenceException问题。 - Yuriy Faktorovich
@Yuriy,“NullReferenceException”是由于尝试将“filename”节点作为“slots”节点的元素访问,而不是“slot”节点的元素访问所导致的。您可以稍后处理缺失值(例如.Where(d => !string.IsNullOrEmpty(d.Filename)))。 - Necros
当然,如果他改了的话,但最初他使用的是slot - Yuriy Faktorovich

2
你的示例中的XML文件可以正常工作。NullReferenceException异常是因为你使用的实际XML文件在一个插槽中没有文件名元素。你可以使用以下代码来检查是否存在所需元素:
if (xmlDoc.Descendants("filename").Any())
string filename = download.Element("filename") == null ? 
    String.Empty : download.Element("filename").Value;

如果filename有可能出现默认值,那么可以使用instead。但更好的做法是正确地处理这个异常。


1
void LoadSlots()
{
  XmlDocument doc = new XmlDocument();
  doc.Load(Environment.CurrentDirectory + "\\queue.xml");

  XmlNodeList nodes = doc.SelectNodes("//queue/slots/slot");

  foreach (XmlNode node in nodes)
  {
    string filename = node.Attributes["filename"].InnerText;
    string size = node.Attributes["size"].InnerText;
    string status = node.Attributes["status"].InnerText;
    _slots.Add(filename, size, status);
  }
}

你为什么改用XmlDocument而不是XDocument?然后,文件名、大小和状态作为属性而不是最初发布的元素。然后有一个神秘的_slots,它是什么? - Yuriy Faktorovich
抱歉,我已经运行它并且它可以工作。请将“_slots”替换为“list”。我只是给它一个特定的名称,即“private List<QueueSlot> _slots = new List<QueueSlot>();”。 - JohnB
另一个打字错误,应该是_slots.Add(new QueueSlot(filename, size, status)); - JohnB
我用了老式的方法!虽然可能效率不高或者有其他问题。 - JohnB

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