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 Tue Oct 26 18:25:59 2004 for s11n by  doxygen 1.3.9.1