Share via


Iterate through each node in XML file using Xdocument

Question

Saturday, August 24, 2013 5:04 AM

How do I loop through each node in the following xml file in a way that can be parsed/formatted in a case statement as

If no child (e.g.   <RegDate>, <Location> etc) then create a 2-dimensional array "MyArray1" containing the element name and the value.

If a node is like <SchoolType> then create a 2-dimensional array "MyArray2" containing the element name and the value.

If a node is like <CourseSelection> then iterate through each <subject> and create a 2-dimensional array "MyArray3" containing the element name and the value.

<School xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    <SchoolType>
        <School></School>
        <Dept></Dept>
        <Level></Level>
        <Degree>Masters</Degree>
        <Other></Other>
        <SchoolType></SchoolType>
    </SchoolType>
    <RegDate>01-02-2013</RegDate>
    <Location>Chicago</Location>
    <CourseType>
        <CourseType-A></CourseType-A>
        <CourseType-B>Science</CourseType-B>
        <CourseType-C>Art</CourseType-C>
        <CourseType-D></CourseType-D>
    </CourseType>
    <CourseSelection>
        <Subject>
            <Instructor>
                <FName>Brad</FName>
                <LName>Pitt</LName>
                <MName>na</MName>
            </Instructor>
            <Instructor>
                <FName>Robert</FName>
                <LName>Downey</LName>
                <MName>x</MName>
            </Instructor>
            <InstructorCount>2</InstructorCount>
            <InstructorMessage></InstructorMessage>
        </Subject>
    </CourseSelection>
    <Undecided>true</Undecided>
    <StartDate>02-03-2013</StartDate>
    <ApprovedBy>Tom Cruise</ApprovedBy>
</School >

All replies (9)

Saturday, August 24, 2013 2:53 PM

See if the code below helps.  I used an enumeration to create 3 types.  then enumeration was needed so I could use a Case Statement.

1) Nodes with multiple Descendants

2) Nodes with one level of Decendants

3) Nodes with no Descendants

I put the XML data into a tree using my own custom class that contains dictionaries.  Each level of the tree is a dictionary with the key being a sting and the value being one of the following

1) Another class which are the children

2) Another class that contains one class or a List of class.  Your input had more than one instructor so I made a List of Insturctors.  Each Instructor has it own dictionary.

3) An Attirbute

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Xml;using System.Xml.Linq;namespace ConsoleApplication1{    class Program    {        static string input =             "<School xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +             "<SchoolType>\n" +             "<School></School>\n" +             "<Dept></Dept>\n" +             "<Level></Level>\n" +             "<Degree>Masters</Degree>\n" +             "<Other></Other>\n" +             "<SchoolType></SchoolType>\n" +             "</SchoolType>\n" +             "<RegDate>01-02-2013</RegDate>\n" +             "<Location>Chicago</Location>\n" +             "<CourseType>\n" +             "<CourseType-A></CourseType-A>\n" +             "<CourseType-B>Science</CourseType-B>\n" +             "<CourseType-C>Art</CourseType-C>\n" +             "<CourseType-D></CourseType-D>\n" +             "</CourseType>\n" +             "<CourseSelection>\n" +             "<Subject>\n" +            "<Instructor>\n" +            "  <FName>Brad</FName>\n" +            " <LName>Pitt</LName>\n" +            " <MName>na</MName>\n" +            "</Instructor>\n" +            "<Instructor>\n" +            "  <FName>Robert</FName>\n" +            "   <LName>Downey</LName>\n" +            "   <MName>x</MName>\n" +            "</Instructor>\n" +            "<InstructorCount>2</InstructorCount>\n" +            "<InstructorMessage></InstructorMessage>\n" +            "</Subject>\n" +            "</CourseSelection>\n" +            "<Undecided>true</Undecided>\n" +            "<StartDate>02-03-2013</StartDate>\n" +            "<ApprovedBy>Tom Cruise</ApprovedBy>\n" +            "</School >";        class MyElement        {            public NodeTypes type;            public Dictionary<string, object> elements;        }                enum NodeTypes        {            HasChildren,            IsNode,            IsAttribute            }        static void Main(string[] args)        {            XDocument doc = new XDocument();            doc = XDocument.Parse(input);            MyElement tree = new MyElement();            SpanXDocument(tree, doc.Root);        }        static void SpanXDocument(MyElement node, XElement elements)        {            NodeTypes nodeType;                   foreach (XElement element in elements.Elements())            {                if (node.elements == null)                {                    node.elements = new Dictionary<string, object>();                }                if (element.Descendants().Count() > 0)                {                    if (element.Descendants().Descendants().Count() > 0)                    {                        nodeType = NodeTypes.HasChildren;                    }                    else                    {                        nodeType = NodeTypes.IsNode;                    }                }                else                {                    nodeType = NodeTypes.IsAttribute;                }                switch (nodeType)                {                    case NodeTypes.HasChildren:                        MyElement newChild = new MyElement();                        newChild.type = NodeTypes.HasChildren;                        node.elements.Add(element.Value, newChild);                        SpanXDocument(newChild, element);                        break;                    case NodeTypes.IsNode:                        MyElement newNode = new MyElement();                        newNode.type = NodeTypes.IsNode;                        newNode.elements = new Dictionary<string, object>();                        //types like instructor can contain on e or mor eitems                        //when more than one must make a list                        if (node.elements.ContainsKey(element.Name.LocalName))                        {                            List<MyElement> ListElements = null;                            if (node.elements[element.Name.LocalName].GetType() == typeof(MyElement))                            {                                //only one exists, change to a List<Dictionary>                                MyElement oldElement = (MyElement)node.elements[element.Name.LocalName];                                //create a list                                ListElements = new List<MyElement>();                                ListElements.Add(oldElement);                                node.elements[element.Name.LocalName] = ListElements;                            }                            else                            {                                ListElements = (List<MyElement>)node.elements[element.Name.LocalName];                            }                                                       //add to a list of Myelement                            MyElement newElement = new MyElement();                            newElement.type = NodeTypes.IsNode;                            foreach (XElement elementNode in element.Elements())                            {                                    newNode.elements.Add(elementNode.Name.LocalName, elementNode.Value);                            }                            ListElements.Add(newElement);                                                  }                        else                        {                            //add to a dictionary                            node.elements.Add(element.Name.LocalName, newNode);                            foreach (XElement elementNode in element.Elements())                            {                                newNode.elements.Add(elementNode.Name.LocalName, elementNode.Value);                            }                        }                                                break;                    case NodeTypes.IsAttribute:                        node.elements.Add(element.Name.LocalName, element.Value);                         break;                }            }        }            }        }

jdweng


Saturday, August 24, 2013 5:00 PM

Thanks, but its a bit completed code for me.

I have seen a code somewhere a while code that used "if..else" statement to parse through the xml.

My goal is to identify each node if they contain children or not.  If a node does not have a child then I just need to read the node value, otherwise, get the node name of the node containing child/children.


Saturday, August 24, 2013 8:37 PM

I simplified the code to the bare minimum.  See if you like htis better

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Xml;using System.Xml.Linq;namespace ConsoleApplication1{    class Program    {        static string input =             "<School xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +             "<SchoolType>\n" +             "<School></School>\n" +             "<Dept></Dept>\n" +             "<Level></Level>\n" +             "<Degree>Masters</Degree>\n" +             "<Other></Other>\n" +             "<SchoolType></SchoolType>\n" +             "</SchoolType>\n" +             "<RegDate>01-02-2013</RegDate>\n" +             "<Location>Chicago</Location>\n" +             "<CourseType>\n" +             "<CourseType-A></CourseType-A>\n" +             "<CourseType-B>Science</CourseType-B>\n" +             "<CourseType-C>Art</CourseType-C>\n" +             "<CourseType-D></CourseType-D>\n" +             "</CourseType>\n" +             "<CourseSelection>\n" +             "<Subject>\n" +            "<Instructor>\n" +            "  <FName>Brad</FName>\n" +            " <LName>Pitt</LName>\n" +            " <MName>na</MName>\n" +            "</Instructor>\n" +            "<Instructor>\n" +            "  <FName>Robert</FName>\n" +            "   <LName>Downey</LName>\n" +            "   <MName>x</MName>\n" +            "</Instructor>\n" +            "<InstructorCount>2</InstructorCount>\n" +            "<InstructorMessage></InstructorMessage>\n" +            "</Subject>\n" +            "</CourseSelection>\n" +            "<Undecided>true</Undecided>\n" +            "<StartDate>02-03-2013</StartDate>\n" +            "<ApprovedBy>Tom Cruise</ApprovedBy>\n" +            "</School >";        enum NodeTypes        {            HasChildren,            IsNode,            IsAttribute        }        static void Main(string[] args)        {            XDocument doc = new XDocument();            doc = XDocument.Parse(input);                        SpanXDocument(doc.Root);        }        static void SpanXDocument(XElement elements)        {            NodeTypes nodeType;            foreach (XElement element in elements.Elements())            {                if (element.Descendants().Count() > 0)                {                    if (element.Descendants().Descendants().Count() > 0)                    {                        nodeType = NodeTypes.HasChildren;                    }                    else                    {                        nodeType = NodeTypes.IsNode;                    }                }                else                {                    nodeType = NodeTypes.IsAttribute;                }                switch (nodeType)                {                    case NodeTypes.HasChildren:                        Console.WriteLine("Has Children Name : {0}",                           element.Name.LocalName);                        SpanXDocument(element);                        break;                    case NodeTypes.IsNode:                        Console.WriteLine("Node Name : {0}",                           element.Name.LocalName);                        foreach (XElement elementNode in element.Elements())                        {                            Console.WriteLine("Node Attribute Name : {0} Value : {1}",                               elementNode.Name.LocalName, elementNode.Value);                        }                        break;                     case NodeTypes.IsAttribute:                        Console.WriteLine("Attribute Name : {0} Value : {1}",                               element.Name.LocalName, element.Value);                        break;                }            }        }    }}

jdweng


Sunday, August 25, 2013 2:30 AM

Looks good, let me try it.  Thanks


Sunday, August 25, 2013 6:04 AM

The original code I pust the results into tree structure with a dictionaries at each branch (dictionary<string, object>) to make it simply to lookup data.  the 2nd code I simply removed the tree and dictionaries.  The code got a little complicated because some Nodes (like instructor) had duplicte keys so I have to create a list object.

jdweng


Monday, August 26, 2013 1:25 AM

How do I modify the second code so it will create a 2-dimensional array (Key, Value) for <Instructor>?

Also, my XML is a file (MyXML.xml); how do I pass it as an input file to parse?


Monday, August 26, 2013 8:15 AM

Here are the answers

1) How do I modify the second code so it will create a 2-dimensional array (Key, Value) for <Instructor>?

Answer : The code below will create a dictionary of the objects below instructor.  If you are trying to add more than one instructor to a dictionary then you need to make a List<> object of the instructors like in my original code like (Key, List<string, string>)

2)

Also, my XML is a file (MyXML.xml); how do I pass it as an input file to parse?

Answer : Use Load() instead of Parse().  See below

XDocument doc = new XDocument();

doc = XDocument.Load(@"c:\temp\abc.xml");

 

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Xml;using System.Xml.Linq;namespace ConsoleApplication1{    class Program    {        static string input =             "<School xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +             "<SchoolType>\n" +             "<School></School>\n" +             "<Dept></Dept>\n" +             "<Level></Level>\n" +             "<Degree>Masters</Degree>\n" +             "<Other></Other>\n" +             "<SchoolType></SchoolType>\n" +             "</SchoolType>\n" +             "<RegDate>01-02-2013</RegDate>\n" +             "<Location>Chicago</Location>\n" +             "<CourseType>\n" +             "<CourseType-A></CourseType-A>\n" +             "<CourseType-B>Science</CourseType-B>\n" +             "<CourseType-C>Art</CourseType-C>\n" +             "<CourseType-D></CourseType-D>\n" +             "</CourseType>\n" +             "<CourseSelection>\n" +             "<Subject>\n" +            "<Instructor>\n" +            "  <FName>Brad</FName>\n" +            " <LName>Pitt</LName>\n" +            " <MName>na</MName>\n" +            "</Instructor>\n" +            "<Instructor>\n" +            "  <FName>Robert</FName>\n" +            "   <LName>Downey</LName>\n" +            "   <MName>x</MName>\n" +            "</Instructor>\n" +            "<InstructorCount>2</InstructorCount>\n" +            "<InstructorMessage></InstructorMessage>\n" +            "</Subject>\n" +            "</CourseSelection>\n" +            "<Undecided>true</Undecided>\n" +            "<StartDate>02-03-2013</StartDate>\n" +            "<ApprovedBy>Tom Cruise</ApprovedBy>\n" +            "</School >";        enum NodeTypes        {            HasChildren,            IsNode,            IsAttribute        }        static void Main(string[] args)        {            XDocument doc = new XDocument();            doc = XDocument.Parse(input);            SpanXDocument(doc.Root);        }        static void SpanXDocument(XElement elements)        {            NodeTypes nodeType;            foreach (XElement element in elements.Elements())            {                if (element.Descendants().Count() > 0)                {                    if (element.Descendants().Descendants().Count() > 0)                    {                        nodeType = NodeTypes.HasChildren;                    }                    else                    {                        nodeType = NodeTypes.IsNode;                    }                }                else                {                    nodeType = NodeTypes.IsAttribute;                }                switch (nodeType)                {                    case NodeTypes.HasChildren:                        Console.WriteLine("Has Children Name : {0}",                           element.Name.LocalName);                        SpanXDocument(element);                        break;                    case NodeTypes.IsNode:                        Console.WriteLine("Node Name : {0}",                           element.Name.LocalName);                        Dictionary<string, string> attributes = new Dictionary<string, string>();                        foreach (XElement elementNode in element.Elements())                        {                            attributes.Add(elementNode.Name.LocalName, elementNode.Value);                            Console.WriteLine("Node Attribute Name : {0} Value : {1}",                               elementNode.Name.LocalName, elementNode.Value);                        }                        break;                    case NodeTypes.IsAttribute:                        Console.WriteLine("Attribute Name : {0} Value : {1}",                           element.Name.LocalName, element.Value);                        break;                }            }        }    }}

jdweng


Tuesday, August 27, 2013 10:21 PM

Hi jdweng,

If I use your original code; how do I read keys and values so for nodes containing child/children?


Wednesday, September 4, 2013 7:22 AM

Hi Shayaan,

  Welcome to MSDN Forum Support.

  Depend on NodeTypes.HasChildren to judge it has children node or not.

  Sincerely,

  Jason Wang

<THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
Thanks
MSDN Community Support

Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.