Skip to content

Instantly share code, notes, and snippets.

@sebclaeys
Created September 19, 2011 21:19
Show Gist options
  • Save sebclaeys/1227644 to your computer and use it in GitHub Desktop.
Save sebclaeys/1227644 to your computer and use it in GitHub Desktop.
Light weight C++ XML writer
#include "xml_writer.hpp"
#include <iostream>
int main()
{
Writer writer(std::cout);
writer.openElt("Movies");
writer.openElt("Goldeneye").attr("date", "1998").content("This is a James Bond movie").endElt();
writer.openElt("Leon").attr("director", "Luc Besson");
writer.openElt("Actor").attr("role", "Leon").attr("name", "Jean Reno").endAll();
std::cout << std::endl;
}
#ifndef XML_WRITER_HPP
# define XML_WRITER_HPP
# define HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
# define INDENT " "
# define NEWLINE "\n"
# include <string>
# include <stack>
# include <iostream>
class Writer
{
public:
Writer(std::ostream& os) : os(os), tag_open(false), new_line(true) {os << HEADER;}
~Writer() {}
Writer& openElt(const char* tag) {
this->closeTag();
if (elt_stack.size() > 0)
os << NEWLINE;
this->indent();
this->os << "<" << tag;
elt_stack.push(tag);
tag_open = true;
new_line = false;
return *this;
}
Writer& closeElt() {
this->closeTag();
std::string elt = elt_stack.top();
this->elt_stack.pop();
if (new_line)
{
os << NEWLINE;
this->indent();
}
new_line = true;
this->os << "</" << elt << ">";
return *this;
}
Writer& closeAll() {
while (elt_stack.size())
this->closeElt();
}
Writer& attr(const char* key, const char* val) {
this->os << " " << key << "=\"";
this->write_escape(val);
this->os << "\"";
return *this;
}
Writer& attr(const char* key, std::string val) {
return attr(key, val.c_str());
}
Writer& content(const char* val) {
this->closeTag();
this->write_escape(val);
return *this;
}
private:
std::ostream& os;
bool tag_open;
bool new_line;
std::stack<std::string> elt_stack;
inline void closeTag() {
if (tag_open)
{
this->os << ">";
tag_open = false;
}
}
inline void indent() {
for (int i = 0; i < elt_stack.size(); i++)
os << (INDENT);
}
inline void write_escape(const char* str) {
for (; *str; str++)
switch (*str) {
case '&': os << "&amp;"; break;
case '<': os << "&lt;"; break;
case '>': os << "&gt;"; break;
case '\'': os << "&apos;"; break;
case '"': os << "&quot;"; break;
default: os.put(*str); break;
}
}
};
#endif /* !XML_WRITER_HPP */
@fraillt
Copy link

fraillt commented Mar 1, 2019

Missing return *this; in closeAll()
:)

@g-h-c
Copy link

g-h-c commented Oct 7, 2019

in main(): endElt() and endAll() should be closeElt() and closeAll()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment