none
Iterate through each node in XML file using Xdocument

    Question

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

    Saturday, August 24, 2013 5:04 AM

All replies

  • 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 2:53 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 5:00 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

    Saturday, August 24, 2013 8:37 PM
  • Looks good, let me try it.  Thanks
    Sunday, August 25, 2013 2:30 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

    Sunday, August 25, 2013 6:04 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?

    • Edited by Shayaan Monday, August 26, 2013 2:39 AM
    Monday, August 26, 2013 1:25 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

    Monday, August 26, 2013 8:15 AM
  • Hi jdweng,

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

    Tuesday, August 27, 2013 10:21 PM
  • 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.

    Wednesday, September 04, 2013 7:22 AM