source: XIOS/dev/dev_olga/src/extern/rapidxml/include/rapidxml_print.hpp @ 1022

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 15.7 KB
Line 
1#ifndef RAPIDXML_PRINT_HPP_INCLUDED
2#define RAPIDXML_PRINT_HPP_INCLUDED
3
4// Copyright (C) 2006, 2009 Marcin Kalicinski
5// Version 1.13
6// Revision $DateTime: 2009/05/13 01:46:17 $
7//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
8
9#include "rapidxml.hpp"
10
11// Only include streams if not disabled
12#ifndef RAPIDXML_NO_STREAMS
13    #include <ostream>
14    #include <iterator>
15#endif
16
17namespace rapidxml
18{
19
20    ///////////////////////////////////////////////////////////////////////
21    // Printing flags
22
23    const int print_no_indenting = 0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
24
25    ///////////////////////////////////////////////////////////////////////
26    // Internal
27
28    //! \cond internal
29    namespace internal
30    {
31       
32        ///////////////////////////////////////////////////////////////////////////
33        // Internal character operations
34   
35        // Copy characters from given range to given output iterator
36        template<class OutIt, class Ch>
37        inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
38        {
39            while (begin != end)
40                *out++ = *begin++;
41            return out;
42        }
43       
44        // Copy characters from given range to given output iterator and expand
45        // characters into references (&lt; &gt; &apos; &quot; &amp;)
46        template<class OutIt, class Ch>
47        inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
48        {
49            while (begin != end)
50            {
51                if (*begin == noexpand)
52                {
53                    *out++ = *begin;    // No expansion, copy character
54                }
55                else
56                {
57                    switch (*begin)
58                    {
59                    case Ch('<'):
60                        *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
61                        break;
62                    case Ch('>'): 
63                        *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
64                        break;
65                    case Ch('\''): 
66                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
67                        break;
68                    case Ch('"'): 
69                        *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
70                        break;
71                    case Ch('&'): 
72                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); 
73                        break;
74                    default:
75                        *out++ = *begin;    // No expansion, copy character
76                    }
77                }
78                ++begin;    // Step to next character
79            }
80            return out;
81        }
82
83        // Fill given output iterator with repetitions of the same character
84        template<class OutIt, class Ch>
85        inline OutIt fill_chars(OutIt out, int n, Ch ch)
86        {
87            for (int i = 0; i < n; ++i)
88                *out++ = ch;
89            return out;
90        }
91
92        // Find character
93        template<class Ch, Ch ch>
94        inline bool find_char(const Ch *begin, const Ch *end)
95        {
96            while (begin != end)
97                if (*begin++ == ch)
98                    return true;
99            return false;
100        }
101
102        ///////////////////////////////////////////////////////////////////////////
103        // Internal printing operations
104   
105        // Print node
106        template<class OutIt, class Ch>
107        inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
108        {
109            // Print proper node type
110            switch (node->type())
111            {
112
113            // Document
114            case node_document:
115                out = print_children(out, node, flags, indent);
116                break;
117
118            // Element
119            case node_element:
120                out = print_element_node(out, node, flags, indent);
121                break;
122           
123            // Data
124            case node_data:
125                out = print_data_node(out, node, flags, indent);
126                break;
127           
128            // CDATA
129            case node_cdata:
130                out = print_cdata_node(out, node, flags, indent);
131                break;
132
133            // Declaration
134            case node_declaration:
135                out = print_declaration_node(out, node, flags, indent);
136                break;
137
138            // Comment
139            case node_comment:
140                out = print_comment_node(out, node, flags, indent);
141                break;
142           
143            // Doctype
144            case node_doctype:
145                out = print_doctype_node(out, node, flags, indent);
146                break;
147
148            // Pi
149            case node_pi:
150                out = print_pi_node(out, node, flags, indent);
151                break;
152
153                // Unknown
154            default:
155                assert(0);
156                break;
157            }
158           
159            // If indenting not disabled, add line break after node
160            if (!(flags & print_no_indenting))
161                *out = Ch('\n'), ++out;
162
163            // Return modified iterator
164            return out;
165        }
166       
167        // Print children of the node                               
168        template<class OutIt, class Ch>
169        inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
170        {
171            for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
172                out = print_node(out, child, flags, indent);
173            return out;
174        }
175
176        // Print attributes of the node
177        template<class OutIt, class Ch>
178        inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
179        {
180            for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
181            {
182                if (attribute->name() && attribute->value())
183                {
184                    // Print attribute name
185                    *out = Ch(' '), ++out;
186                    out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
187                    *out = Ch('='), ++out;
188                    // Print attribute value using appropriate quote type
189                    if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
190                    {
191                        *out = Ch('\''), ++out;
192                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
193                        *out = Ch('\''), ++out;
194                    }
195                    else
196                    {
197                        *out = Ch('"'), ++out;
198                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
199                        *out = Ch('"'), ++out;
200                    }
201                }
202            }
203            return out;
204        }
205
206        // Print data node
207        template<class OutIt, class Ch>
208        inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
209        {
210            assert(node->type() == node_data);
211            if (!(flags & print_no_indenting))
212                out = fill_chars(out, indent, Ch('\t'));
213            out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
214            return out;
215        }
216
217        // Print data node
218        template<class OutIt, class Ch>
219        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
220        {
221            assert(node->type() == node_cdata);
222            if (!(flags & print_no_indenting))
223                out = fill_chars(out, indent, Ch('\t'));
224            *out = Ch('<'); ++out;
225            *out = Ch('!'); ++out;
226            *out = Ch('['); ++out;
227            *out = Ch('C'); ++out;
228            *out = Ch('D'); ++out;
229            *out = Ch('A'); ++out;
230            *out = Ch('T'); ++out;
231            *out = Ch('A'); ++out;
232            *out = Ch('['); ++out;
233            out = copy_chars(node->value(), node->value() + node->value_size(), out);
234            *out = Ch(']'); ++out;
235            *out = Ch(']'); ++out;
236            *out = Ch('>'); ++out;
237            return out;
238        }
239
240        // Print element node
241        template<class OutIt, class Ch>
242        inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
243        {
244            assert(node->type() == node_element);
245
246            // Print element name and attributes, if any
247            if (!(flags & print_no_indenting))
248                out = fill_chars(out, indent, Ch('\t'));
249            *out = Ch('<'), ++out;
250            out = copy_chars(node->name(), node->name() + node->name_size(), out);
251            out = print_attributes(out, node, flags);
252           
253            // If node is childless
254            if (node->value_size() == 0 && !node->first_node())
255            {
256                // Print childless node tag ending
257                *out = Ch('/'), ++out;
258                *out = Ch('>'), ++out;
259            }
260            else
261            {
262                // Print normal node tag ending
263                *out = Ch('>'), ++out;
264
265                // Test if node contains a single data node only (and no other nodes)
266                xml_node<Ch> *child = node->first_node();
267                if (!child)
268                {
269                    // If node has no children, only print its value without indenting
270                    out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
271                }
272                else if (child->next_sibling() == 0 && child->type() == node_data)
273                {
274                    // If node has a sole data child, only print its value without indenting
275                    out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
276                }
277                else
278                {
279                    // Print all children with full indenting
280                    if (!(flags & print_no_indenting))
281                        *out = Ch('\n'), ++out;
282                    out = print_children(out, node, flags, indent + 1);
283                    if (!(flags & print_no_indenting))
284                        out = fill_chars(out, indent, Ch('\t'));
285                }
286
287                // Print node end
288                *out = Ch('<'), ++out;
289                *out = Ch('/'), ++out;
290                out = copy_chars(node->name(), node->name() + node->name_size(), out);
291                *out = Ch('>'), ++out;
292            }
293            return out;
294        }
295
296        // Print declaration node
297        template<class OutIt, class Ch>
298        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
299        {
300            // Print declaration start
301            if (!(flags & print_no_indenting))
302                out = fill_chars(out, indent, Ch('\t'));
303            *out = Ch('<'), ++out;
304            *out = Ch('?'), ++out;
305            *out = Ch('x'), ++out;
306            *out = Ch('m'), ++out;
307            *out = Ch('l'), ++out;
308
309            // Print attributes
310            out = print_attributes(out, node, flags);
311           
312            // Print declaration end
313            *out = Ch('?'), ++out;
314            *out = Ch('>'), ++out;
315           
316            return out;
317        }
318
319        // Print comment node
320        template<class OutIt, class Ch>
321        inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
322        {
323            assert(node->type() == node_comment);
324            if (!(flags & print_no_indenting))
325                out = fill_chars(out, indent, Ch('\t'));
326            *out = Ch('<'), ++out;
327            *out = Ch('!'), ++out;
328            *out = Ch('-'), ++out;
329            *out = Ch('-'), ++out;
330            out = copy_chars(node->value(), node->value() + node->value_size(), out);
331            *out = Ch('-'), ++out;
332            *out = Ch('-'), ++out;
333            *out = Ch('>'), ++out;
334            return out;
335        }
336
337        // Print doctype node
338        template<class OutIt, class Ch>
339        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
340        {
341            assert(node->type() == node_doctype);
342            if (!(flags & print_no_indenting))
343                out = fill_chars(out, indent, Ch('\t'));
344            *out = Ch('<'), ++out;
345            *out = Ch('!'), ++out;
346            *out = Ch('D'), ++out;
347            *out = Ch('O'), ++out;
348            *out = Ch('C'), ++out;
349            *out = Ch('T'), ++out;
350            *out = Ch('Y'), ++out;
351            *out = Ch('P'), ++out;
352            *out = Ch('E'), ++out;
353            *out = Ch(' '), ++out;
354            out = copy_chars(node->value(), node->value() + node->value_size(), out);
355            *out = Ch('>'), ++out;
356            return out;
357        }
358
359        // Print pi node
360        template<class OutIt, class Ch>
361        inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
362        {
363            assert(node->type() == node_pi);
364            if (!(flags & print_no_indenting))
365                out = fill_chars(out, indent, Ch('\t'));
366            *out = Ch('<'), ++out;
367            *out = Ch('?'), ++out;
368            out = copy_chars(node->name(), node->name() + node->name_size(), out);
369            *out = Ch(' '), ++out;
370            out = copy_chars(node->value(), node->value() + node->value_size(), out);
371            *out = Ch('?'), ++out;
372            *out = Ch('>'), ++out;
373            return out;
374        }
375
376    }
377    //! \endcond
378
379    ///////////////////////////////////////////////////////////////////////////
380    // Printing
381
382    //! Prints XML to given output iterator.
383    //! \param out Output iterator to print to.
384    //! \param node Node to be printed. Pass xml_document to print entire document.
385    //! \param flags Flags controlling how XML is printed.
386    //! \return Output iterator pointing to position immediately after last character of printed text.
387    template<class OutIt, class Ch> 
388    inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
389    {
390        return internal::print_node(out, &node, flags, 0);
391    }
392
393#ifndef RAPIDXML_NO_STREAMS
394
395    //! Prints XML to given output stream.
396    //! \param out Output stream to print to.
397    //! \param node Node to be printed. Pass xml_document to print entire document.
398    //! \param flags Flags controlling how XML is printed.
399    //! \return Output stream.
400    template<class Ch> 
401    inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
402    {
403        print(std::ostream_iterator<Ch>(out), node, flags);
404        return out;
405    }
406
407    //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
408    //! \param out Output stream to print to.
409    //! \param node Node to be printed.
410    //! \return Output stream.
411    template<class Ch> 
412    inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
413    {
414        return print(out, node);
415    }
416
417#endif
418
419}
420
421#endif
Note: See TracBrowser for help on using the repository browser.