position.cxx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // file : examples/inheritance/position.cxx
  2. // copyright : not copyrighted - public domain
  3. #include <iostream>
  4. #include <xml/parser>
  5. #include <xml/serializer>
  6. #include "position.hxx"
  7. using namespace std;
  8. using namespace xml;
  9. // position
  10. //
  11. position::
  12. position (parser& p)
  13. : lat_ (p.attribute<float> ("lat")),
  14. lon_ (p.attribute<float> ("lon"))
  15. {
  16. p.content (content::empty);
  17. }
  18. void position::
  19. serialize (serializer& s) const
  20. {
  21. s.attribute ("lat", lat_);
  22. s.attribute ("lon", lon_);
  23. }
  24. // object
  25. //
  26. object::
  27. object (parser& p)
  28. : name_ (p.attribute ("name")),
  29. id_ (p.attribute<unsigned int> ("id"))
  30. {
  31. p.content (content::complex);
  32. do
  33. {
  34. p.next_expect (parser::start_element, "position");
  35. positions_.push_back (position (p));
  36. p.next_expect (parser::end_element);
  37. // Note that here we have to also check the name to make sure
  38. // it is the position element and not something that should be
  39. // handled by a derived class.
  40. //
  41. } while (p.peek () == parser::start_element && p.name () == "position");
  42. }
  43. void object::
  44. serialize_attributes (serializer& s) const
  45. {
  46. s.attribute ("name", name_);
  47. s.attribute ("id", id_);
  48. }
  49. void object::
  50. serialize_content (serializer& s) const
  51. {
  52. for (positions_type::const_iterator i (positions_.begin ());
  53. i != positions_.end ();
  54. ++i)
  55. {
  56. s.start_element ("position");
  57. i->serialize (s);
  58. s.end_element ();
  59. }
  60. }
  61. // elevation
  62. //
  63. elevation::
  64. elevation (parser& p)
  65. : value_ (p.attribute<float> ("val"))
  66. {
  67. p.content (content::empty);
  68. }
  69. void elevation::
  70. serialize (serializer& s) const
  71. {
  72. s.attribute ("val", value_);
  73. }
  74. // object
  75. //
  76. elevated_object::
  77. elevated_object (parser& p)
  78. : object (p), // First parse our base.
  79. units_ (p.attribute ("units"))
  80. {
  81. // If we are happy with the content model used by our base (complex
  82. // in this case), then we don't need to set one ourselves. We, could,
  83. // however "upgrade" our content model from empty to either simple or
  84. // complex.
  85. do
  86. {
  87. p.next_expect (parser::start_element, "elevation");
  88. elevations_.push_back (elevation (p));
  89. p.next_expect (parser::end_element);
  90. } while (p.peek () == parser::start_element && p.name () == "elevation");
  91. }
  92. void elevated_object::
  93. serialize_attributes (serializer& s) const
  94. {
  95. object::serialize_attributes (s); // First serialize our base attributes.
  96. s.attribute ("units", units_);
  97. }
  98. void elevated_object::
  99. serialize_content (serializer& s) const
  100. {
  101. object::serialize_content (s); // First serialize our base content.
  102. for (elevations_type::const_iterator i (elevations_.begin ());
  103. i != elevations_.end ();
  104. ++i)
  105. {
  106. s.start_element ("elevation");
  107. i->serialize (s);
  108. s.end_element ();
  109. }
  110. }
  111. // objects
  112. //
  113. objects::
  114. objects (parser& p)
  115. {
  116. // Note that for the root of the object model we parse the start/end
  117. // element ourselves instead of expecting the caller to do so. This
  118. // makes the client code nice and simple.
  119. //
  120. p.next_expect (parser::start_element, "objects", content::complex);
  121. // First parse all the objects, if any.
  122. //
  123. while (p.peek () == parser::start_element && p.name () == "object")
  124. {
  125. p.next (); // "Swallow" the start_element event.
  126. simple_objects_.push_back (object (p));
  127. p.next_expect (parser::end_element);
  128. }
  129. // Then parse all the elevated object, if any.
  130. //
  131. while (p.peek () == parser::start_element && p.name () == "elevated-object")
  132. {
  133. p.next (); // "Swallow" the start_element event.
  134. elevated_objects_.push_back (elevated_object (p));
  135. p.next_expect (parser::end_element);
  136. }
  137. // We should have at least one object.
  138. //
  139. if (simple_objects_.empty () && elevated_objects_.empty ())
  140. throw parsing (p, "at least one object or elevated object required");
  141. p.next_expect (xml::parser::end_element); // objects
  142. }
  143. void objects::
  144. serialize (serializer& s) const
  145. {
  146. // Note that for the root of the object model we serialize the
  147. // start/end element ourselves instead of expecting the caller
  148. // to do so. This makes the client code nice and simple.
  149. //
  150. s.start_element ("objects");
  151. // First serialize all the objects.
  152. //
  153. for (simple_objects_type::const_iterator i (simple_objects_.begin ());
  154. i != simple_objects_.end ();
  155. ++i)
  156. {
  157. s.start_element ("object");
  158. i->serialize (s);
  159. s.end_element ();
  160. }
  161. // Then serialize all the elevated objects.
  162. //
  163. for (elevated_objects_type::const_iterator i (elevated_objects_.begin ());
  164. i != elevated_objects_.end ();
  165. ++i)
  166. {
  167. s.start_element ("elevated-object");
  168. i->serialize (s);
  169. s.end_element ();
  170. }
  171. s.end_element (); // objects
  172. }