Video of the week

This is a must-watch video about one of us trying to reach the stars :-)

Well done #HRejterzy

Reading XML files using XmlTextReader and XPathNavigator

XML file is a good way to provide simple configuration file in our project. I have created so far few WCF service configs and decided to use this format as constant. First I am going to create basic XML file using Microsoft XML Notepad - available here.

  1. <?xml version="1.0" encoding="utf-8" ?>
  2.  
  3. <config>
  4. <modules>
  5.  
  6. <module>
  7. <name>module 1</name>
  8. <path>/bin</path>
  9. </module>
  10.  
  11. <module>
  12. <name>module 2</name>
  13. <path>/bin</path>
  14. </module>
  15.  
  16. </modules>
  17. </config>

Why XML file? In my opinion (not only mine) - there's much less work to handle with these file than writing our own classes to cope with our *.dat files. Furthermore You probably have noticed that Microsoft uses these files as default format as config files for example in Visual Studio. Ok, so I created first mini project where I introduced XmlTextReader class:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Xml;
  6.  
  7. namespace XMLDemo
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. XmlTextReader xtr = null;
  14. try
  15. {
  16. xtr = new XmlTextReader(@"H:\demo.xml");
  17. }
  18. catch (Exception e)
  19. {
  20. Console.WriteLine(e.Message);
  21. Console.ReadLine();
  22. return;
  23. }
  24.  
  25. Console.WriteLine("Press Enter to read elements from demo.xml file.");
  26. Console.ReadLine();
  27. while (xtr.Read())
  28. {
  29. if (xtr.NodeType == XmlNodeType.Element)
  30. {
  31. Console.WriteLine("Element: " + xtr.Name);
  32. }
  33. }
  34.  
  35. Console.WriteLine();
  36. xtr.Close();
  37.  
  38. xtr = new XmlTextReader(@"H:\demo.xml");
  39.  
  40. Console.WriteLine("Press Enter to read values from demo.xml file.");
  41. Console.ReadLine();
  42. while (xtr.Read())
  43. {
  44. if (xtr.NodeType == XmlNodeType.Text)
  45. {
  46. Console.WriteLine("Value: " + xtr.Value);
  47. }
  48. }
  49.  
  50. xtr.Close();
  51. Console.ReadLine();
  52. }
  53. }
  54. }

I passed path to the constructor of XmlTextReader and put this instruction in try catch block just in case. The below code seems to be the most important:

  1. while (xtr.Read())
  2. {
  3. if (xtr.NodeType == XmlNodeType.Element)
  4. {
  5. Console.WriteLine("Element: " + xtr.Name);
  6. }
  7. }

 

Read method goes through all nodes only in one direction - it measn, we cannot go back! We have no file pointer here to rewind it and set at the beginning to read file again. This code lists only names of the elements - root, first child (first child), .., second node (first child), .. etc.

 

elements

Ok, now we want to get particular values from nodes - in this case we wanna know everything about added modules to our configuration file. We can see after preceding while that we have another while, which provides us this information:

elements

Ok, now we want to change the way we manage xml files - we want to read as well as have ability to read once again without closing xml file. But how?

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Xml;
  6. using System.Xml.XPath;
  7.  
  8. namespace XMLDemo
  9. {
  10. class Program
  11. {
  12. static void Main(string[] args)
  13. {
  14. XmlDocument xdoc = null;
  15. try
  16. {
  17. xdoc = new XmlDocument();
  18. xdoc.Load(@"H:\demo.xml");
  19. }
  20. catch (Exception e)
  21. {
  22. Console.WriteLine(e.Message);
  23. Console.ReadLine();
  24. return;
  25. }
  26.  
  27. XPathNavigator nav = xdoc.CreateNavigator();
  28.  
  29. Console.WriteLine("Press Enter to read values from demo.xml file.");
  30. Console.ReadLine();
  31.  
  32. nav.MoveToFirstChild(); // <config>
  33. nav.MoveToFirstChild(); // <modules>
  34. nav.MoveToFirstChild(); // <module>
  35.  
  36. Console.WriteLine("Value: " + nav.Value);
  37. while (nav.MoveToNext())
  38. {
  39. Console.WriteLine("Value: " + nav.Value);
  40. }
  41.  
  42. Console.ReadLine();
  43. }
  44. }
  45. }

The base concept here is to associate XmlDocument object with XPathNavigator. This class allows us to move through xml file in easy way. Look how many MoveTo* method is included in XPathNavigator class:

moveto