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

simplexml_serializer.h

00001 #ifndef simplexml_SERIALIZER_H_INCLUDED 00002 #define simplexml_SERIALIZER_H_INCLUDED 1 00003 00004 //////////////////////////////////////////////////////////////////////// 00005 // data_node_serializers.h: some file parsers for the s11n framework 00006 // 00007 // License: Public Domain 00008 // Author: stephan@s11n.net 00009 //////////////////////////////////////////////////////////////////////// 00010 00011 #define MAGIC_COOKIE_SIMPLEXML "<!DOCTYPE s11n::simplexml>" 00012 00013 namespace s11n { 00014 namespace io { 00015 00016 00017 /*** 00018 The sharing namespace defines some "sharing contexts" 00019 for use with s11n::phoenix. They are used to 00020 provide contexts in which disparate framework components 00021 can share data. 00022 */ 00023 namespace sharing { 00024 /** 00025 Sharing context used by simplexml_serializer. 00026 */ 00027 struct simplexml_sharing_context {}; 00028 } 00029 typedef std::map<std::string,std::string> entity_translation_map; 00030 00031 /** 00032 The entity translations map used by simplexml_serializer. 00033 */ 00034 entity_translation_map & simplexml_serializer_translations(); 00035 00036 00037 00038 // TAB() is a helper macro for some serializers. 00039 #define TAB(LEVEL,ECHO) indent = ""; for( size_t i = 0; i < depth + LEVEL; i++ ) { indent += '\t'; if(ECHO) dest << '\t'; } 00040 00041 /** 00042 De/serializes objects from/to a simple XML grammar, 00043 with properties stored as XML attibutes and children 00044 stored as subnodes. 00045 */ 00046 template <typename NodeType> 00047 class simplexml_serializer : public tree_builder_lexer<NodeType,sharing::simplexml_sharing_context> 00048 { 00049 public: 00050 typedef NodeType node_type; 00051 00052 typedef simplexml_serializer<node_type> this_type; // convenience typedef 00053 typedef tree_builder_lexer<node_type,sharing::simplexml_sharing_context> parent_type; // convenience typedef 00054 00055 simplexml_serializer() : parent_type( "simplexml_data_nodeFlexLexer" ), m_depth(0) 00056 { 00057 this->magic_cookie( MAGIC_COOKIE_SIMPLEXML ); 00058 } 00059 00060 virtual ~simplexml_serializer() {} 00061 00062 /** 00063 Reimplemented to return this type's entity 00064 translation map. 00065 */ 00066 virtual const entity_translation_map & entity_translations() const 00067 { 00068 return simplexml_serializer_translations(); 00069 } 00070 00071 00072 /** 00073 Writes src out to dest. 00074 */ 00075 virtual bool serialize( const node_type & src, std::ostream & dest ) 00076 { 00077 size_t depth = this->m_depth++; 00078 if ( 0 == depth ) 00079 { 00080 dest << this->magic_cookie() << '\n'; 00081 } 00082 00083 00084 std::string nname = src.name(); 00085 std::string impl = src.impl_class(); 00086 std::string indent; 00087 const entity_translation_map & trans = this->entity_translations(); 00088 00089 std::string ximpl = impl; 00090 s11n::translate_entities( ximpl, trans, false ); 00091 00092 TAB(0,1); 00093 dest << "<" << nname << " s11n_class=\"" << ximpl << "\""; 00094 00095 std::string propval; 00096 std::string key; 00097 00098 typename node_type::const_iterator it = src.begin(), et = src.end(); 00099 if ( it != et ) 00100 { 00101 for ( ; it != et; ++it ) 00102 { 00103 if ( "CDATA" == ( *it ).first ) 00104 continue; // special treatment later on 00105 key = (*it).first; 00106 propval = (*it).second; 00107 s11n::translate_entities( propval, trans, false ); 00108 dest << " " << key << "=\"" << propval << "\""; 00109 } 00110 } 00111 00112 bool use_closer = false; // if false then an element can <close_itself /> 00113 if ( src.is_set( "CDATA" ) ) 00114 { 00115 dest << ">"; 00116 use_closer = true; 00117 dest << "<![CDATA[" << src.get_string( "CDATA" ) << "]]>"; 00118 } 00119 00120 00121 bool tailindent = false; 00122 00123 if( src.children().end() != src.children().begin() ) 00124 { 00125 if( ! use_closer ) dest << '>'; 00126 use_closer = true; 00127 tailindent = true; 00128 dest << '\n'; 00129 std::for_each( src.children().begin(), 00130 src.children().end(), 00131 node_child_simple_formatter<this_type>( *this, 00132 dest, 00133 "", 00134 "" ) 00135 ); 00136 } 00137 00138 dest << ( tailindent ? indent : "" ); 00139 if( use_closer ) 00140 { 00141 dest << "</" << nname << '>'; 00142 } 00143 else 00144 { 00145 dest << " />"; 00146 } 00147 dest << '\n'; 00148 00149 if( 0 == depth ) 00150 { 00151 dest.flush(); 00152 // if we don't do this then the client is possibly forced to flush() the stream :/ 00153 } 00154 --this->m_depth; 00155 return true; 00156 } 00157 00158 00159 private: 00160 size_t m_depth; 00161 }; 00162 00163 00164 } // namespace io 00165 } // namespace s11n 00166 #undef TAB 00167 00168 #endif // simplexml_SERIALIZER_H_INCLUDED

Generated on Wed Jul 28 16:04:15 2004 for s11n by doxygen 1.3.7