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