Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested foreach loop reading .xml and writing object to list

I have a method that executes upon form_load event that seems to work properly omitting one line.

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

The AddContact method adds the Employee object to a static list; however, the line:

this.AddContact(ccontact);

was not being executed.

A sample of the XML file:

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

I had tried setting a breakpoint and debugging, and sure enough, the line was skipped over completely as if it were not even there.

As per Alan's advice, I changed the PersonTag.FirstChild.Value as it was attempting to reference a ChildNode that did not exist.

The updated, working method:

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;
}
like image 598
randomusername Avatar asked Oct 05 '22 16:10

randomusername


2 Answers

You can easily parse your xml with LINQ to 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 solution:

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);
}
like image 130
Sergey Berezovskiy Avatar answered Oct 10 '22 00:10

Sergey Berezovskiy


Are you sure you're not just hitting an exception? Wrap your logic in a try/catch and see if it hits.

Lines like this can cause null reference exceptions and may be the reason you're not hitting that line of code:

PersonTag.FirstChild.Value

I would imagine calling it on FirstChild on Employee, FirstName, or LastName would return null, since they contain no child node.

Perhaps try:

PersonTag.InnerText
like image 20
alan Avatar answered Oct 10 '22 01:10

alan