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