Click here to Skip to main content
Click here to Skip to main content

Simple C++ class for XML writing

By , 4 Dec 2003
 

Introduction

In some of my programs, I have to write the data in XML format. Only writing: reading and parsing is the mission of some other tools. Actually I only have to write the simple plain text with some specific markup.

For these purposes, I have implemented a simple class, which behaves as usual std::stream, but also track all the needed XML markings. The class implementation is very simple and template-based. One may write to XmlStream, everything that can be written into std::ostream. The tags and attributes are declared by special helper functions.

Using the code

Look at the example below, which tells everything about my class (I specially omitted the implementation of the XmlStream class, if you’ve interest in it, you'll download the source code, I think).

ofstream f("sample.xml");
XmlStream xml(f);

xml << prolog() // write XML file declaration
  << tag("sample-tag") // root tag

    << tag("some-tag") // child tag
      << attr("int-attribute") << 123
      << attr("double-attribute") << 456.789
      << chardata() << "This is the text"
    << endtag() // close current tag

    << tag("empty-self-closed-tag") // sibling of <some-tag>
    << endtag()

    << tag() << "computed-name-tag"
      << attr("text-attr") << "a bit of text"
    << endtag()

    << tag("deep-tag") // deep enclosing
      << tag("sub-tag-2")
        << tag("sub-tag-3")
    << endtag("deep-tag"); // close all tags up to specified

// you don't worry about closing all open tags!

As you can see, writing of XML became a very simple procedure. XmlStream delegates all the incoming data to a specified std::ostream (std::ofstream in the example above) except for the tags and attributes declarations, which are issued by helper functions: tag(), endtag(), attr(), chardata() and prolog(). To fill attribute values and tag character data, one should use standard stream operations. If object of some class can be written into std::ostream, it's automatically writeable into my XmlStream. This feature is released by template operator<<, which mostly calls standard streaming operations.

template<class t> XmlStream& operator<<(const t& value) {
  // for computed-name tags we have to remember written data
  if (stateTagName == state)
    // tagName is object of std::ostringstream class
    tagName << value;
  // now call specified std::stream which
  // performs actual output  
  s << value;
  return *this;
}

The final executable contains only those implementations of this operator, which corresponds to actually used data types.

Advantages of my approach

  • Writing of XML data is very fast (almost as fast as plain text writing).
  • You use standard and well-known functions to build the content of the XML document. It's simple to implement new operator's supporting any user classes.
  • The source code, which writes XML data, represents itself the structure of the resulting document.
  • XmlStream is a really tiny class! Almost all of its work is placed in one overloaded operator<<.

Disadvantages

  • All the data are written into XML "as is", without any encoding (UTF-8, UTF-16 etc.). In my tasks, it's often not a matter of headache, because my data are simply either Latin alphas or numbers. But for the common case, one may have to implement special std::ostream (in fact: std::streambuf) successor, which will perform the encoding work.
  • XmlStream does not check if output XML data represent well-formed XML document. Programmer must check himself whether the tag and attribute names are valid and there are no special characters (like angle brackets) in the attribute values and character data.

Futures

The current version of XmlWriter is used in my programs, which outputs the results of the scientific calculations in XML format. If someone wants to improve this simple class, he may first get rid of disadvantages mentioned above. Also he might change the processing of the tags to make output XML documents more human-readable (i.e. add line separators, padding etc).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Oboltus
Web Developer
Russian Federation Russian Federation
Member
Programming since 1992
Favorite programming language: C++
Main interest (currently): computer modeling of physical processes in radiation-damaged metalls

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalxmlwriter detailsmemberBernd Speiser11 Sep '05 - 7:16 
This class could be of great help in one of my projects (http://echempp.sourceforge.net) for saving the state of various objects in a file. Indeed, it's easy to use.
 
However, I have one comment and two questions:
 
(1) One has to use namespace xmlw, which is perfectly ok. But maybe it could be added to the documentation so that users don't have to look up the source.
 
(2) My compiler (gcc, v. 3.3.5) complains (warns) that two switch statements (line 109, line 162) in the source of xmlwriter do not test for the default case. Since I have for the rest of my calculations the compiler set to treat warnings as errors, this is fatal. I have added two lines
 
default:
;
 
in each case. OK?
 
(3) The xml source after the prolog is written in one big line, which makes it hard to read. Some structured output with added spaces would be much nicer to look at (for example if someone wants to edit the xml file). However, something like
 
XmlStream x (stream);
x << std::endl;
 
does not work.
Is there any possibility to get line breaks into the xml file without changing the source?

Bernd
QuestionUnicode?memberAbu Mami11 Mar '05 - 1:40 
Hi, has anyone succeeded in using this to write Unicode files? Seems like wofstream makes this impossible - is that assumption correct?
 
Thanks.
GeneralUse conditionsmemberdmaximov22 Apr '04 - 21:48 
What about use conditions of this class?
May I use it in commercial projects?

GeneralRe: Use conditionsmemberOboltus26 Apr '04 - 23:05 
Absolutely free Smile | :)

GeneralRe: Use conditionsmemberdmaximov27 Apr '04 - 18:29 
Thanks.
Generalread XMLmemberblablakam28 Jan '04 - 4:41 
You XML writer worked so fast. Very good.
Thank you!
 
Whould you be so kind to to write( or to tip me)
with the possiblty to read the same XML file.
 
Thank You agn.
Eek! | :eek:
GeneralRead XML!memberM.Khadem18 Dec '03 - 0:59 
your code can be very usefuller than now if it can read xmls in this simple way.isn't it? Smile | :)
GeneralXML ReadermemberNagesh P10 Dec '03 - 23:49 
Really, its great class. It helped me a lot.
Anather small Request...
Have you written XMLReader the same way as of XML writer?.
I have one which does lot of file operations. It is not feasiable one.
So I request you, If you have XML reader, Please send it to me.
Thank you
Nagesh
 
The great ideas come Once you share them....
GeneralRe: XML ReadermemberOboltus11 Dec '03 - 0:02 
I didn't yet think about reading XML sources via std::iostream operations.
GeneralMicrosoft XMLDOM interfacememberNadiaTariq10 Dec '03 - 1:02 
Hi,
I am not really sure whether MSXML DOM Interface would do the same fairly easy and efficiently what you are trying to achieve.Let me know if you are targetting at something else.Very easy to follow your class no doubt.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 5 Dec 2003
Article Copyright 2003 by Oboltus
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid