JUL
28
2007

Writing XML

One should think that reading and writing XML are solved problems. But interestingly there still is heavy development going on in this area. So Trolltech includes their new QXmlStreamReader and QXmlStreamWriter classes since Qt 4.3, which was released less than two months ago. Today I used these classes for the first time and was delighted. This is the first XML API which lives up to the high standard of Qt.

The QXmlStreamReader is a streaming pull parser. That's a great approach because it's easier to use than the SAX parser and is more efficient than using a DOM tree. But for now let's concentrate on writing XML.

The QXmlStreamWriter is the counterpart to QXmlStreamReader. If you look at its API you might think: "That's it?" But it really is that simple. Why did we have to live with hand-crafted XML output via printf, QTextStream or similar awkwardnesses for all the years? One simple example to illustrate how nicely XML can now be written with Qt:


  QXmlStreamWriter xml( &file );
  
  xml.writeStartDocument();

  xml.writeStartElement( "toothache" );

  foreach( Meal *meal, food ) {
    xml.writeStartElement( "candy" );

    xml.writeEmptyElement( "chocolate" );
    xml.writeAttribute( "count", QString::number( meal->chocolateCount() ) );
    
    xml.writeEmptyElement( "softdrinks" );
    xml.writeAttribute( "count", QString::number( meal->softdrinkCount() ) );
  
    xml.writeEndElement();
  }
  
  xml.writeEndDocument();

This writes something like:


  
    
      
      
    
    
      
      
    
  

One slight annoyance is the need to convert integers to strings manually for the XML attributes. This could be made more convenient by providing some overloaded functions. Or did I miss something?

The most elegant way I know to write XML still is the Ruby XML Builder, though. This fully uses the dynamic nature of Ruby and allows to write amazingly intuitive code like the following example which is equivalent to the Qt code above:


xml = Builder::XmlMarkup.new :target => $stdout

xml.instruct!

xml.toothache do
  food.each do |meal|
    xml.candy do
      xml.chocolate :count => meal.chocolate_count
      xml.softdrinks :count => meal.softdrink_count
    end
  end
end

I tried to write something which comes close to the Ruby XML Builder in Kode with my XmlBuilder class, but in C++ it simply is not possible to reach the elegance of Ruby for this use case.

Anyway, it is great to see that even in presumaby simple areas like XML writing there still is progress in the software world. The future is bright ;-)