Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

xml_writer.cpp

Go to the documentation of this file.
00001 /*
00002 **  ClanLib SDK
00003 **  Copyright (c) 1997-2005 The ClanLib Team
00004 **
00005 **  This software is provided 'as-is', without any express or implied
00006 **  warranty.  In no event will the authors be held liable for any damages
00007 **  arising from the use of this software.
00008 **
00009 **  Permission is granted to anyone to use this software for any purpose,
00010 **  including commercial applications, and to alter it and redistribute it
00011 **  freely, subject to the following restrictions:
00012 **
00013 **  1. The origin of this software must not be misrepresented; you must not
00014 **     claim that you wrote the original software. If you use this software
00015 **     in a product, an acknowledgment in the product documentation would be
00016 **     appreciated but is not required.
00017 **  2. Altered source versions must be plainly marked as such, and must not be
00018 **     misrepresented as being the original software.
00019 **  3. This notice may not be removed or altered from any source distribution.
00020 **
00021 **  Note: Some of the libraries ClanLib link to may have additional
00022 **  requirements or restrictions.
00023 **
00024 **  File Author(s):
00025 **
00026 **    Magnus Norddahl
00027 */
00028 
00029 #include "precomp.h"
00030 #include "xml_writer.h"
00031 #include "xml_token_save.h"
00032 #include "string_help.h"
00033 #include "string_format.h"
00034 #include "xml_writer_generic.h"
00035 
00036 static std::string insert_escapes_fast(std::string str);
00037 
00039 // CL_XMLWriter construction:
00040 
00041 CL_XMLWriter::CL_XMLWriter()
00042 {
00043 }
00044 
00045 CL_XMLWriter::CL_XMLWriter(const CL_XMLWriter &copy) : impl(copy.impl)
00046 {
00047 }
00048 
00049 CL_XMLWriter::CL_XMLWriter(CL_IODevice *output, bool delete_output) : impl(new CL_XMLWriter_Generic)
00050 {
00051         impl->output = output;
00052         impl->delete_output = delete_output;
00053 }
00054 
00055 CL_XMLWriter::~CL_XMLWriter()
00056 {
00057 }
00058 
00060 // CL_XMLWriter attributes:
00061 
00062 bool CL_XMLWriter::get_insert_whitespace() const
00063 {
00064         return impl->insert_whitespace;
00065 }
00066 
00067 void CL_XMLWriter::set_insert_whitespace(bool enable)
00068 {
00069         impl->insert_whitespace = enable;
00070 }
00071 
00073 // CL_XMLWriter operations:
00074 
00075 void CL_XMLWriter::write(const CL_XMLTokenSave &token)
00076 {
00077         if (!impl) return;
00078 
00079         std::string str;
00080         switch (token.get_type())
00081         {
00082         case CL_XMLToken::NULL_TOKEN:
00083                 return; // should this throw exception instead?
00084                 
00085         case CL_XMLToken::ELEMENT_TOKEN:
00086                 if (token.get_variant() == CL_XMLToken::END)
00087                 {
00088                         str = cl_format("</%1>", insert_escapes_fast(token.get_name()));
00089                 }
00090                 else
00091                 {
00092                         str = cl_format("<%1", insert_escapes_fast(token.get_name()));
00093 
00094                         int size = token.get_attributes_number();
00095                         for (int i=0; i<size; i++)
00096                         {
00097                                 std::pair<std::string, std::string> attribute(token.get_attribute(i));
00098                                 str.append(cl_format(" %1=\"%2\"", insert_escapes_fast(attribute.first), insert_escapes_fast(attribute.second)));
00099                         }
00100 
00101                         if (token.get_variant() == CL_XMLToken::SINGLE)
00102                                 str.append("/>");
00103                         else
00104                                 str.append(">");
00105                 }
00106                 break;
00107                 
00108         case CL_XMLToken::TEXT_TOKEN:
00109                 str = insert_escapes_fast(token.get_value());
00110                 break;
00111                 
00112         case CL_XMLToken::CDATA_SECTION_TOKEN:
00113                 str = cl_format("<!CDATA[%1]]>", token.get_value());
00114                 break;
00115 
00116         case CL_XMLToken::COMMENT_TOKEN:
00117                 str = cl_format("<!--%1-->", token.get_value());
00118                 break;
00119 
00120         case CL_XMLToken::ENTITY_REFERENCE_TOKEN:
00121         case CL_XMLToken::ENTITY_TOKEN:
00122         case CL_XMLToken::PROCESSING_INSTRUCTION_TOKEN:
00123         case CL_XMLToken::DOCUMENT_TYPE_TOKEN:
00124         case CL_XMLToken::NOTATION_TOKEN:
00125                 return; // not implemented yet.
00126         }
00127 
00128         if (token.get_variant() == CL_XMLToken::END)
00129         {
00130                 impl->indent--;
00131         }
00132 
00133         if (impl->insert_whitespace)
00134         {
00135                 std::string indent_tabs(impl->indent, '\t');
00136                 impl->output->send(indent_tabs.data(), (int) indent_tabs.size());
00137         }
00138 
00139         impl->output->send(str.data(), (int) str.size());
00140 
00141         if (impl->insert_whitespace)
00142         {
00143 #ifdef WIN32
00144                 impl->output->send("\r\n", 2);
00145 #else
00146                 impl->output->send("\n", 2);
00147 #endif
00148         }
00149 
00150         if (token.get_variant() == CL_XMLToken::BEGIN)
00151         {
00152                 impl->indent++;
00153         }
00154 }
00155         
00157 // CL_XMLWriter implementation:
00158 
00159 static std::string insert_escapes_fast(std::string str)
00160 {
00161         static std::string const amp("&amp;");
00162         static std::string const quot("&quot;");
00163         static std::string const apos("&apos;");
00164         static std::string const lt("&lt;");
00165         static std::string const gt("&gt;");
00166 
00167         std::string::size_type pos = 0;
00168         while (pos < str.size())
00169         {
00170                 switch(str[pos])
00171                 {
00172                 case '&':
00173                         str.replace(pos, 1, amp);
00174                         pos += amp.size();
00175                         break;
00176                 case '\'':
00177                         str.replace(pos, 1, apos);
00178                         pos += apos.size();
00179                         break;
00180                 case '\"':
00181                         str.replace(pos, 1, quot);
00182                         pos += quot.size();
00183                         break;
00184                 case '<':
00185                         str.replace(pos, 1, lt);
00186                         pos += lt.size();
00187                         break;
00188                 case '>':
00189                         str.replace(pos, 1, gt);
00190                         pos += gt.size();
00191                         break;
00192                 default:
00193                         ++pos;
00194                         break;
00195                 }
00196         }
00197         return str;
00198 }

Generated on Sat Feb 19 22:51:16 2005 for npcore by  doxygen 1.4.1