00001 #ifndef simplexml_SERIALIZER_H_INCLUDED
00002 #define simplexml_SERIALIZER_H_INCLUDED 1
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <s11n.net/s11n/io/data_node_format.hpp>
00012 #include <s11n.net/s11n/io/strtool.hpp>
00013
00014 #include <s11n.net/s11n/traits.hpp>
00015 #define MAGIC_COOKIE_SIMPLEXML "<!DOCTYPE s11n::simplexml>"
00016
00017 namespace s11n {
00018 namespace io {
00019
00020
00021
00022
00023
00024
00025
00026
00027 namespace sharing {
00028
00029
00030
00031 struct simplexml_sharing_context {};
00032 }
00033 typedef std::map<std::string,std::string> entity_translation_map;
00034
00035
00036
00037
00038 entity_translation_map & simplexml_serializer_translations();
00039
00040
00041
00042
00043 #define INDENT(LEVEL,ECHO) indent = ""; for( size_t i = 0; i < depth + LEVEL; i++ ) { indent += '\t'; if(ECHO) dest << '\t'; }
00044
00045
00046
00047
00048
00049
00050 template <typename NodeType>
00051 class simplexml_serializer : public tree_builder_lexer<NodeType,sharing::simplexml_sharing_context>
00052 {
00053 public:
00054 typedef NodeType node_type;
00055
00056 typedef simplexml_serializer<node_type> this_type;
00057 typedef tree_builder_lexer<node_type,sharing::simplexml_sharing_context> parent_type;
00058
00059 simplexml_serializer() : parent_type( "simplexml_data_nodeFlexLexer" ), m_depth(0)
00060 {
00061 this->magic_cookie( MAGIC_COOKIE_SIMPLEXML );
00062 }
00063
00064 virtual ~simplexml_serializer() {}
00065
00066
00067
00068
00069
00070 virtual const entity_translation_map & entity_translations() const
00071 {
00072 return simplexml_serializer_translations();
00073 }
00074
00075
00076
00077
00078
00079 virtual bool serialize( const node_type & src, std::ostream & dest )
00080 {
00081 try
00082 {
00083 return this->serialize_impl( src, dest );
00084 }
00085 catch(...)
00086 {
00087 this->m_depth = 0;
00088 throw;
00089 }
00090 return false;
00091 }
00092
00093 private:
00094
00095
00096
00097 bool serialize_impl( const node_type & src, std::ostream & dest )
00098 {
00099 typedef ::s11n::node_traits<node_type> NT;
00100 size_t depth = this->m_depth++;
00101 if ( 0 == depth )
00102 {
00103 dest << this->magic_cookie() << '\n';
00104 }
00105
00106
00107 std::string nname = NT::name(src);
00108 std::string impl = NT::class_name(src);
00109 std::string indent;
00110 const entity_translation_map & trans = this->entity_translations();
00111
00112 std::string ximpl = impl;
00113 ::s11n::io::strtool::translate( ximpl, trans, false );
00114
00115 INDENT(0,1);
00116 dest << "<" << nname << " s11n_class=\"" << ximpl << "\"";
00117
00118 std::string propval;
00119 std::string key;
00120
00121 typedef typename NT::property_map_type::const_iterator PropIT;
00122 PropIT it = NT::properties(src).begin();
00123 PropIT et = NT::properties(src).end();
00124 if ( it != et )
00125 {
00126 for ( ; it != et; ++it )
00127 {
00128 key = (*it).first;
00129 if ( key == std::string("CDATA") )
00130 continue;
00131 propval = (*it).second;
00132 ::s11n::io::strtool::translate_entities( propval, trans, false );
00133 dest << " " << key << "=\"" << propval << "\"";
00134 }
00135 }
00136
00137 bool use_closer = false;
00138 if ( NT::is_set( src, std::string("CDATA") ) )
00139 {
00140 dest << ">";
00141 use_closer = true;
00142 dest << "<![CDATA[" << NT::get( src, "CDATA", std::string("") ) << "]]>";
00143 }
00144
00145
00146 bool tailindent = false;
00147
00148 typedef typename NT::child_list_type CLT;
00149 typedef typename CLT::const_iterator CLIT;
00150 CLIT cit = NT::children(src).begin();
00151 CLIT cet = NT::children(src).end();
00152 if( cit != cet )
00153 {
00154 if( ! use_closer ) dest << '>';
00155 use_closer = true;
00156 tailindent = true;
00157 dest << '\n';
00158 for( ; cet != cit; ++cit )
00159 {
00160 this->serialize_impl( *(*cit), dest );
00161 }
00162 }
00163
00164 dest << ( tailindent ? indent : "" );
00165 if( use_closer )
00166 {
00167 dest << "</" << nname << '>';
00168 }
00169 else
00170 {
00171 dest << " />";
00172
00173 }
00174 dest << '\n';
00175
00176 if( 0 == depth )
00177 {
00178 dest.flush();
00179
00180 }
00181 --this->m_depth;
00182 return true;
00183 }
00184
00185
00186 private:
00187 size_t m_depth;
00188 };
00189
00190
00191 }
00192 }
00193 #undef INDENT
00194
00195 #endif // simplexml_SERIALIZER_H_INCLUDED