xmlwriter.h

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2001-2006, William Joseph.
00003 All Rights Reserved.
00004 
00005 This file is part of GtkRadiant.
00006 
00007 GtkRadiant is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 GtkRadiant is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GtkRadiant; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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

Generated by  doxygen 1.6.2