Easy XML reading using XmlTextReader

When looking at examples and samples for the .NET System.Xml.XmlTextReader, i was hoping it would be as easy to use as XmlTextWriter. But i did not find such examples.

XmlTextReader will read node per node, using the method Read, and a programmer will have to evaluate what type of node the current node is. But XmlTextReader has two short-hand methods: ReadStartElement and ReadElementString.

Suppose we have the following xml :

 <root>
   <itemlist>
     <item> 
       <name>Item1</name> 
       <value>110</value>
     </item>
     <item>
       <name>Item2</name>
       <value>234</value>
     </item>
     <item>
       <name>Another Item</name>
       <value>432</value> 
     </item> 
   </itemlist>
 </root>

What we want to do is read one item in a simple way. That is possible as follows:

 private void ReadItem(XmlTextReader reader, out String name, out String value) { reader.ReadStartElement("item"); name = reader.ReadElementString("name") ; value = reader.ReadElementString("value"); reader.ReadEndElement(); //item } 

Unfortunately ReadStartElement will throw an exception if the current element is not the same as the wanted element. So we need a bit more code to iterate smartly over all possibilities.

private void ReadItemList(XmlTextReader reader) 
{ 
    reader.ReadStartElement("itemlist"); 
    reader.Read(); 
    // read next element 
    while (reader.LocalName == "item") 
    { 
        String name; 
        String value; 
        ReadItem(reader, out name, out value) ; 
        // ... do something here with read item ... 
        reader.Read(); 
    } 
    reader.ReadEndElement(); // itemlist 
}

The reader.Read() positions ourself on the next node, allowing some kind of look-ahead, while the ReadEndElement and ReadStartElement can handle this perfectly well. They will either proceed to the next node, or stay on the current node. That's why this code works. For completeness, this does the setup:

XmlTextReader importReader = new XmlTextReader(fileName); 
importReader.ReadStartElement("root"); 
ReadItemList(importReader); 
importReader.ReadEndElement(); 

... where filename points to the file containing the above shown xml.

If you have any questions or comments regarding this example, please let me know.

This allows for very readable and concise code, but only if you know how the xml file you are reading is formed (the order of the elements). I will solve this in the next post.


Comments
Matt Baker 2017-08-31 15:24:00 UTC

Not sure this works... String listname in ReadItemList is never used.

nathanvda 2017-08-31 15:54:47 UTC

Yes you are right. This code was extracted from a project where we had a lot of different named "itemlists", so the listname was a parameter. I have corrected the code to remove the parameter (as it is not relevant for this example). WTF this is ancient :P :P

Add comment

Recent comments

Tags

ruby on rails 34 ruby 26 rails3 17 rails 15 oracle 11 rspec 9 rspec2 7 jquery 7 ubuntu 5 javascript 5 windows 5 activerecord 3 refactoring 3 geoserver 3 gis 3 arrrrcamp 3 actionmailer 2 oracle spatial 2 tdd 2 postgis 2 routing 2 rvm 2 mongoid 2 csharp 2 thin 2 win32 2 gem 2 rails4 2 git 2 service 2 haml 2 cucumber 2 view testing 2 i18n 1 displaysleep 1 spatial 1 gemsets 1 wubi 1 oracle_enhanced_adapter 1 migrations 1 watchr 1 ci 1 plugins 1 coderetreat 1 ie8 1 ssl 1 oci 1 nested model form 1 wcf 1 11.04 1 jsonp 1 ruby-oci8 1 teamcity 1 engines 1 pgadmin 1 soap 1 content_for 1 word automation 1 plugin 1 capybara 1 xml 1 bootstrap 1 migrate to rails3 1 mvc 1 unity 1 rendering 1 word2007 1 x64 1 limited stock 1 fast tests 1 pl/sql 1 delayed_job 1 pdf 1 test coverage 1 optimization 1 processing 1 borland 1 method_missing 1 cross-browser 1 devise 1 schema_plus 1 mongo 1 mongrel 1 dual boot 1 usability 1 mongrel_service 1 dba 1 mission statement 1 model 1 metadata 1 rcov 1 exceptions 1 image_tag 1 attachments 1 bde 1 css 1 yield 1 ajax 1 generative art 1 rails-assets 1 coordinate systems 1 submodules 1 netzke 1 ora-01031 1 authlogic 1 postgresql 1 shopping cart 1 agile 1 fast_tagger 1 subjective 1 wice_grid 1 generators 1 nvidia 1 mongodb 1 etsyhacks 1 staleobjecterror 1 session 1 jeweler 1 wordpress hacked 1 jasmine 1 heroku 1 rjs 1 life 1 unobtrusive-javascript 1 render_anywhere 1 html5 1 rails31 1 json 1 cocoon 1 mingw32 1 observe_field 1 osx 1 actionwebservice 1 testing 1 debugging 1 strings 1