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         template<class OutIt, class Ch>
00105         inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent);
00106         template<class OutIt, class Ch>
00107         inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
00108         template<class OutIt, class Ch>
00109         inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
00110         template<class OutIt, class Ch>
00111         inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
00112         template<class OutIt, class Ch>
00113         inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
00114         template<class OutIt, class Ch>
00115         inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
00116         template<class OutIt, class Ch>
00117         inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
00118         template<class OutIt, class Ch>
00119         inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
00120 
00121 
00122         // Print node
00123         template<class OutIt, class Ch>
00124         inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00125         {
00126             // Print proper node type
00127             switch (node->type())
00128             {
00129 
00130             // Document
00131             case node_document:
00132                 out = print_children(out, node, flags, indent);
00133                 break;
00134 
00135             // Element
00136             case node_element:
00137                 out = print_element_node(out, node, flags, indent);
00138                 break;
00139 
00140             // Data
00141             case node_data:
00142                 out = print_data_node(out, node, flags, indent);
00143                 break;
00144 
00145             // CDATA
00146             case node_cdata:
00147                 out = print_cdata_node(out, node, flags, indent);
00148                 break;
00149 
00150             // Declaration
00151             case node_declaration:
00152                 out = print_declaration_node(out, node, flags, indent);
00153                 break;
00154 
00155             // Comment
00156             case node_comment:
00157                 out = print_comment_node(out, node, flags, indent);
00158                 break;
00159 
00160             // Doctype
00161             case node_doctype:
00162                 out = print_doctype_node(out, node, flags, indent);
00163                 break;
00164 
00165             // Pi
00166             case node_pi:
00167                 out = print_pi_node(out, node, flags, indent);
00168                 break;
00169 
00170                 // Unknown
00171             default:
00172                 assert(0);
00173                 break;
00174             }
00175 
00176             // If indenting not disabled, add line break after node
00177             if (!(flags & print_no_indenting))
00178                 *out = Ch('\n'), ++out;
00179 
00180             // Return modified iterator
00181             return out;
00182         }
00183 
00184         // Print children of the node
00185         template<class OutIt, class Ch>
00186         inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00187         {
00188             for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
00189                 out = print_node(out, child, flags, indent);
00190             return out;
00191         }
00192 
00193         // Print attributes of the node
00194         template<class OutIt, class Ch>
00195         inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
00196         {
00197             for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
00198             {
00199                 if (attribute->name() && attribute->value())
00200                 {
00201                     // Print attribute name
00202                     *out = Ch(' '), ++out;
00203                     out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
00204                     *out = Ch('='), ++out;
00205                     // Print attribute value using appropriate quote type
00206                     if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
00207                     {
00208                         *out = Ch('\''), ++out;
00209                         out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
00210                         *out = Ch('\''), ++out;
00211                     }
00212                     else
00213                     {
00214                         *out = Ch('"'), ++out;
00215                         out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
00216                         *out = Ch('"'), ++out;
00217                     }
00218                 }
00219             }
00220             return out;
00221         }
00222 
00223         // Print data node
00224         template<class OutIt, class Ch>
00225         inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00226         {
00227             assert(node->type() == node_data);
00228             if (!(flags & print_no_indenting))
00229                 out = fill_chars(out, indent, Ch('\t'));
00230             out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
00231             return out;
00232         }
00233 
00234         // Print data node
00235         template<class OutIt, class Ch>
00236         inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00237         {
00238             assert(node->type() == node_cdata);
00239             if (!(flags & print_no_indenting))
00240                 out = fill_chars(out, indent, Ch('\t'));
00241             *out = Ch('<'); ++out;
00242             *out = Ch('!'); ++out;
00243             *out = Ch('['); ++out;
00244             *out = Ch('C'); ++out;
00245             *out = Ch('D'); ++out;
00246             *out = Ch('A'); ++out;
00247             *out = Ch('T'); ++out;
00248             *out = Ch('A'); ++out;
00249             *out = Ch('['); ++out;
00250             out = copy_chars(node->value(), node->value() + node->value_size(), out);
00251             *out = Ch(']'); ++out;
00252             *out = Ch(']'); ++out;
00253             *out = Ch('>'); ++out;
00254             return out;
00255         }
00256 
00257         // Print element node
00258         template<class OutIt, class Ch>
00259         inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00260         {
00261             assert(node->type() == node_element);
00262 
00263             // Print element name and attributes, if any
00264             if (!(flags & print_no_indenting))
00265                 out = fill_chars(out, indent, Ch('\t'));
00266             *out = Ch('<'), ++out;
00267             out = copy_chars(node->name(), node->name() + node->name_size(), out);
00268             out = print_attributes(out, node, flags);
00269 
00270             // If node is childless
00271             if (node->value_size() == 0 && !node->first_node())
00272             {
00273                 // Print childless node tag ending
00274                 *out = Ch('/'), ++out;
00275                 *out = Ch('>'), ++out;
00276             }
00277             else
00278             {
00279                 // Print normal node tag ending
00280                 *out = Ch('>'), ++out;
00281 
00282                 // Test if node contains a single data node only (and no other nodes)
00283                 xml_node<Ch> *child = node->first_node();
00284                 if (!child)
00285                 {
00286                     // If node has no children, only print its value without indenting
00287                     out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
00288                 }
00289                 else if (child->next_sibling() == 0 && child->type() == node_data)
00290                 {
00291                     // If node has a sole data child, only print its value without indenting
00292                     out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
00293                 }
00294                 else
00295                 {
00296                     // Print all children with full indenting
00297                     if (!(flags & print_no_indenting))
00298                         *out = Ch('\n'), ++out;
00299                     out = print_children(out, node, flags, indent + 1);
00300                     if (!(flags & print_no_indenting))
00301                         out = fill_chars(out, indent, Ch('\t'));
00302                 }
00303 
00304                 // Print node end
00305                 *out = Ch('<'), ++out;
00306                 *out = Ch('/'), ++out;
00307                 out = copy_chars(node->name(), node->name() + node->name_size(), out);
00308                 *out = Ch('>'), ++out;
00309             }
00310             return out;
00311         }
00312 
00313         // Print declaration node
00314         template<class OutIt, class Ch>
00315         inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00316         {
00317             // Print declaration start
00318             if (!(flags & print_no_indenting))
00319                 out = fill_chars(out, indent, Ch('\t'));
00320             *out = Ch('<'), ++out;
00321             *out = Ch('?'), ++out;
00322             *out = Ch('x'), ++out;
00323             *out = Ch('m'), ++out;
00324             *out = Ch('l'), ++out;
00325 
00326             // Print attributes
00327             out = print_attributes(out, node, flags);
00328 
00329             // Print declaration end
00330             *out = Ch('?'), ++out;
00331             *out = Ch('>'), ++out;
00332 
00333             return out;
00334         }
00335 
00336         // Print comment node
00337         template<class OutIt, class Ch>
00338         inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00339         {
00340             assert(node->type() == node_comment);
00341             if (!(flags & print_no_indenting))
00342                 out = fill_chars(out, indent, Ch('\t'));
00343             *out = Ch('<'), ++out;
00344             *out = Ch('!'), ++out;
00345             *out = Ch('-'), ++out;
00346             *out = Ch('-'), ++out;
00347             out = copy_chars(node->value(), node->value() + node->value_size(), out);
00348             *out = Ch('-'), ++out;
00349             *out = Ch('-'), ++out;
00350             *out = Ch('>'), ++out;
00351             return out;
00352         }
00353 
00354         // Print doctype node
00355         template<class OutIt, class Ch>
00356         inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00357         {
00358             assert(node->type() == node_doctype);
00359             if (!(flags & print_no_indenting))
00360                 out = fill_chars(out, indent, Ch('\t'));
00361             *out = Ch('<'), ++out;
00362             *out = Ch('!'), ++out;
00363             *out = Ch('D'), ++out;
00364             *out = Ch('O'), ++out;
00365             *out = Ch('C'), ++out;
00366             *out = Ch('T'), ++out;
00367             *out = Ch('Y'), ++out;
00368             *out = Ch('P'), ++out;
00369             *out = Ch('E'), ++out;
00370             *out = Ch(' '), ++out;
00371             out = copy_chars(node->value(), node->value() + node->value_size(), out);
00372             *out = Ch('>'), ++out;
00373             return out;
00374         }
00375 
00376         // Print pi node
00377         template<class OutIt, class Ch>
00378         inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
00379         {
00380             assert(node->type() == node_pi);
00381             if (!(flags & print_no_indenting))
00382                 out = fill_chars(out, indent, Ch('\t'));
00383             *out = Ch('<'), ++out;
00384             *out = Ch('?'), ++out;
00385             out = copy_chars(node->name(), node->name() + node->name_size(), out);
00386             *out = Ch(' '), ++out;
00387             out = copy_chars(node->value(), node->value() + node->value_size(), out);
00388             *out = Ch('?'), ++out;
00389             *out = Ch('>'), ++out;
00390             return out;
00391         }
00392 
00393     }
00395 
00397     // Printing
00398 
00404     template<class OutIt, class Ch>
00405     inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
00406     {
00407         return internal::print_node(out, &node, flags, 0);
00408     }
00409 
00410 #ifndef RAPIDXML_NO_STREAMS
00411 
00417     template<class Ch>
00418     inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
00419     {
00420         print(std::ostream_iterator<Ch>(out), node, flags);
00421         return out;
00422     }
00423 
00428     template<class Ch>
00429     inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
00430     {
00431         return print(out, node);
00432     }
00433 
00434 #endif
00435 
00436 }
00437 
00438 #endif


mvsim
Author(s):
autogenerated on Thu Sep 7 2017 09:27:48