xmlwriter.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #if !defined(INCLUDED_XML_XMLWRITER_H)
00023 #define INCLUDED_XML_XMLWRITER_H
00024
00025 #include "convert.h"
00026 #include <vector>
00027 #include "xml/ixml.h"
00028
00029 class XMLEntityOutputStream {
00030 SingleCharacterOutputStream m_ostream;
00031 public:
00032 XMLEntityOutputStream(TextOutputStream& ostream)
00033 : m_ostream(ostream) {
00034 }
00035 void write(const char c) {
00036 m_ostream.write(c);
00037 }
00038 void writeEscaped(const char c) {
00039 switch (c) {
00040 case '<':
00041 write('&');
00042 write('l');
00043 write('t');
00044 write(';');
00045 break;
00046 case '>':
00047 write('&');
00048 write('g');
00049 write('t');
00050 write(';');
00051 break;
00052 case '"':
00053 write('&');
00054 write('q');
00055 write('u');
00056 write('o');
00057 write('t');
00058 write(';');
00059 break;
00060 case '&':
00061 write('&');
00062 write('a');
00063 write('m');
00064 write('p');
00065 write(';');
00066 break;
00067 default:
00068 write(c);
00069 break;
00070 }
00071 }
00072 std::size_t write(const char* buffer, std::size_t length) {
00073 const char*const end = buffer + length;
00074 for (const char* p = buffer; p != end; ++p) {
00075 writeEscaped(*p);
00076 }
00077 return length;
00078 }
00079 };
00080
00081 template<typename T>
00082 inline XMLEntityOutputStream& operator<<(XMLEntityOutputStream& ostream, const T& t) {
00083 return ostream_write(ostream, t);
00084 }
00085
00086
00087 class XMLStreamWriter : public XMLImporter, public XMLAttrVisitor {
00088 class state_t {
00089 public:
00090 enum EState {
00091 eStartElement,
00092 eContent,
00093 };
00094 state_t()
00095 : m_state(eStartElement) {}
00096 EState m_state;
00097 };
00098
00099 XMLEntityOutputStream m_ostream;
00100 std::vector<state_t> m_elements;
00101
00102 void write_cdata(const char* buffer, std::size_t length) {
00103 m_ostream << ConvertLocaleToUTF8(StringRange(buffer, buffer + length));
00104 }
00105 void write_string(const std::string& string) {
00106 m_ostream << string;
00107 }
00108 void write_quoted_string(const std::string& string) {
00109 m_ostream.write('"');
00110 m_ostream << string;
00111 m_ostream.write('"');
00112 }
00113 public:
00114 XMLStreamWriter(TextOutputStream& ostream)
00115 : m_ostream(ostream) {
00116 m_elements.push_back(state_t());
00117 m_elements.back().m_state = state_t::eContent;
00118 m_ostream.write('<');
00119 m_ostream.write('?');
00120 write_string("xml");
00121 visit("version", "1.0");
00122 m_ostream.write('?');
00123 m_ostream.write('>');
00124 }
00125
00126 void pushElement(const XMLElement& element) {
00127 if (m_elements.back().m_state == state_t::eStartElement) {
00128 m_elements.back().m_state = state_t::eContent;
00129 m_ostream.write('>');
00130 }
00131
00132 m_elements.push_back(state_t());
00133
00134 m_ostream.write('<');
00135 write_string(element.name());
00136 element.forEachAttribute(*this);
00137 }
00138 void popElement(const std::string& name) {
00139 if (m_elements.back().m_state == state_t::eStartElement) {
00140 m_ostream.write('/');
00141 m_ostream.write('>');
00142 m_elements.pop_back();
00143 } else {
00144 m_ostream.write('<');
00145 m_ostream.write('/');
00146 write_string(name);
00147 m_ostream.write('>');
00148 m_elements.pop_back();
00149 }
00150 }
00151 std::size_t write(const char* data, std::size_t length) {
00152 if (m_elements.back().m_state == state_t::eStartElement) {
00153 m_elements.back().m_state = state_t::eContent;
00154 m_ostream.write('>');
00155 }
00156 write_cdata(data, length);
00157 return length;
00158 }
00159
00160 void visit(const std::string& name, const std::string& value) {
00161 m_ostream.write(' ');
00162 write_string(name);
00163 m_ostream.write('=');
00164 write_quoted_string(value);
00165 }
00166 };
00167
00168
00169 #endif