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 typedef ::s11n::node_traits<node_type> NT;
00082 size_t depth = this->m_depth++;
00083 if ( 0 == depth )
00084 {
00085 dest << this->magic_cookie() << '\n';
00086 }
00087
00088
00089 std::string nname = NT::name(src);
00090 std::string impl = NT::class_name(src);
00091 std::string indent;
00092 const entity_translation_map & trans = this->entity_translations();
00093
00094 std::string ximpl = impl;
00095 ::s11n::io::strtool::translate( ximpl, trans, false );
00096
00097 INDENT(0,1);
00098 dest << "<" << nname << " s11n_class=\"" << ximpl << "\"";
00099
00100 std::string propval;
00101 std::string key;
00102
00103 typedef typename NT::property_map_type::const_iterator PropIT;
00104 PropIT it = NT::properties(src).begin();
00105 PropIT et = NT::properties(src).end();
00106 if ( it != et )
00107 {
00108 for ( ; it != et; ++it )
00109 {
00110 key = (*it).first;
00111 if ( key == std::string("CDATA") )
00112 continue;
00113 propval = (*it).second;
00114 ::s11n::io::strtool::translate_entities( propval, trans, false );
00115 dest << " " << key << "=\"" << propval << "\"";
00116 }
00117 }
00118
00119 bool use_closer = false;
00120 if ( NT::is_set( src, std::string("CDATA") ) )
00121 {
00122 dest << ">";
00123 use_closer = true;
00124 dest << "<![CDATA[" << NT::get( src, "CDATA", std::string("") ) << "]]>";
00125 }
00126
00127
00128 bool tailindent = false;
00129
00130 if( NT::children(src).end() != NT::children(src).begin() )
00131 {
00132 if( ! use_closer ) dest << '>';
00133 use_closer = true;
00134 tailindent = true;
00135 dest << '\n';
00136 std::for_each( NT::children(src).begin(),
00137 NT::children(src).end(),
00138 node_child_simple_formatter<this_type>( *this,
00139 dest,
00140 "",
00141 "" )
00142 );
00143 }
00144
00145 dest << ( tailindent ? indent : "" );
00146 if( use_closer )
00147 {
00148 dest << "</" << nname << '>';
00149 }
00150 else
00151 {
00152 dest << " />";
00153
00154 }
00155 dest << '\n';
00156
00157 if( 0 == depth )
00158 {
00159 dest.flush();
00160
00161 }
00162 --this->m_depth;
00163 return true;
00164 }
00165
00166
00167 private:
00168 size_t m_depth;
00169 };
00170
00171
00172 }
00173 }
00174 #undef INDENT
00175
00176 #endif // simplexml_SERIALIZER_H_INCLUDED