嵌套 foreach 循环读取 .xml 并将对象写入列表

Posted

技术标签:

【中文标题】嵌套 foreach 循环读取 .xml 并将对象写入列表【英文标题】:Nested foreach loop reading .xml and writing object to list 【发布时间】:2012-12-01 20:58:48 【问题描述】:

我有一个在 form_load 事件上执行的方法,它似乎可以正常工作,省略一行。

private int ReadInPeople()

    XmlNodeList nodeList = m_xmlDoc.DocumentElement.ChildNodes;
    foreach (XmlNode PersonNode in nodeList)
    
        Employee ccontact = new Employee();
        foreach (XmlNode PersonTag in PersonNode.ChildNodes)
        
            switch (PersonTag.Name)
            
                case "Employee":
                    ccontact.EmployeeNumber = PersonTag.FirstChild.Value;
                    break;
                case "FirstName":
                    ccontact.FirstName = PersonTag.FirstChild.Value;
                    break;
                case "LastName":
                    ccontact.LastName = PersonTag.FirstChild.Value;
                    break;
                default:
                    break;
            
        
        this.AddContact(ccontact);
    
    return nodeList.Count;

AddContact 方法将 Employee 对象添加到静态列表中;但是,该行:

this.AddContact(ccontact);

没有被执行。

XML 文件示例:

<?xml version="1.0" encoding="utf-8"?>
<people>
  <person>
    <Employee>123456789</Employee>
    <FirstName>John</FirstName>
    <LastName>Smith</LastName>
  </person>
  <person>
    <Employee>987654321</Employee>
    <FirstName>Ellen</FirstName>
    <LastName>Wayne</LastName>
  </person>
</people>

我曾尝试设置断点和调试,果然,该行被完全跳过,就好像它甚至不存在一样。

根据 Alan 的建议,我更改了 PersonTag.FirstChild.Value,因为它试图引用一个不存在的 ChildNode。

更新的工作方法:

private int ReadInPeople()

    XmlNodeList nodeList = m_xmlDoc.DocumentElement.ChildNodes;
    foreach (XmlNode PersonNode in nodeList)
    
        Employee ccontact = new Employee();
        foreach (XmlNode PersonTag in PersonNode.ChildNodes)
        
            switch (PersonTag.Name)
            
                case "Employee":
                    ccontact.EmployeeNumber = PersonTag.InnerText;
                    break;
                case "FirstName":
                    ccontact.FirstName = PersonTag.InnerText;
                    break;
                case "LastName":
                    ccontact.LastName = PersonTag.InnerText;
                    break;
                default:
                    break;
            
        
        this.AddContact(ccontact);
    
    return nodeList.Count;

【问题讨论】:

AddContact 方法是否标有System.Diagnostics.ConditionalAttribute @eulerfx - 我不知道 - 有没有办法验证? 转到该方法的定义,看看它是否标有该属性。 @eulerfx - 它没有标记该属性。 - 我什至可以将问题行代码更改为简单的代码,例如:myContacts.Add(ccontact),但它仍然被跳过。 【参考方案1】:

您确定您不只是遇到异常吗?将你的逻辑包装在 try/catch 中,看看它是否成功。

这样的行可能会导致空引用异常,并且可能是您没有点击该行代码的原因:

PersonTag.FirstChild.Value

我想在 Employee、FirstName 或 LastName 的 FirstChild 上调用它会返回 null,因为它们不包含子节点。

或许可以试试:

PersonTag.InnerText

【讨论】:

我将每个 PersonTag.FirstChild.Value 切换为 Persontag.Value,现在调试器遇到了问题 - 但正在解析的值现在为空。 然而,你把我推上了正确的道路!我将它们更新为 PersonTag.InnerText 以搜索文本而不是 Child,一切都很好。谢谢!【参考方案2】:

您可以使用 LINQ to XML 轻松解析您的 xml:

XDocument xdoc = XDocument.Load(path_to_xml);   
var employees = xdoc.Descendants("person")
                    .Select(p => new Employee()
                    
                        FirstName = (string)p.Element("FirstName"),
                        LastName = (string)p.Element("LastName"),
                        EmployeeNumber = (long)p.Element("Employee")
                    );

foreach (var ccontact in employees)
    this.AddContact(ccontact);

XmlDocument 解决方案:

XmlNodeList nodeList = m_xmlDoc.DocumentElement.SelectNodes("person");
foreach (XmlNode PersonNode in nodeList)

    Employee ccontact = new Employee();
    ccontact.LastName = PersonNode["LastName"].InnerText;
    ccontact.FirstName = PersonNode["FirstName"].InnerText;
    ccontact.EmployeeNumber = PersonNode["Employee"].InnerText;
    this.AddContact(ccontact);

【讨论】:

+1。这是一个更好的解决方案。如果您直接在后代上循环而不是先进行查询,它会变得更简单.. @OlivierJacot-Descombes 谢谢!多年前我曾通过 XmlDocument 进行 xml 解析,但现在在我们得到 Linq to Xml 后,我看不到任何使用它的理由 :) 我首先进行查询的原因是解析和应用业务逻辑的分离(添加给联系人).. 但是是的,代码可以更紧凑:) 是的,System.Xml.Linq 有一个更简单直接的对象模型可供使用。 @lazyberezovsky - +1.. 我更喜欢 Linq to Xml 解决方案;但是,我的老师希望我们使用 XmlDocument 进行解析。它似乎没有任何原因不能按原样工作。 @lazyberezovsky - 感谢您的建议。我已经用有效的解决方案更新了问题 - XmlDocument 很挑剔。【参考方案3】:

Build -&gt; Rebuild Solution?

众所周知,它有时会有所帮助。

或者:Debug -&gt; Exceptions... -&gt; Thrown

【讨论】:

以上是关于嵌套 foreach 循环读取 .xml 并将对象写入列表的主要内容,如果未能解决你的问题,请参考以下文章

打破 foreach C#

是否可以在没有嵌套循环的情况下读取整个 XML 文件

xml节点foreach循环

PowerShell 中的嵌套 ForEach()

每个循环的 XML 节点读取

我想在c#中使用foreach循环一一读取具有特定json对象数组的json文件数据