Parse xml using C# and print path to each element

Code:

using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Stack elements = new Stack();
StringBuilder output = new StringBuilder();
//Example string
String xmlString =
@”<bookstore>
<book genre=’autobiography’ publicationdate=’1981-03-22′ ISBN=’1-861003-11-0′>
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Franklin</last-name>
</author>
<price>8.99</price>
</book>
</bookstore>”;

// Replace the path if you have an xml file
// XmlTextReader reader = new XmlTextReader(“D:\\Example.xml”);
XmlReader reader = XmlReader.Create(new StringReader(xmlString));
while(reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
elements.Push(reader.Name);
}
if (reader.NodeType == XmlNodeType.EndElement)
{
//Console.WriteLine(currentElement);
if (reader.Name == elements.Peek())
{
Console.WriteLine(elements.Peek() + “:” + PrintValues(elements));
elements.Pop();
}
}

}
Console.ReadLine();
}
public static String PrintValues(IEnumerable myCollection)
{
Stack reverse = new Stack();
String value = “”;
foreach (Object obj in myCollection)
reverse.Push(obj.ToString());
foreach (String values in reverse)
value += values+”/”;
return value;
}
}
}

Output:

title:bookstore/book/title/
first-name:bookstore/book/author/first-name/
last-name:bookstore/book/author/last-name/
author:bookstore/book/author/
price:bookstore/book/price/
book:bookstore/book/
bookstore:bookstore/

 

Advertisements

9 thoughts on “Parse xml using C# and print path to each element

  1. This is really helpfull.
    But can you please get the same output by parsing a complex xml having elements with same and attributes and using Dictionary to store elements/attributes and their paths rather than stack?

    Thanks in advance.

    1. Here I am using stack only to check the end of xmlnode element, For you to store the elements in dictionary, you just need to create a dictionary and replace Console.WriteLine() with Dictionary add methods

      1. Hey Mohith, We can do that but in dictionary the key should be unique rigth!
        But in our xml we can have elements with same name, so the condition of unique key fails.

      2. Haa, nice question by the way. For this you can have a counter that increments when you navigate to next set of books in the example above.

  2. This is my program

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Xml;
    using System.Xml.XPath;
    using System.Xml.Linq;

    namespace NewWindows
    {
    class DicPath
    {
    public string getDicPath(XmlNode node)
    {
    string path = node.Name;
    XmlNode searchNode = null;

    while ((searchNode = node.ParentNode).NodeType != XmlNodeType.Document)
    {
    path = searchNode.Name + “/” + path;
    node = searchNode;
    }
    return “/” + path;
    }
    }

    class Program
    {
    DicPath dp = new DicPath();

    public void AddToDictionary(XmlNodeList nodes)
    {
    Dictionary dictionary = new Dictionary();
    string dicPath = string.Empty;
    int num = 1;

    foreach (XmlNode node in nodes)
    {
    string dicKey = node.LocalName;
    string dicKey1 = string.Empty;

    if (dictionary.ContainsKey(dicKey))
    {
    string ancestor = Convert.ToString(node.ParentNode.LocalName);
    dicKey1 = ancestor+”.”+dicKey + “_” + num;

    dicPath = dp.getDicPath(node);
    dictionary.Add(dicKey1, dicPath);

    if (node.PreviousSibling != null)
    {
    if (node.LocalName.Equals(node.PreviousSibling.LocalName))
    {
    num++;
    }
    }
    Console.WriteLine(dicKey1+” “+dicPath);
    }
    else
    {
    num = 1;
    dicPath = dp.getDicPath(node);
    dictionary.Add(dicKey, dicPath);
    Console.WriteLine(dicKey+” “+dicPath);
    }
    }
    Console.ReadLine();
    }

    static void Main(string[] args)
    {
    Program program = new Program();

    string path = @”D:\EmployeeDetails.xml”;
    XmlDocument doc = new XmlDocument();
    doc.Load(path);

    XmlNodeList nodes = doc.SelectNodes(“//*”);
    program.AddToDictionary(nodes);
    }
    }
    }

    And here is the Xml File

    550
    950
    82%

    Lara

    560
    955
    80%

    Mary

    If my child nodes are repeating I want them to store as parentNode.childNode_num, but if I have the same parent and child combination i’m getting an error because i’m unable to retrieve parentNode_num which is stored in the dictionary.
    I want that to be stored as parentNode_num.childNode_num

    1. The approach you have used is pretty complex, instead use the approach like how I have used in my program I’ll tell u in more detail how to deal it simple:
      Use stack to push all XMLnodes, eg:bookstore then once u find pop it out from stack (you need to push and pop all children also) once stack is empty then increment num (num++) now store it in dictionary using that num.
      I think now u can get it, use my program written and implement logic for num++ and create a dictionary and add the XML nodes to dictionary.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s