dom.cxx 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // file : examples/hybrid/dom.cxx
  2. // copyright : not copyrighted - public domain
  3. #include <xml/parser>
  4. #include <xml/serializer>
  5. #include "dom.hxx"
  6. using namespace std;
  7. using namespace xml;
  8. static bool
  9. whitespace (const string& s)
  10. {
  11. for (string::size_type i (0); i < s.size (); ++i)
  12. {
  13. char c (s[i]);
  14. if (c != 0x20 && c != 0x0A && c != 0x0D && c != 0x09)
  15. return false;
  16. }
  17. return true;
  18. }
  19. element::
  20. element (parser& p, bool se)
  21. {
  22. if (se)
  23. p.next_expect (parser::start_element);
  24. name_ = p.qname ();
  25. // Extract attributes.
  26. //
  27. const parser::attribute_map_type& m (p.attribute_map ());
  28. for (parser::attribute_map_type::const_iterator i (m.begin ());
  29. i != m.end ();
  30. ++i)
  31. attributes_[i->first] = i->second.value;
  32. // Parse content (nested elements or text).
  33. //
  34. while (p.peek () != parser::end_element)
  35. {
  36. switch (p.next ())
  37. {
  38. case parser::start_element:
  39. {
  40. if (!text_.empty ())
  41. {
  42. if (!whitespace (text_))
  43. throw parsing (p, "element in simple content");
  44. text_.clear ();
  45. }
  46. elements_.push_back (element (p, false));
  47. p.next_expect (parser::end_element);
  48. break;
  49. }
  50. case parser::characters:
  51. {
  52. if (!elements_.empty ())
  53. {
  54. if (!whitespace (p.value ()))
  55. throw parsing (p, "characters in complex content");
  56. break; // Ignore whitespaces.
  57. }
  58. text_ += p.value ();
  59. break;
  60. }
  61. default:
  62. break; // Ignore any other events.
  63. }
  64. }
  65. if (se)
  66. p.next_expect (parser::end_element);
  67. }
  68. void element::
  69. serialize (serializer& s, bool se) const
  70. {
  71. if (se)
  72. s.start_element (name_);
  73. // Add attributes.
  74. //
  75. for (attributes_type::const_iterator i (attributes_.begin ());
  76. i != attributes_.end ();
  77. ++i)
  78. {
  79. s.attribute (i->first, i->second);
  80. }
  81. // Serialize content (nested elements or text).
  82. //
  83. if (!elements_.empty ())
  84. {
  85. for (elements_type::const_iterator i (elements_.begin ());
  86. i != elements_.end ();
  87. ++i)
  88. {
  89. i->serialize (s);
  90. }
  91. }
  92. else if (!text_.empty ())
  93. s.characters (text_);
  94. if (se)
  95. s.end_element ();
  96. }