1 // This is brl/bbas/bxml/bxml_document.h 2 #ifndef bxml_document_h_ 3 #define bxml_document_h_ 4 //: 5 // \file 6 // \brief An XML document representation 7 // \author Matt Leotta (Brown) 8 // \date October 5, 2006 9 // 10 // \verbatim 11 // Modifications 12 // Ozge C. Ozcanli (Brown) - July 15, 2009 - enabled smart pointer for bxml_document 13 // Ricardo Fabbri (Brown) - October 18, 2009 - specialized get_attribute for strings 14 // \endverbatim 15 16 #include <string> 17 #include <sstream> 18 #include <iostream> 19 #include <map> 20 #include <utility> 21 #include <vector> 22 #ifdef _MSC_VER 23 # include <vcl_msvc_warnings.h> 24 #endif 25 #include <vbl/vbl_ref_count.h> 26 #include <vbl/vbl_smart_ptr.h> 27 #include <vsl/vsl_binary_io.h> 28 29 //: A block of character data found within XML tags 30 // This is a base class and can be either plain text or 31 // an XML element 32 class bxml_data : public vbl_ref_count 33 { 34 public: 35 enum datatype {TEXT, ELEMENT}; 36 37 ~bxml_data() override = default; 38 39 //: Return the type of XML data 40 virtual datatype type() const = 0; 41 }; 42 43 //: compare two XML data objects 44 bool operator==(const bxml_data& d1, const bxml_data& d2); 45 46 47 typedef vbl_smart_ptr<bxml_data> bxml_data_sptr; 48 49 50 //: text data within XML 51 class bxml_text : public bxml_data 52 { 53 public: 54 //: Constructor bxml_text(std::string data)55 bxml_text(std::string data) : data_(std::move(data)) {} 56 57 //: Destructor 58 ~bxml_text() override = default; 59 60 //: Return the type of XML data type()61 datatype type() const override { return TEXT; } 62 63 //: Access the text data data()64 std::string data() const { return data_; } 65 66 //: Set the text data set_data(const std::string & data)67 void set_data(const std::string& data) { data_ = data; } 68 69 private: 70 std::string data_; 71 }; 72 73 74 //: An XML element 75 class bxml_element : public bxml_data 76 { 77 public: 78 typedef std::vector<bxml_data_sptr>::const_iterator const_data_iterator; 79 typedef std::map<std::string,std::string>::const_iterator const_attr_iterator; 80 81 //: Constructor - default 82 bxml_element() = default; 83 84 //: Constructor bxml_element(std::string name)85 bxml_element(std::string name) : name_(std::move(name)) {} 86 87 //: Destructor 88 ~bxml_element() override = default; 89 90 //: Return the type of XML data type()91 datatype type() const override { return ELEMENT; } 92 93 //: Return the name of the element name()94 std::string name() const { return name_; } 95 96 //: Return the value of an attribute 97 std::string attribute(const std::string& attr_name) const; 98 99 //: Specialization for std::string. get_attribute(const std::string & attr_name,std::string & value)100 bool get_attribute(const std::string& attr_name, std::string& value) const 101 { 102 value = this->attribute(attr_name); 103 return true; 104 } 105 106 //: Return the value of an attribute. 107 // \see specialization for std::string. 108 template <class T> get_attribute(const std::string & attr_name,T & value)109 bool get_attribute(const std::string& attr_name, T& value) const 110 { 111 std::stringstream s(this->attribute(attr_name)); 112 if (s.str() == "") 113 return false; 114 s >> value; 115 return true; 116 } 117 118 119 //: Return the values of all attributes with a given name 120 std::vector<std::string> attributes(const std::string& attr_name) const; 121 122 //: Specialization for std::string. get_attributea(const std::string & attr_name,std::vector<std::string> & values)123 bool get_attributea(const std::string& attr_name, std::vector<std::string>& values) const 124 { 125 values = this->attributes(attr_name); 126 return true; 127 } 128 129 //: Return the value of an attribute. 130 // \see specialization for std::string. 131 template <class T> get_attributes(const std::string & attr_name,std::vector<T> & values)132 bool get_attributes(const std::string& attr_name, std::vector<T>& values) const 133 { 134 values.clear(); 135 std::vector<std::string> values_str = attributes(attr_name); 136 for (const auto & vi : values_str) { 137 std::stringstream s(vi); 138 if (s.str() == "") 139 return false; 140 T value_t; 141 s >> value_t; 142 values.push_back(value_t); 143 144 } 145 return true; 146 } 147 148 //: Return the number of attributes num_attributes()149 unsigned int num_attributes() const { return (unsigned int)attributes_.size(); } 150 151 //: An iterator to the beginning of the attributes attr_begin()152 const_attr_iterator attr_begin() const { return attributes_.begin(); } 153 154 //: An iterator to the end of the attributes attr_end()155 const_attr_iterator attr_end() const { return attributes_.end(); } 156 157 //: Return the number of data nodes num_data()158 unsigned int num_data() const { return (unsigned int)data_.size(); } 159 160 //: An iterator to the beginning of the data data_begin()161 const_data_iterator data_begin() const { return data_.begin(); } 162 163 //: An iterator to the end of the data data_end()164 const_data_iterator data_end() const { return data_.end(); } 165 166 //: Append text in this element 167 void append_text(const std::string& text); 168 169 //: Append data (typically another element) in this element append_data(const bxml_data_sptr & el)170 void append_data(const bxml_data_sptr& el) 171 { data_.push_back(el); } 172 173 //: Set attribute with and optional precision. 174 template <class T> 175 void set_attribute(const std::string& attr_name, const T& attr_value, unsigned p = 5) 176 { 177 std::stringstream s; 178 s.precision(p); 179 s << attr_value; 180 attributes_[attr_name] = s.str(); 181 } 182 //: Specialization for std::string below. set_attribute(const std::string & attr_name,const std::string & attr_value)183 void set_attribute(const std::string& attr_name, const std::string& attr_value) 184 { attributes_[attr_name] = attr_value; } 185 186 private: 187 //: The name of the element 188 std::string name_; 189 190 //: The map of attributes to values 191 std::map<std::string,std::string> attributes_; 192 193 //: The character data. 194 std::vector<bxml_data_sptr> data_; 195 }; 196 197 198 //: compare two XML element objects 199 bool operator==(const bxml_element& e1, const bxml_element& e2); 200 201 202 //: Represents a full XML document stored as a tree 203 class bxml_document : public vbl_ref_count 204 { 205 public: 206 //: Constructor - default 207 bxml_document(); 208 209 //: Destructor 210 ~bxml_document() override= default; 211 212 //: Return the root element root_element()213 bxml_data_sptr root_element() const {return root_element_;} 214 215 //: Return the version string version()216 std::string version() const { return version_; } 217 218 //: Return the encoding string encoding()219 std::string encoding() const { return encoding_; } 220 221 //: Return the standalone bit standalone()222 bool standalone() const { return standalone_; } 223 224 //: set the root element set_root_element(const bxml_data_sptr & root)225 void set_root_element(const bxml_data_sptr& root) 226 { root_element_ = root; } 227 228 //: Set the version string set_version(const std::string & version)229 void set_version(const std::string& version) { version_ = version; } 230 231 //: Set the encoding string set_encoding(const std::string & encoding)232 void set_encoding(const std::string& encoding) { encoding_ = encoding; } 233 234 //: Set the standalone bit set_standalone(bool standalone)235 void set_standalone(bool standalone) { standalone_ = standalone; } 236 237 private: 238 //: The root element 239 bxml_data_sptr root_element_; 240 241 std::string version_; 242 std::string encoding_; 243 bool standalone_; 244 }; 245 246 247 248 typedef vbl_smart_ptr<bxml_document> bxml_document_sptr; 249 250 //: compare two XML documents 251 bool operator==(const bxml_document& d1, const bxml_document& d2); 252 253 // Binary io, NOT IMPLEMENTED, signatures defined to use bxml_document as a brdb_value 254 void vsl_b_write(vsl_b_ostream & os, bxml_document const &ph); 255 void vsl_b_read(vsl_b_istream & is, bxml_document &ph); 256 void vsl_b_read(vsl_b_istream& is, bxml_document* ph); 257 void vsl_b_write(vsl_b_ostream& os, const bxml_document* &ph); 258 259 260 #endif // bxml_document_h_ 261