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


asr_rapidxml
Author(s): Aumann Florian
autogenerated on Thu Jun 6 2019 18:55:38