TM2IN  0.5.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 
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  }
378 
380  // Printing
381 
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 
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 
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
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)
Definition: rapidxml_print.hpp:388
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.
Definition: rapidxml_print.hpp:23
Definition: rapidxml.hpp:138
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
Definition: rapidxml.hpp:137
Definition: rapidxml.hpp:57
std::size_t value_size() const
Definition: rapidxml.hpp:700