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