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 <ostream>
14  #include <iterator>
15 #endif
16 
17 namespace rapidxml
18 {
19 
21  // Printing flags
22 
23  const int print_no_indenting = 0x1;
24 
26  // Internal
27 
29  namespace internal
30  {
31 
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 
103  // Internal printing operations
104  template<class OutIt, class Ch>
105  inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent);
106 
107  template<class OutIt, class Ch>
108  inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags);
109 
110  template<class OutIt, class Ch>
111  inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
112 
113  template<class OutIt, class Ch>
114  inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
115 
116  template<class OutIt, class Ch>
117  inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
118 
119  template<class OutIt, class Ch>
120  inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
121 
122  template<class OutIt, class Ch>
123  inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
124 
125  template<class OutIt, class Ch>
126  inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
127 
128  template<class OutIt, class Ch>
129  inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
130 
131  // Print node
132  template<class OutIt, class Ch>
133  inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
134  {
135  // Print proper node type
136  switch (node->type())
137  {
138 
139  // Document
140  case node_document:
141  out = print_children(out, node, flags, indent);
142  break;
143 
144  // Element
145  case node_element:
146  out = print_element_node(out, node, flags, indent);
147  break;
148 
149  // Data
150  case node_data:
151  out = print_data_node(out, node, flags, indent);
152  break;
153 
154  // CDATA
155  case node_cdata:
156  out = print_cdata_node(out, node, flags, indent);
157  break;
158 
159  // Declaration
160  case node_declaration:
161  out = print_declaration_node(out, node, flags, indent);
162  break;
163 
164  // Comment
165  case node_comment:
166  out = print_comment_node(out, node, flags, indent);
167  break;
168 
169  // Doctype
170  case node_doctype:
171  out = print_doctype_node(out, node, flags, indent);
172  break;
173 
174  // Pi
175  case node_pi:
176  out = print_pi_node(out, node, flags, indent);
177  break;
178 
179  // Unknown
180  default:
181  assert(0);
182  break;
183  }
184 
185  // If indenting not disabled, add line break after node
186  if (!(flags & print_no_indenting))
187  *out = Ch('\n'), ++out;
188 
189  // Return modified iterator
190  return out;
191  }
192 
193  // Print children of the node
194  template<class OutIt, class Ch>
195  inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
196  {
197  for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
198  out = print_node(out, child, flags, indent);
199  return out;
200  }
201 
202  // Print attributes of the node
203  template<class OutIt, class Ch>
204  inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
205  {
206  for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
207  {
208  if (attribute->name() && attribute->value())
209  {
210  // Print attribute name
211  *out = Ch(' '), ++out;
212  out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
213  *out = Ch('='), ++out;
214  // Print attribute value using appropriate quote type
215  if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
216  {
217  *out = Ch('\''), ++out;
218  out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
219  *out = Ch('\''), ++out;
220  }
221  else
222  {
223  *out = Ch('"'), ++out;
224  out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
225  *out = Ch('"'), ++out;
226  }
227  }
228  }
229  return out;
230  }
231 
232  // Print data node
233  template<class OutIt, class Ch>
234  inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
235  {
236  assert(node->type() == node_data);
237  if (!(flags & print_no_indenting))
238  out = fill_chars(out, indent, Ch('\t'));
239  out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
240  return out;
241  }
242 
243  // Print data node
244  template<class OutIt, class Ch>
245  inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
246  {
247  assert(node->type() == node_cdata);
248  if (!(flags & print_no_indenting))
249  out = fill_chars(out, indent, Ch('\t'));
250  *out = Ch('<'); ++out;
251  *out = Ch('!'); ++out;
252  *out = Ch('['); ++out;
253  *out = Ch('C'); ++out;
254  *out = Ch('D'); ++out;
255  *out = Ch('A'); ++out;
256  *out = Ch('T'); ++out;
257  *out = Ch('A'); ++out;
258  *out = Ch('['); ++out;
259  out = copy_chars(node->value(), node->value() + node->value_size(), out);
260  *out = Ch(']'); ++out;
261  *out = Ch(']'); ++out;
262  *out = Ch('>'); ++out;
263  return out;
264  }
265 
266  // Print element node
267  template<class OutIt, class Ch>
268  inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
269  {
270  assert(node->type() == node_element);
271 
272  // Print element name and attributes, if any
273  if (!(flags & print_no_indenting))
274  out = fill_chars(out, indent, Ch('\t'));
275  *out = Ch('<'), ++out;
276  out = copy_chars(node->name(), node->name() + node->name_size(), out);
277  out = print_attributes(out, node, flags);
278 
279  // If node is childless
280  if (node->value_size() == 0 && !node->first_node())
281  {
282  // Print childless node tag ending
283  *out = Ch('/'), ++out;
284  *out = Ch('>'), ++out;
285  }
286  else
287  {
288  // Print normal node tag ending
289  *out = Ch('>'), ++out;
290 
291  // Test if node contains a single data node only (and no other nodes)
292  xml_node<Ch> *child = node->first_node();
293  if (!child)
294  {
295  // If node has no children, only print its value without indenting
296  out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
297  }
298  else if (child->next_sibling() == 0 && child->type() == node_data)
299  {
300  // If node has a sole data child, only print its value without indenting
301  out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
302  }
303  else
304  {
305  // Print all children with full indenting
306  if (!(flags & print_no_indenting))
307  *out = Ch('\n'), ++out;
308  out = print_children(out, node, flags, indent + 1);
309  if (!(flags & print_no_indenting))
310  out = fill_chars(out, indent, Ch('\t'));
311  }
312 
313  // Print node end
314  *out = Ch('<'), ++out;
315  *out = Ch('/'), ++out;
316  out = copy_chars(node->name(), node->name() + node->name_size(), out);
317  *out = Ch('>'), ++out;
318  }
319  return out;
320  }
321 
322  // Print declaration node
323  template<class OutIt, class Ch>
324  inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
325  {
326  // Print declaration start
327  if (!(flags & print_no_indenting))
328  out = fill_chars(out, indent, Ch('\t'));
329  *out = Ch('<'), ++out;
330  *out = Ch('?'), ++out;
331  *out = Ch('x'), ++out;
332  *out = Ch('m'), ++out;
333  *out = Ch('l'), ++out;
334 
335  // Print attributes
336  out = print_attributes(out, node, flags);
337 
338  // Print declaration end
339  *out = Ch('?'), ++out;
340  *out = Ch('>'), ++out;
341 
342  return out;
343  }
344 
345  // Print comment node
346  template<class OutIt, class Ch>
347  inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
348  {
349  assert(node->type() == node_comment);
350  if (!(flags & print_no_indenting))
351  out = fill_chars(out, indent, Ch('\t'));
352  *out = Ch('<'), ++out;
353  *out = Ch('!'), ++out;
354  *out = Ch('-'), ++out;
355  *out = Ch('-'), ++out;
356  out = copy_chars(node->value(), node->value() + node->value_size(), out);
357  *out = Ch('-'), ++out;
358  *out = Ch('-'), ++out;
359  *out = Ch('>'), ++out;
360  return out;
361  }
362 
363  // Print doctype node
364  template<class OutIt, class Ch>
365  inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
366  {
367  assert(node->type() == node_doctype);
368  if (!(flags & print_no_indenting))
369  out = fill_chars(out, indent, Ch('\t'));
370  *out = Ch('<'), ++out;
371  *out = Ch('!'), ++out;
372  *out = Ch('D'), ++out;
373  *out = Ch('O'), ++out;
374  *out = Ch('C'), ++out;
375  *out = Ch('T'), ++out;
376  *out = Ch('Y'), ++out;
377  *out = Ch('P'), ++out;
378  *out = Ch('E'), ++out;
379  *out = Ch(' '), ++out;
380  out = copy_chars(node->value(), node->value() + node->value_size(), out);
381  *out = Ch('>'), ++out;
382  return out;
383  }
384 
385  // Print pi node
386  template<class OutIt, class Ch>
387  inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
388  {
389  assert(node->type() == node_pi);
390  if (!(flags & print_no_indenting))
391  out = fill_chars(out, indent, Ch('\t'));
392  *out = Ch('<'), ++out;
393  *out = Ch('?'), ++out;
394  out = copy_chars(node->name(), node->name() + node->name_size(), out);
395  *out = Ch(' '), ++out;
396  out = copy_chars(node->value(), node->value() + node->value_size(), out);
397  *out = Ch('?'), ++out;
398  *out = Ch('>'), ++out;
399  return out;
400  }
401 
402  }
404 
406  // Printing
407 
413  template<class OutIt, class Ch>
414  inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
415  {
416  return internal::print_node(out, &node, flags, 0);
417  }
418 
419 #ifndef RAPIDXML_NO_STREAMS
420 
426  template<class Ch>
427  inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
428  {
429  print(std::ostream_iterator<Ch>(out), node, flags);
430  return out;
431  }
432 
437  template<class Ch>
438  inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
439  {
440  return print(out, node);
441  }
442 
443 #endif
444 
445 }
446 
447 #endif
This file contains rapidxml parser and DOM implementation.
A comment node. Name is empty. Value contains comment text.
Definition: rapidxml.hpp:149
OutIt print(OutIt out, const xml_node< Ch > &node, int flags=0)
Ch * value() const
Definition: rapidxml.hpp:692
std::size_t name_size() const
Definition: rapidxml.hpp:681
A CDATA node. Name is empty. Value contains data text.
Definition: rapidxml.hpp:148
An element node. Name contains element name. Value contains text of first data node.
Definition: rapidxml.hpp:146
A document node. Name and value are empty.
Definition: rapidxml.hpp:145
xml_node< Ch > * first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:936
node_type type() const
Definition: rapidxml.hpp:913
Ch * name() const
Definition: rapidxml.hpp:673
xml_attribute< Ch > * first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:1025
const int print_no_indenting
Printer flag instructing the printer to suppress indenting of XML. See print() function.
A data node. Name is empty. Value contains data text.
Definition: rapidxml.hpp:147
A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
Definition: rapidxml.hpp:151
A PI node. Name contains target. Value contains instructions.
Definition: rapidxml.hpp:152
A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalon...
Definition: rapidxml.hpp:150
xml_node< Ch > * next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:1004
std::size_t value_size() const
Definition: rapidxml.hpp:700


asr_rapidxml
Author(s): Aumann Florian
autogenerated on Thu Dec 5 2019 03:14:37