rapidxml_print.hpp
Go to the documentation of this file.
00001 #ifndef RAPIDXML_PRINT_HPP_INCLUDED
00002 #define RAPIDXML_PRINT_HPP_INCLUDED
00003 
00004 // Copyright (C) 2006, 2009 Marcin Kalicinski
00005 // Version 1.13
00006 // Revision $DateTime: 2009/05/13 01:46:17 $
00008 
00009 #include "rapidxml.hpp"
00010 
00011 // Only include streams if not disabled
00012 #ifndef RAPIDXML_NO_STREAMS
00013     #include <ostream>
00014     #include <iterator>
00015 #endif
00016 
00017 namespace rapidxml
00018 {
00019 
00021     // Printing flags
00022 
00023     const int print_no_indenting = 0x1;   
00024 
00026     // Internal
00027 
00029     namespace internal
00030     {
00031         
00033         // Internal character operations
00034     
00035         // Copy characters from given range to given output iterator
00036         template<class OutIt, class Ch>
00037         inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
00038         {
00039             while (begin != end)
00040                 *out++ = *begin++;
00041             return out;
00042         }
00043         
00044         // Copy characters from given range to given output iterator and expand
00045         // characters into references (&lt; &gt; &apos; &quot; &amp;)
00046         template<class OutIt, class Ch>
00047         inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
00048         {
00049             while (begin != end)
00050             {
00051                 if (*begin == noexpand)
00052                 {
00053                     *out++ = *begin;    // No expansion, copy character
00054                 }
00055                 else
00056                 {
00057                     switch (*begin)
00058                     {
00059                     case Ch('<'):
00060                         *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
00061                         break;
00062                     case Ch('>'): 
00063                         *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
00064                         break;
00065                     case Ch('\''): 
00066                         *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
00067                         break;
00068                     case Ch('"'): 
00069                         *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
00070                         break;
00071                     case Ch('&'): 
00072                         *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); 
00073                         break;
00074                     default:
00075                         *out++ = *begin;    // No expansion, copy character
00076                     }
00077                 }
00078                 ++begin;    // Step to next character
00079             }
00080             return out;
00081         }
00082 
00083         // Fill given output iterator with repetitions of the same character
00084         template<class OutIt, class Ch>
00085         inline OutIt fill_chars(OutIt out, int n, Ch ch)
00086         {
00087             for (int i = 0; i < n; ++i)
00088                 *out++ = ch;
00089             return out;
00090         }
00091 
00092         // Find character
00093         template<class Ch, Ch ch>
00094         inline bool find_char(const Ch *begin, const Ch *end)
00095         {
00096             while (begin != end)
00097                 if (*begin++ == ch)
00098                     return true;
00099             return false;
00100         }
00101 
00103         // Internal printing operations
00104     
00105         // Print node
00106         template<class OutIt, class Ch>
00107         inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00108         {
00109             // Print proper node type
00110             switch (node->type())
00111             {
00112 
00113             // Document
00114             case node_document:
00115                 out = print_children(out, node, flags, indent);
00116                 break;
00117 
00118             // Element
00119             case node_element:
00120                 out = print_element_node(out, node, flags, indent);
00121                 break;
00122             
00123             // Data
00124             case node_data:
00125                 out = print_data_node(out, node, flags, indent);
00126                 break;
00127             
00128             // CDATA
00129             case node_cdata:
00130                 out = print_cdata_node(out, node, flags, indent);
00131                 break;
00132 
00133             // Declaration
00134             case node_declaration:
00135                 out = print_declaration_node(out, node, flags, indent);
00136                 break;
00137 
00138             // Comment
00139             case node_comment:
00140                 out = print_comment_node(out, node, flags, indent);
00141                 break;
00142             
00143             // Doctype
00144             case node_doctype:
00145                 out = print_doctype_node(out, node, flags, indent);
00146                 break;
00147 
00148             // Pi
00149             case node_pi:
00150                 out = print_pi_node(out, node, flags, indent);
00151                 break;
00152 
00153                 // Unknown
00154             default:
00155                 assert(0);
00156                 break;
00157             }
00158             
00159             // If indenting not disabled, add line break after node
00160             if (!(flags & print_no_indenting))
00161                 *out = Ch('\n'), ++out;
00162 
00163             // Return modified iterator
00164             return out;
00165         }
00166         
00167         // Print children of the node                               
00168         template<class OutIt, class Ch>
00169         inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00170         {
00171             for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
00172                 out = print_node(out, child, flags, indent);
00173             return out;
00174         }
00175 
00176         // Print attributes of the node
00177         template<class OutIt, class Ch>
00178         inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
00179         {
00180             for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
00181             {
00182                 if (attribute->name() && attribute->value())
00183                 {
00184                     // Print attribute name
00185                     *out = Ch(' '), ++out;
00186                     out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
00187                     *out = Ch('='), ++out;
00188                     // Print attribute value using appropriate quote type
00189                     if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
00190                     {
00191                         *out = Ch('\''), ++out;
00192                         out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
00193                         *out = Ch('\''), ++out;
00194                     }
00195                     else
00196                     {
00197                         *out = Ch('"'), ++out;
00198                         out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
00199                         *out = Ch('"'), ++out;
00200                     }
00201                 }
00202             }
00203             return out;
00204         }
00205 
00206         // Print data node
00207         template<class OutIt, class Ch>
00208         inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00209         {
00210             assert(node->type() == node_data);
00211             if (!(flags & print_no_indenting))
00212                 out = fill_chars(out, indent, Ch('\t'));
00213             out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
00214             return out;
00215         }
00216 
00217         // Print data node
00218         template<class OutIt, class Ch>
00219         inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00220         {
00221             assert(node->type() == node_cdata);
00222             if (!(flags & print_no_indenting))
00223                 out = fill_chars(out, indent, Ch('\t'));
00224             *out = Ch('<'); ++out;
00225             *out = Ch('!'); ++out;
00226             *out = Ch('['); ++out;
00227             *out = Ch('C'); ++out;
00228             *out = Ch('D'); ++out;
00229             *out = Ch('A'); ++out;
00230             *out = Ch('T'); ++out;
00231             *out = Ch('A'); ++out;
00232             *out = Ch('['); ++out;
00233             out = copy_chars(node->value(), node->value() + node->value_size(), out);
00234             *out = Ch(']'); ++out;
00235             *out = Ch(']'); ++out;
00236             *out = Ch('>'); ++out;
00237             return out;
00238         }
00239 
00240         // Print element node
00241         template<class OutIt, class Ch>
00242         inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00243         {
00244             assert(node->type() == node_element);
00245 
00246             // Print element name and attributes, if any
00247             if (!(flags & print_no_indenting))
00248                 out = fill_chars(out, indent, Ch('\t'));
00249             *out = Ch('<'), ++out;
00250             out = copy_chars(node->name(), node->name() + node->name_size(), out);
00251             out = print_attributes(out, node, flags);
00252             
00253             // If node is childless
00254             if (node->value_size() == 0 && !node->first_node())
00255             {
00256                 // Print childless node tag ending
00257                 *out = Ch('/'), ++out;
00258                 *out = Ch('>'), ++out;
00259             }
00260             else
00261             {
00262                 // Print normal node tag ending
00263                 *out = Ch('>'), ++out;
00264 
00265                 // Test if node contains a single data node only (and no other nodes)
00266                 xml_node<Ch> *child = node->first_node();
00267                 if (!child)
00268                 {
00269                     // If node has no children, only print its value without indenting
00270                     out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
00271                 }
00272                 else if (child->next_sibling() == 0 && child->type() == node_data)
00273                 {
00274                     // If node has a sole data child, only print its value without indenting
00275                     out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
00276                 }
00277                 else
00278                 {
00279                     // Print all children with full indenting
00280                     if (!(flags & print_no_indenting))
00281                         *out = Ch('\n'), ++out;
00282                     out = print_children(out, node, flags, indent + 1);
00283                     if (!(flags & print_no_indenting))
00284                         out = fill_chars(out, indent, Ch('\t'));
00285                 }
00286 
00287                 // Print node end
00288                 *out = Ch('<'), ++out;
00289                 *out = Ch('/'), ++out;
00290                 out = copy_chars(node->name(), node->name() + node->name_size(), out);
00291                 *out = Ch('>'), ++out;
00292             }
00293             return out;
00294         }
00295 
00296         // Print declaration node
00297         template<class OutIt, class Ch>
00298         inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00299         {
00300             // Print declaration start
00301             if (!(flags & print_no_indenting))
00302                 out = fill_chars(out, indent, Ch('\t'));
00303             *out = Ch('<'), ++out;
00304             *out = Ch('?'), ++out;
00305             *out = Ch('x'), ++out;
00306             *out = Ch('m'), ++out;
00307             *out = Ch('l'), ++out;
00308 
00309             // Print attributes
00310             out = print_attributes(out, node, flags);
00311             
00312             // Print declaration end
00313             *out = Ch('?'), ++out;
00314             *out = Ch('>'), ++out;
00315             
00316             return out;
00317         }
00318 
00319         // Print comment node
00320         template<class OutIt, class Ch>
00321         inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00322         {
00323             assert(node->type() == node_comment);
00324             if (!(flags & print_no_indenting))
00325                 out = fill_chars(out, indent, Ch('\t'));
00326             *out = Ch('<'), ++out;
00327             *out = Ch('!'), ++out;
00328             *out = Ch('-'), ++out;
00329             *out = Ch('-'), ++out;
00330             out = copy_chars(node->value(), node->value() + node->value_size(), out);
00331             *out = Ch('-'), ++out;
00332             *out = Ch('-'), ++out;
00333             *out = Ch('>'), ++out;
00334             return out;
00335         }
00336 
00337         // Print doctype node
00338         template<class OutIt, class Ch>
00339         inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00340         {
00341             assert(node->type() == node_doctype);
00342             if (!(flags & print_no_indenting))
00343                 out = fill_chars(out, indent, Ch('\t'));
00344             *out = Ch('<'), ++out;
00345             *out = Ch('!'), ++out;
00346             *out = Ch('D'), ++out;
00347             *out = Ch('O'), ++out;
00348             *out = Ch('C'), ++out;
00349             *out = Ch('T'), ++out;
00350             *out = Ch('Y'), ++out;
00351             *out = Ch('P'), ++out;
00352             *out = Ch('E'), ++out;
00353             *out = Ch(' '), ++out;
00354             out = copy_chars(node->value(), node->value() + node->value_size(), out);
00355             *out = Ch('>'), ++out;
00356             return out;
00357         }
00358 
00359         // Print pi node
00360         template<class OutIt, class Ch>
00361         inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00362         {
00363             assert(node->type() == node_pi);
00364             if (!(flags & print_no_indenting))
00365                 out = fill_chars(out, indent, Ch('\t'));
00366             *out = Ch('<'), ++out;
00367             *out = Ch('?'), ++out;
00368             out = copy_chars(node->name(), node->name() + node->name_size(), out);
00369             *out = Ch(' '), ++out;
00370             out = copy_chars(node->value(), node->value() + node->value_size(), out);
00371             *out = Ch('?'), ++out;
00372             *out = Ch('>'), ++out;
00373             return out;
00374         }
00375 
00376     }
00378 
00380     // Printing
00381 
00387     template<class OutIt, class Ch> 
00388     inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
00389     {
00390         return internal::print_node(out, &node, flags, 0);
00391     }
00392 
00393 #ifndef RAPIDXML_NO_STREAMS
00394 
00400     template<class Ch> 
00401     inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
00402     {
00403         print(std::ostream_iterator<Ch>(out), node, flags);
00404         return out;
00405     }
00406 
00411     template<class Ch> 
00412     inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
00413     {
00414         return print(out, node);
00415     }
00416 
00417 #endif
00418 
00419 }
00420 
00421 #endif


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:32:17