Skip to content

Instantly share code, notes, and snippets.

@apfeltee
Created July 17, 2016 05:16
Show Gist options
  • Save apfeltee/20d942f503067671026517fd28aae2bb to your computer and use it in GitHub Desktop.
Save apfeltee/20d942f503067671026517fd28aae2bb to your computer and use it in GitHub Desktop.
Primitive XML/HTML writer in plain C++, modeled after javascript.
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <vector>
class Element
{
public:
using AttrMap = std::map<std::string, std::string>;
public:
static std::string htmlquote(const std::string& val)
{
return val;
}
private:
std::string m_tag;
std::stringstream m_inline;
AttrMap m_attributes;
std::vector<Element> m_elements;
public:
Element(const Element& old)
{
m_tag = old.m_tag;
m_inline << old.m_inline.str();
m_attributes = old.m_attributes;
for(auto it=old.m_elements.begin(); it!=old.m_elements.end(); it++)
{
m_elements.push_back(*it);
}
}
Element(const std::string& tname): m_tag(tname)
{
}
Element(const std::string& tname, const std::string& txt): m_tag(tname)
{
text() << txt;
}
Element createElement(const std::string& tname) const
{
return Element(tname);
}
Element createElement(const std::string& tname, const std::string& txt)
{
return Element(tname, txt);
}
Element& setAttribute(const std::string& key, const std::string& val)
{
m_attributes[key] = val;
return *this;
}
Element& appendChild(const Element& elm)
{
m_elements.push_back(elm);
return *this;
}
std::vector<Element> children() const
{
return m_elements;
}
std::string toXML() const
{
std::stringstream obuf;
obuf << "<" << m_tag;
if(m_attributes.size() > 0)
{
obuf << " ";
for(auto attrit=m_attributes.begin(); attrit!=m_attributes.end(); attrit++)
{
auto& key = attrit->first;
auto& value = attrit->second;
obuf << key << "=\"" << htmlquote(value) << "\"";
if(attrit != (--(m_attributes.end())))
{
obuf << " ";
}
}
}
obuf << ">";
for(auto it=m_elements.begin(); it!=m_elements.end(); it++)
{
auto& elm = *it;
obuf << elm.toXML();
}
if(hasText())
{
obuf << "</" << m_tag << ">";
}
return obuf.str();
}
bool hasText() const
{
return (
(m_inline.str().size() > 0) ||
(m_elements.size() > 0)
);
}
std::string text() const
{
return m_inline.str();
}
std::stringstream& text()
{
return m_inline;
}
};
int main()
{
Element doc("html");
auto form = doc.createElement("form");
auto input = doc.createElement("input");
auto submit = doc.createElement("submit");
form.setAttribute("action", "/bin/submit.cgi");
input.setAttribute("name", "fr_uname").setAttribute("type", "text");
submit.setAttribute("type", "submit").setAttribute("value", "Go!");
form.appendChild(input).appendChild(submit);
doc.appendChild(form);
std::cout << doc.toXML() << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment