Photon 1.0.0
Loading...
Searching...
No Matches
rapidxml_print.hpp
Go to the documentation of this file.
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 $
8
9#include "rapidxml.hpp"
10
11// Only include streams if not disabled
12#ifndef RAPIDXML_NO_STREAMS
13#include <iterator>
14#include <ostream>
15#endif
16
17namespace rapidxml
18{
19
21 // Printing flags
22
24 0x1;
25
27 // Internal
28
30 namespace internal
31 {
32
34 // Internal character operations
35
36 // Copy characters from given range to given output iterator
37 template <class OutIt, class Ch> 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('&');
61 *out++ = Ch('l');
62 *out++ = Ch('t');
63 *out++ = Ch(';');
64 break;
65 case Ch('>'):
66 *out++ = Ch('&');
67 *out++ = Ch('g');
68 *out++ = Ch('t');
69 *out++ = Ch(';');
70 break;
71 case Ch('\''):
72 *out++ = Ch('&');
73 *out++ = Ch('a');
74 *out++ = Ch('p');
75 *out++ = Ch('o');
76 *out++ = Ch('s');
77 *out++ = Ch(';');
78 break;
79 case Ch('"'):
80 *out++ = Ch('&');
81 *out++ = Ch('q');
82 *out++ = Ch('u');
83 *out++ = Ch('o');
84 *out++ = Ch('t');
85 *out++ = Ch(';');
86 break;
87 case Ch('&'):
88 *out++ = Ch('&');
89 *out++ = Ch('a');
90 *out++ = Ch('m');
91 *out++ = Ch('p');
92 *out++ = Ch(';');
93 break;
94 default:
95 *out++ = *begin; // No expansion, copy character
96 }
97 }
98 ++begin; // Step to next character
99 }
100 return out;
101 }
102
103 // Fill given output iterator with repetitions of the same character
104 template <class OutIt, class Ch> inline OutIt fill_chars(OutIt out, int n, Ch ch)
105 {
106 for (int i = 0; i < n; ++i)
107 *out++ = ch;
108 return out;
109 }
110
111 // Find character
112 template <class Ch, Ch ch> inline bool find_char(const Ch* begin, const Ch* end)
113 {
114 while (begin != end)
115 if (*begin++ == ch)
116 return true;
117 return false;
118 }
119
121 // Internal printing operations
122
123 // Print node
124 template <class OutIt, class Ch>
125 inline OutIt print_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
126 {
127 // Print proper node type
128 switch (node->type())
129 {
130
131 // Document
132 case node_document:
133 out = print_children(out, node, flags, indent);
134 break;
135
136 // Element
137 case node_element:
138 out = print_element_node(out, node, flags, indent);
139 break;
140
141 // Data
142 case node_data:
143 out = print_data_node(out, node, flags, indent);
144 break;
145
146 // CDATA
147 case node_cdata:
148 out = print_cdata_node(out, node, flags, indent);
149 break;
150
151 // Declaration
152 case node_declaration:
153 out = print_declaration_node(out, node, flags, indent);
154 break;
155
156 // Comment
157 case node_comment:
158 out = print_comment_node(out, node, flags, indent);
159 break;
160
161 // Doctype
162 case node_doctype:
163 out = print_doctype_node(out, node, flags, indent);
164 break;
165
166 // Pi
167 case node_pi:
168 out = print_pi_node(out, node, flags, indent);
169 break;
170
171 // Unknown
172 default:
173 assert(0);
174 break;
175 }
176
177 // If indenting not disabled, add line break after node
178 if (!(flags & print_no_indenting))
179 *out = Ch('\n'), ++out;
180
181 // Return modified iterator
182 return out;
183 }
184
185 // Print children of the node
186 template <class OutIt, class Ch>
187 inline OutIt print_children(OutIt out, const xml_node<Ch>* node, int flags, int indent)
188 {
189 for (xml_node<Ch>* child = node->first_node(); child; child = child->next_sibling())
190 out = print_node(out, child, flags, indent);
191 return out;
192 }
193
194 // Print attributes of the node
195 template <class OutIt, class Ch> inline OutIt print_attributes(OutIt out, const xml_node<Ch>* node, int flags)
196 {
197 for (xml_attribute<Ch>* attribute = node->first_attribute(); attribute;
198 attribute = attribute->next_attribute())
199 {
200 if (attribute->name() && attribute->value())
201 {
202 // Print attribute name
203 *out = Ch(' '), ++out;
204 out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
205 *out = Ch('='), ++out;
206 // Print attribute value using appropriate quote type
207 if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
208 {
209 *out = Ch('\''), ++out;
210 out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(),
211 Ch('"'), out);
212 *out = Ch('\''), ++out;
213 }
214 else
215 {
216 *out = Ch('"'), ++out;
217 out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(),
218 Ch('\''), out);
219 *out = Ch('"'), ++out;
220 }
221 }
222 }
223 return out;
224 }
225
226 // Print data node
227 template <class OutIt, class Ch>
228 inline OutIt print_data_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
229 {
230 assert(node->type() == node_data);
231 if (!(flags & print_no_indenting))
232 out = fill_chars(out, indent, Ch('\t'));
233 out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
234 return out;
235 }
236
237 // Print data node
238 template <class OutIt, class Ch>
239 inline OutIt print_cdata_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
240 {
241 assert(node->type() == node_cdata);
242 if (!(flags & print_no_indenting))
243 out = fill_chars(out, indent, Ch('\t'));
244 *out = Ch('<');
245 ++out;
246 *out = Ch('!');
247 ++out;
248 *out = Ch('[');
249 ++out;
250 *out = Ch('C');
251 ++out;
252 *out = Ch('D');
253 ++out;
254 *out = Ch('A');
255 ++out;
256 *out = Ch('T');
257 ++out;
258 *out = Ch('A');
259 ++out;
260 *out = Ch('[');
261 ++out;
262 out = copy_chars(node->value(), node->value() + node->value_size(), out);
263 *out = Ch(']');
264 ++out;
265 *out = Ch(']');
266 ++out;
267 *out = Ch('>');
268 ++out;
269 return out;
270 }
271
272 // Print element node
273 template <class OutIt, class Ch>
274 inline OutIt print_element_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
275 {
276 assert(node->type() == node_element);
277
278 // Print element name and attributes, if any
279 if (!(flags & print_no_indenting))
280 out = fill_chars(out, indent, Ch('\t'));
281 *out = Ch('<'), ++out;
282 out = copy_chars(node->name(), node->name() + node->name_size(), out);
283 out = print_attributes(out, node, flags);
284
285 // If node is childless
286 if (node->value_size() == 0 && !node->first_node())
287 {
288 // Print childless node tag ending
289 *out = Ch('/'), ++out;
290 *out = Ch('>'), ++out;
291 }
292 else
293 {
294 // Print normal node tag ending
295 *out = Ch('>'), ++out;
296
297 // Test if node contains a single data node only (and no other nodes)
298 xml_node<Ch>* child = node->first_node();
299 if (!child)
300 {
301 // If node has no children, only print its value without indenting
302 out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
303 }
304 else if (child->next_sibling() == 0 && child->type() == node_data)
305 {
306 // If node has a sole data child, only print its value without indenting
307 out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
308 }
309 else
310 {
311 // Print all children with full indenting
312 if (!(flags & print_no_indenting))
313 *out = Ch('\n'), ++out;
314 out = print_children(out, node, flags, indent + 1);
315 if (!(flags & print_no_indenting))
316 out = fill_chars(out, indent, Ch('\t'));
317 }
318
319 // Print node end
320 *out = Ch('<'), ++out;
321 *out = Ch('/'), ++out;
322 out = copy_chars(node->name(), node->name() + node->name_size(), out);
323 *out = Ch('>'), ++out;
324 }
325 return out;
326 }
327
328 // Print declaration node
329 template <class OutIt, class Ch>
330 inline OutIt print_declaration_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
331 {
332 // Print declaration start
333 if (!(flags & print_no_indenting))
334 out = fill_chars(out, indent, Ch('\t'));
335 *out = Ch('<'), ++out;
336 *out = Ch('?'), ++out;
337 *out = Ch('x'), ++out;
338 *out = Ch('m'), ++out;
339 *out = Ch('l'), ++out;
340
341 // Print attributes
342 out = print_attributes(out, node, flags);
343
344 // Print declaration end
345 *out = Ch('?'), ++out;
346 *out = Ch('>'), ++out;
347
348 return out;
349 }
350
351 // Print comment node
352 template <class OutIt, class Ch>
353 inline OutIt print_comment_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
354 {
355 assert(node->type() == node_comment);
356 if (!(flags & print_no_indenting))
357 out = fill_chars(out, indent, Ch('\t'));
358 *out = Ch('<'), ++out;
359 *out = Ch('!'), ++out;
360 *out = Ch('-'), ++out;
361 *out = Ch('-'), ++out;
362 out = copy_chars(node->value(), node->value() + node->value_size(), out);
363 *out = Ch('-'), ++out;
364 *out = Ch('-'), ++out;
365 *out = Ch('>'), ++out;
366 return out;
367 }
368
369 // Print doctype node
370 template <class OutIt, class Ch>
371 inline OutIt print_doctype_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
372 {
373 assert(node->type() == node_doctype);
374 if (!(flags & print_no_indenting))
375 out = fill_chars(out, indent, Ch('\t'));
376 *out = Ch('<'), ++out;
377 *out = Ch('!'), ++out;
378 *out = Ch('D'), ++out;
379 *out = Ch('O'), ++out;
380 *out = Ch('C'), ++out;
381 *out = Ch('T'), ++out;
382 *out = Ch('Y'), ++out;
383 *out = Ch('P'), ++out;
384 *out = Ch('E'), ++out;
385 *out = Ch(' '), ++out;
386 out = copy_chars(node->value(), node->value() + node->value_size(), out);
387 *out = Ch('>'), ++out;
388 return out;
389 }
390
391 // Print pi node
392 template <class OutIt, class Ch>
393 inline OutIt print_pi_node(OutIt out, const xml_node<Ch>* node, int flags, int indent)
394 {
395 assert(node->type() == node_pi);
396 if (!(flags & print_no_indenting))
397 out = fill_chars(out, indent, Ch('\t'));
398 *out = Ch('<'), ++out;
399 *out = Ch('?'), ++out;
400 out = copy_chars(node->name(), node->name() + node->name_size(), out);
401 *out = Ch(' '), ++out;
402 out = copy_chars(node->value(), node->value() + node->value_size(), out);
403 *out = Ch('?'), ++out;
404 *out = Ch('>'), ++out;
405 return out;
406 }
407
408 } // namespace internal
410
412 // Printing
413
419 template <class OutIt, class Ch> inline OutIt print(OutIt out, const xml_node<Ch>& node, int flags = 0)
420 {
421 return internal::print_node(out, &node, flags, 0);
422 }
423
424#ifndef RAPIDXML_NO_STREAMS
425
431 template <class Ch>
432 inline std::basic_ostream<Ch>& print(std::basic_ostream<Ch>& out, const xml_node<Ch>& node, int flags = 0)
433 {
434 print(std::ostream_iterator<Ch>(out), node, flags);
435 return out;
436 }
437
440 template <class Ch> inline std::basic_ostream<Ch>& operator<<(std::basic_ostream<Ch>& out, const xml_node<Ch>& node)
441 {
442 return print(out, node);
443 }
444
445#endif
446
447} // namespace rapidxml
448
449#endif
Definition rapidxml.hpp:784
std::size_t name_size() const
Definition rapidxml.hpp:669
std::size_t value_size() const
Definition rapidxml.hpp:687
Ch * name() const
Definition rapidxml.hpp:661
Ch * value() const
Definition rapidxml.hpp:679
Definition rapidxml.hpp:882
node_type type() const
Definition rapidxml.hpp:900
xml_attribute< Ch > * first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition rapidxml.hpp:1017
xml_node< Ch > * next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition rapidxml.hpp:995
xml_node< Ch > * first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition rapidxml.hpp:924
#define out
Definition encodings.cpp:5
Definition rapidxml.hpp:62
OutIt print(OutIt out, const xml_node< Ch > &node, int flags=0)
Definition rapidxml_print.hpp:419
const int print_no_indenting
Printer flag instructing the printer to suppress indenting of XML. See print() function.
Definition rapidxml_print.hpp:23
@ node_comment
A comment node. Name is empty. Value contains comment text.
Definition rapidxml.hpp:147
@ node_document
A document node. Name and value are empty.
Definition rapidxml.hpp:143
@ node_element
An element node. Name contains element name. Value contains text of first data node.
Definition rapidxml.hpp:144
@ node_data
A data node. Name is empty. Value contains data text.
Definition rapidxml.hpp:145
@ node_cdata
A CDATA node. Name is empty. Value contains data text.
Definition rapidxml.hpp:146
@ node_doctype
A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
Definition rapidxml.hpp:150
@ node_pi
A PI node. Name contains target. Value contains instructions.
Definition rapidxml.hpp:151
@ node_declaration
Definition rapidxml.hpp:148
std::basic_ostream< Ch > & operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node)
Definition rapidxml_print.hpp:440
This file contains rapidxml parser and DOM implementation.
i
Definition tag_strings.h:60