some documentation and new feartures for attributes
This commit is contained in:
		| @@ -17,7 +17,7 @@ | |||||||
| /*! @page limitations Known Limitations | /*! @page limitations Known Limitations | ||||||
|  |  | ||||||
|     - Templates cannot specify number of sub-elements. |     - Templates cannot specify number of sub-elements. | ||||||
|     - XML-Comments are not supported. |     - XML-Comments are only ignored. | ||||||
|     - Mixed tags and text is not supported. Tags may either contain |     - Mixed tags and text is not supported. Tags may either contain | ||||||
|       other tags only (type xml::Node) or text only (type |       other tags only (type xml::Node) or text only (type | ||||||
|       xml::String). |       xml::String). | ||||||
| @@ -25,45 +25,78 @@ | |||||||
|       (e.g. <p><p><p></p></p></p>) |       (e.g. <p><p><p></p></p></p>) | ||||||
|     - No check yet for optional and mandatory attributes in xml::Factory |     - No check yet for optional and mandatory attributes in xml::Factory | ||||||
|     - Exceptions should be optional, best effort otherwise (option "strict") */ |     - Exceptions should be optional, best effort otherwise (option "strict") */ | ||||||
|  |  | ||||||
|  | //! Represents classes for handling C++ access to XML files with strict schema. | ||||||
|  | /*! The schema ist not presented through xsd, but it can be declared in C++. | ||||||
|  |  | ||||||
|  |     A xml::Factory represents a factory that owns a template and can | ||||||
|  |     instanciate XML trees that are valid for the given template from | ||||||
|  |     streams. If anything is not valid, an exception is thrown. The @c | ||||||
|  |     what() method of the exception gives additional information about | ||||||
|  |     the problem. | ||||||
|  |  | ||||||
|  |     In the following example, we want to represent XML data that are | ||||||
|  |     contained in a <persons> tag, and may contain a list of @c | ||||||
|  |     person. Each @c person has a mandatory attribute @c id and | ||||||
|  |     optional @c member-of. @c person has a @c name and may contain a | ||||||
|  |     list of @c friends, where each @c friend has an attribute @c | ||||||
|  |     id. (The @c id attribute of course should reference to the @c id | ||||||
|  |     of another @c name, but this relationship cannot be declared.) | ||||||
|  |  | ||||||
|  |     All tags are by default specified as 0..n (optional and any number | ||||||
|  |     there of). | ||||||
|  |  | ||||||
|  |     <code> | ||||||
|  |     #include <xml-cxx/xml.hxx> | ||||||
|  |     #include <iostream> | ||||||
|  |     #include <<stream> | ||||||
|  |     [...] | ||||||
|  |     xml::Factory test(xml::Node("persons")             // root node | ||||||
|  |                       <<(xml::Node("person")           // child of persons | ||||||
|  |                          .attr("id", xml::mandatory) | ||||||
|  |                          .attr("member-of", xml::optional)) | ||||||
|  |                          <<xml::String("name")         // the person's name | ||||||
|  |                          <<(xml::Node("friends")       // friends of person | ||||||
|  |                             <<(xml::Node("friend")     // a friend | ||||||
|  |                                .attr("id", xml::mandatory))))); | ||||||
|  |     [...] | ||||||
|  |     try { | ||||||
|  |       std::auto_ptr<xml::Node> persons(test.read(std::ifstream("file.xml))); | ||||||
|  |       // Here we can be sure, that our structure is valid, | ||||||
|  |       // but we must check optional elements before access, otherwise | ||||||
|  |       // we get an exception. | ||||||
|  |       [...] | ||||||
|  |       for (xml::Node::size_type i(0); i<persons.children(); ++i) { | ||||||
|  |         std::cout<<"Person: "<<*persons[i]["name"]; // exception if no "name" | ||||||
|  |         if (persons[i]("friends")) // check if "friends" is set | ||||||
|  |           std::cout<<" has "<<persons[i]["friends"].children()<<" friends" | ||||||
|  |         else | ||||||
|  |           std::cout<<" has no friend list"; | ||||||
|  |         std::cout<<std::endl; | ||||||
|  |       } | ||||||
|  |       [...] | ||||||
|  |     } catch (const std::exception& x) { | ||||||
|  |       std::cerr<<"**** Error in file \"file.xml\":"<<std::endl | ||||||
|  |                <<x.what()<<std::endl; | ||||||
|  |     } | ||||||
|  |     </code> */ | ||||||
| namespace xml { | namespace xml { | ||||||
|    |    | ||||||
|   //============================================================================ |   //============================================================================ | ||||||
|     class  Attributes: public std::map<std::string, std::string> { |  | ||||||
|     public: |  | ||||||
|       class Value: public value_type { |  | ||||||
|         public: |  | ||||||
|           Value(const std::string& name) throw(); |  | ||||||
|           value_type& operator=(const std::string& value) throw(); |  | ||||||
|         private: |  | ||||||
|           Value(); // not implemented |  | ||||||
|       }; |  | ||||||
|       Attributes() throw(); |  | ||||||
|       Attributes(const std::string& empty) throw(); |  | ||||||
|       Attributes& operator<<(const value_type& v) throw(); |  | ||||||
|       Attributes& operator<<(const std::string& key) throw(); |  | ||||||
|       Attributes& operator=(const std::string& value) throw(); |  | ||||||
|     private: |  | ||||||
|       iterator _active; |  | ||||||
|   }; |  | ||||||
|   typedef Attributes::Value Attr; |  | ||||||
|   enum NodeType {START, END, EMPTY, SPECIAL}; |   enum NodeType {START, END, EMPTY, SPECIAL}; | ||||||
|   struct Tag { |  | ||||||
|       std::string name; |  | ||||||
|       NodeType type; |  | ||||||
|       std::string text; |  | ||||||
|       Attributes attributes; |  | ||||||
|       std::string special; |  | ||||||
|   }; |  | ||||||
|   const bool mandatory = true; |   const bool mandatory = true; | ||||||
|   const bool optional = false; |   const bool optional = false; | ||||||
|  |  | ||||||
|   //================================================================= EXCEPTIONS |   //================================================================= EXCEPTIONS | ||||||
|  |   struct Tag; | ||||||
|  |   class Attributes; | ||||||
|   class Node; |   class Node; | ||||||
|   class Factory; |   class Factory; | ||||||
|  |  | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class exception: public std::exception { |   class exception: public std::exception { | ||||||
|     public: |     public: | ||||||
|  |       exception(std::string reason) throw(); | ||||||
|       exception(std::string reason, const Node& t) throw(); |       exception(std::string reason, const Node& t) throw(); | ||||||
|       ~exception() throw(); |       ~exception() throw(); | ||||||
|       const char* what() const throw(); |       const char* what() const throw(); | ||||||
| @@ -121,53 +154,55 @@ namespace xml { | |||||||
|   class stream_error: public exception { |   class stream_error: public exception { | ||||||
|     public: |     public: | ||||||
|       stream_error(const std::string& reason, const Node& t, |       stream_error(const std::string& reason, const Node& t, | ||||||
|                    std::istream& is, Tag tag, char c=0) throw(); |                    std::istream& is, const Tag& tag, char c=0) throw(); | ||||||
|       ~stream_error() throw() {} |       ~stream_error() throw(); | ||||||
|       const char* what() const throw(); |       const char* what() const throw(); | ||||||
|     private: |     private: | ||||||
|       std::istream::streampos _pos; |       std::istream::streampos _pos; | ||||||
|       Tag _tag; |       Tag* _tag; | ||||||
|       char _char; |       char _char; | ||||||
|   }; |   }; | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class wrong_end_tag: public stream_error { |   class wrong_end_tag: public stream_error { | ||||||
|     public: |     public: | ||||||
|       wrong_end_tag(const Node& t, std::istream& is, Tag tag, char c=0) |       wrong_end_tag(const Node& t, std::istream& is, const Tag& tag, char c=0) | ||||||
|           throw(): |           throw(): | ||||||
|           stream_error("mismatching end tag", t, is, tag, c) { |           stream_error("mismatching end tag", t, is, tag, c) { | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   class missing_end_tag: public stream_error { |   class missing_end_tag: public stream_error { | ||||||
|     public: |     public: | ||||||
|       missing_end_tag(const Node& t, std::istream& is, Tag tag, char c=0) |       missing_end_tag(const Node& t, std::istream& is, const Tag& tag, char c=0) | ||||||
|           throw(): |           throw(): | ||||||
|           stream_error("missing end tag, end of file reached", t, is, tag, c) { |           stream_error("missing end tag, end of file reached", t, is, tag, c) { | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   class empty_stream: public stream_error { |   class empty_stream: public stream_error { | ||||||
|     public: |     public: | ||||||
|       empty_stream(const Node& t, std::istream& is, Tag tag, char c=0) |       empty_stream(const Node& t, std::istream& is, const Tag& tag, char c=0) | ||||||
|           throw(): |           throw(): | ||||||
|           stream_error("no xml tag found, stream is empty", t, is, tag, c) { |           stream_error("no xml tag found, stream is empty", t, is, tag, c) { | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   class wrong_start_tag: public stream_error { |   class wrong_start_tag: public stream_error { | ||||||
|     public: |     public: | ||||||
|       wrong_start_tag(const Node& t, std::istream& is, Tag tag, char c=0) |       wrong_start_tag(const Node& t, std::istream& is, const Tag& tag, char c=0) | ||||||
|           throw(): |           throw(): | ||||||
|           stream_error("start tag does not match expected tag", t, is, tag, c) { |           stream_error("start tag does not match expected tag", t, is, tag, c) { | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   class second_slash_in_tag: public stream_error { |   class second_slash_in_tag: public stream_error { | ||||||
|     public: |     public: | ||||||
|       second_slash_in_tag(const Node& t, std::istream& is, Tag tag, char c=0) |       second_slash_in_tag(const Node& t, std::istream& is, const Tag& tag, | ||||||
|  |                           char c=0) | ||||||
|           throw(): |           throw(): | ||||||
|           stream_error("a tag may have no more than one slash", t, is, tag, c) { |           stream_error("a tag may have no more than one slash", t, is, tag, c) { | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   class character_after_slash: public stream_error { |   class character_after_slash: public stream_error { | ||||||
|     public: |     public: | ||||||
|       character_after_slash(const Node& t, std::istream& is, Tag tag, char c=0) |       character_after_slash(const Node& t, std::istream& is, const Tag& tag, | ||||||
|  |                             char c=0) | ||||||
|           throw(): |           throw(): | ||||||
|           stream_error("unexpected character after empty-slash", |           stream_error("unexpected character after empty-slash", | ||||||
|                        t, is, tag, c) { |                        t, is, tag, c) { | ||||||
| @@ -175,14 +210,15 @@ namespace xml { | |||||||
|   }; |   }; | ||||||
|   class attributes_in_end_tag: public stream_error { |   class attributes_in_end_tag: public stream_error { | ||||||
|     public: |     public: | ||||||
|       attributes_in_end_tag(const Node& t, std::istream& is, Tag tag) |       attributes_in_end_tag(const Node& t, std::istream& is, const Tag& tag) | ||||||
|           throw(): |           throw(): | ||||||
|           stream_error("attributes are not allowed in end tags",t, is, tag) { |           stream_error("attributes are not allowed in end tags",t, is, tag) { | ||||||
|       } |       } | ||||||
|   }; |   }; | ||||||
|   class attribute_value_not_quoted: public stream_error { |   class attribute_value_not_quoted: public stream_error { | ||||||
|     public: |     public: | ||||||
|       attribute_value_not_quoted(const Node& t, std::istream& is, Tag tag, |       attribute_value_not_quoted(const Node& t, std::istream& is, | ||||||
|  |                                  const Tag& tag, | ||||||
|                                  char c, std::string attr) throw(): |                                  char c, std::string attr) throw(): | ||||||
|           stream_error("attribute values must be quoted (\")\nattribute: "+attr, |           stream_error("attribute values must be quoted (\")\nattribute: "+attr, | ||||||
|                        t, is, tag, c) { |                        t, is, tag, c) { | ||||||
| @@ -190,7 +226,7 @@ namespace xml { | |||||||
|   }; |   }; | ||||||
|   class duplicate_attribute: public stream_error { |   class duplicate_attribute: public stream_error { | ||||||
|     public: |     public: | ||||||
|       duplicate_attribute(const Node& t, std::istream& is, Tag tag, |       duplicate_attribute(const Node& t, std::istream& is, const Tag& tag, | ||||||
|                           std::string attr) throw(): |                           std::string attr) throw(): | ||||||
|           stream_error("attribute duplicated\nattribute: "+attr, |           stream_error("attribute duplicated\nattribute: "+attr, | ||||||
|                        t, is, tag, 0) { |                        t, is, tag, 0) { | ||||||
| @@ -199,6 +235,66 @@ namespace xml { | |||||||
|  |  | ||||||
|   //============================================================================ |   //============================================================================ | ||||||
|  |  | ||||||
|  |   //---------------------------------------------------------------------------- | ||||||
|  |   //! Map for attribute values. | ||||||
|  |   /*! Attributes can be set using method xml::Node::attr(). Check for | ||||||
|  |       an attribute with xml::Node::hasAttr(). Attributes must be | ||||||
|  |       unique, which means that every attribute must be set at maximum | ||||||
|  |       once. This is corect: <code><node | ||||||
|  |       attribute="value"></code>, this is not allowed: | ||||||
|  |       <code><node attribute="value" attribute="value"></code> */ | ||||||
|  |   class  Attributes: public std::map<std::string, std::string> { | ||||||
|  |     public: | ||||||
|  |       //! Attributes may contain a list of space separated values. | ||||||
|  |       typedef std::vector<std::string> List; | ||||||
|  |       //! Attribute values ar mainly a std::pair. | ||||||
|  |       /*! In addition to a normal std::pair, attributes offer an | ||||||
|  |           assignment operator to set the value, and can be constructed | ||||||
|  |           as empty attribute, given only a key. */ | ||||||
|  |       class Value: public value_type { | ||||||
|  |         public: | ||||||
|  |           //! Construct an empty attribute. | ||||||
|  |           Value(const std::string& name) throw(); | ||||||
|  |           //! Construct an attribute with name an value. | ||||||
|  |           Value(const std::string& name, const std::string& namevalue) throw(); | ||||||
|  |           //! Assign a value. | ||||||
|  |           value_type& operator=(const std::string& value) throw(); | ||||||
|  |           //! Get the attribute name. | ||||||
|  |           const std::string& name() const throw(); | ||||||
|  |           //! Get the attribute value. | ||||||
|  |           const std::string& value() const throw(); | ||||||
|  |           //! Get the attribute value. | ||||||
|  |           std::string& value() throw(); | ||||||
|  |           //! Convert the attribute to a boolean. | ||||||
|  |           operator bool() const throw(); | ||||||
|  |           //! Convert the attribute to a number. | ||||||
|  |           operator unsigned long() const throw(); | ||||||
|  |           //! Convert the attribute to a space separated list. | ||||||
|  |           operator List() const throw(); | ||||||
|  |           List toList(const std::string& separators=" \t\n\r") const throw(); | ||||||
|  |         private: | ||||||
|  |           Value(); // not implemented, key must always be given | ||||||
|  |       }; | ||||||
|  |       Attributes() throw(); | ||||||
|  |       Attributes(const std::string& empty) throw(); | ||||||
|  |       Attributes& operator<<(const value_type& v) throw(); | ||||||
|  |       Attributes& operator<<(const std::string& key) throw(); | ||||||
|  |       Attributes& operator=(const std::string& value) throw(); | ||||||
|  |     private: | ||||||
|  |       iterator _active; | ||||||
|  |   }; | ||||||
|  |   typedef Attributes::Value Attr; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   //---------------------------------------------------------------------------- | ||||||
|  |   struct Tag { | ||||||
|  |       std::string name; | ||||||
|  |       NodeType type; | ||||||
|  |       std::string text; | ||||||
|  |       Attributes attributes; | ||||||
|  |       std::string special; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class Node { |   class Node { | ||||||
|     private: |     private: | ||||||
| @@ -284,9 +380,6 @@ namespace xml { | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   class List: public Node { |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   class Factory { |   class Factory { | ||||||
|     public: |     public: | ||||||
|       Factory(const Node& t) throw(); |       Factory(const Node& t) throw(); | ||||||
|   | |||||||
							
								
								
									
										112
									
								
								src/xml.cxx
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								src/xml.cxx
									
									
									
									
									
								
							| @@ -37,37 +37,12 @@ unsigned int MethodTrace::_level(0); | |||||||
|  |  | ||||||
| namespace xml { | namespace xml { | ||||||
|    |    | ||||||
|   //============================================================================ |  | ||||||
|   Attributes::Value::Value(const std::string& name) throw(): |  | ||||||
|       Attributes::value_type(name, std::string()) { |  | ||||||
|   } |  | ||||||
|   Attributes::value_type& Attributes::Value::operator=(const std::string& value) |  | ||||||
|       throw() { |  | ||||||
|     second = value; |  | ||||||
|     return *this; |  | ||||||
|   } |  | ||||||
|   Attributes::Attributes() throw(): _active(end()) {} |  | ||||||
|   Attributes::Attributes(const std::string& empty) throw() { |  | ||||||
|     _active = insert(Value(empty)).first; |  | ||||||
|   } |  | ||||||
|   Attributes& Attributes::operator<<(const value_type& v) throw() { |  | ||||||
|     _active = insert(v).first; |  | ||||||
|     return *this; |  | ||||||
|   } |  | ||||||
|   Attributes& Attributes::operator<<(const std::string& key) throw() { |  | ||||||
|     _active = insert(Value(key)).first; |  | ||||||
|     return *this; |  | ||||||
|   } |  | ||||||
|   Attributes& Attributes::operator=(const std::string& value) throw() { |  | ||||||
|     if (_active==end()) return *this; |  | ||||||
|     _active->second = value; |  | ||||||
|     _active = end(); |  | ||||||
|     return *this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   //================================================================= EXCEPTIONS |   //================================================================= EXCEPTIONS | ||||||
|  |  | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|  |   exception::exception(std::string reason) throw(): | ||||||
|  |       _what(reason), _node(0) { | ||||||
|  |   } | ||||||
|   exception::exception(std::string reason, const Node& t) throw(): |   exception::exception(std::string reason, const Node& t) throw(): | ||||||
|       _what(reason), _node(t.clone().release()) { |       _what(reason), _node(t.clone().release()) { | ||||||
|   } |   } | ||||||
| @@ -122,8 +97,11 @@ namespace xml { | |||||||
|   } |   } | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   stream_error::stream_error(const std::string& reason, const Node& t, |   stream_error::stream_error(const std::string& reason, const Node& t, | ||||||
|                              std::istream& is, Tag tag, char c) throw(): |                              std::istream& is, const Tag& tag, char c) throw(): | ||||||
|       exception(reason, t), _pos(is.tellg()), _tag(tag), _char(c) { |       exception(reason, t), _pos(is.tellg()), _tag(new Tag(tag)), _char(c) { | ||||||
|  |   } | ||||||
|  |   stream_error::~stream_error() throw() { | ||||||
|  |     delete _tag; | ||||||
|   } |   } | ||||||
|   const char* stream_error::what() const throw() { |   const char* stream_error::what() const throw() { | ||||||
|     static std::string w; |     static std::string w; | ||||||
| @@ -134,12 +112,12 @@ namespace xml { | |||||||
|       if (_char) |       if (_char) | ||||||
|         ss<<"\nactual character: "<<(_char>31?_char:'?') |         ss<<"\nactual character: "<<(_char>31?_char:'?') | ||||||
|           <<" (ascii="<<(int)_char<<")"; |           <<" (ascii="<<(int)_char<<")"; | ||||||
|       ss<<"\ntag type: "<<(_tag.type==START?"START" |       ss<<"\ntag type: "<<(_tag->type==START?"START" | ||||||
|                            :(_tag.type==END?"END" |                            :(_tag->type==END?"END" | ||||||
|                              :(_tag.type==EMPTY?"EMPTY" |                              :(_tag->type==EMPTY?"EMPTY" | ||||||
|                                :"???? <UNKNOWN>"))); |                                :"???? <UNKNOWN>"))); | ||||||
|       if (_tag.name.size()) ss<<"\nnode name read: "<<_tag.name; |       if (_tag->name.size()) ss<<"\nnode name read: "<<_tag->name; | ||||||
|       if (_tag.text.size()) ss<<"\ncontained text: "<<_tag.text; |       if (_tag->text.size()) ss<<"\ncontained text: "<<_tag->text; | ||||||
|       w = ss.str(); |       w = ss.str(); | ||||||
|     } |     } | ||||||
|     return w.c_str(); |     return w.c_str(); | ||||||
| @@ -147,6 +125,70 @@ namespace xml { | |||||||
|  |  | ||||||
|   //============================================================================ |   //============================================================================ | ||||||
|  |  | ||||||
|  |   //---------------------------------------------------------------------------- | ||||||
|  |   Attributes::Value::Value(const std::string& name) throw(): | ||||||
|  |       Attributes::value_type(name, std::string()) { | ||||||
|  |   } | ||||||
|  |   Attributes::Value::Value(const std::string& name, | ||||||
|  |                            const std::string& value) throw(): | ||||||
|  |       Attributes::value_type(name, value) { | ||||||
|  |   } | ||||||
|  |   const std::string& Attributes::Value::name() const throw() { | ||||||
|  |     return first; | ||||||
|  |   } | ||||||
|  |   const std::string& Attributes::Value::value() const throw() { | ||||||
|  |     return second; | ||||||
|  |   } | ||||||
|  |   std::string& Attributes::Value::value() throw() { | ||||||
|  |     return second; | ||||||
|  |   } | ||||||
|  |   Attributes::Value::operator bool() const throw() { | ||||||
|  |     /*! @return @c true if the value is set and not equal to one of: | ||||||
|  |         @c false @c no @c 0. */ | ||||||
|  |     return !(second.size()||second=="false"||second=="no"||second=="0"); | ||||||
|  |   } | ||||||
|  |   Attributes::Value::operator unsigned long() const throw() { | ||||||
|  |     std::stringstream ss(second); | ||||||
|  |     int i(0); | ||||||
|  |     ss>>i; | ||||||
|  |     return i; | ||||||
|  |   } | ||||||
|  |   Attributes::Value::operator List() const throw() { | ||||||
|  |     return toList(); | ||||||
|  |   } | ||||||
|  |   Attributes::List Attributes::Value::toList(const std::string& separators) | ||||||
|  |       const throw() { | ||||||
|  |     List l; | ||||||
|  |     for (std::string::size_type it(0), pos(0); | ||||||
|  |          (pos=second.find_first_of(separators, it)), it!=std::string::npos; | ||||||
|  |          it=pos!=std::string::npos?++pos:std::string::npos) | ||||||
|  |       l.push_back(std::string(second.begin()+it, second.begin()+pos)); | ||||||
|  |     return l; | ||||||
|  |   } | ||||||
|  |   //---------------------------------------------------------------------------- | ||||||
|  |   Attributes::value_type& Attributes::Value::operator=(const std::string& value) | ||||||
|  |       throw() { | ||||||
|  |     second = value; | ||||||
|  |     return *this; | ||||||
|  |   } | ||||||
|  |   Attributes::Attributes() throw(): _active(end()) {} | ||||||
|  |   Attributes::Attributes(const std::string& empty) throw() { | ||||||
|  |     _active = insert(Value(empty)).first; | ||||||
|  |   } | ||||||
|  |   Attributes& Attributes::operator<<(const value_type& v) throw() { | ||||||
|  |     _active = insert(v).first; | ||||||
|  |     return *this; | ||||||
|  |   } | ||||||
|  |   Attributes& Attributes::operator<<(const std::string& key) throw() { | ||||||
|  |     _active = insert(Value(key)).first; | ||||||
|  |     return *this; | ||||||
|  |   } | ||||||
|  |   Attributes& Attributes::operator=(const std::string& value) throw() { | ||||||
|  |     if (_active==end()) return *this; | ||||||
|  |     _active->second = value; | ||||||
|  |     _active = end(); | ||||||
|  |     return *this; | ||||||
|  |   } | ||||||
|   //---------------------------------------------------------------------------- |   //---------------------------------------------------------------------------- | ||||||
|   Node::Node(std::string name) throw(): |   Node::Node(std::string name) throw(): | ||||||
|       _name(name), _parent(0) { |       _name(name), _parent(0) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user