more docu; other behaviour for parent
This commit is contained in:
@@ -639,13 +639,13 @@ SOURCE_BROWSER = YES
|
|||||||
# Setting the INLINE_SOURCES tag to YES will include the body
|
# Setting the INLINE_SOURCES tag to YES will include the body
|
||||||
# of functions and classes directly in the documentation.
|
# of functions and classes directly in the documentation.
|
||||||
|
|
||||||
INLINE_SOURCES = YES
|
INLINE_SOURCES = NO
|
||||||
|
|
||||||
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
|
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
|
||||||
# doxygen to hide any special comment blocks from generated source code
|
# doxygen to hide any special comment blocks from generated source code
|
||||||
# fragments. Normal C and C++ comments will always remain visible.
|
# fragments. Normal C and C++ comments will always remain visible.
|
||||||
|
|
||||||
STRIP_CODE_COMMENTS = YES
|
STRIP_CODE_COMMENTS = NO
|
||||||
|
|
||||||
# If the REFERENCED_BY_RELATION tag is set to YES (the default)
|
# If the REFERENCED_BY_RELATION tag is set to YES (the default)
|
||||||
# then for each documented function all documented
|
# then for each documented function all documented
|
||||||
|
@@ -424,9 +424,10 @@ namespace xml {
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
class String: public Node {
|
class String: public Node {
|
||||||
public:
|
public:
|
||||||
String(std::string name, size_type min=0, size_type max=0) throw();
|
String(std::string name,
|
||||||
|
Node::size_type min=0, Node::size_type max=0) throw();
|
||||||
String(std::string name, const std::string& text,
|
String(std::string name, const std::string& text,
|
||||||
size_type min=0, size_type max=0) throw();
|
Node::size_type min=0, Node::size_type max=0) throw();
|
||||||
virtual std::auto_ptr<Node> clone() const throw();
|
virtual std::auto_ptr<Node> clone() const throw();
|
||||||
virtual ~String() throw() {}
|
virtual ~String() throw() {}
|
||||||
virtual std::string text() const throw();
|
virtual std::string text() const throw();
|
||||||
|
99
src/xml.cxx
99
src/xml.cxx
@@ -170,9 +170,9 @@ namespace xml {
|
|||||||
return second;
|
return second;
|
||||||
}
|
}
|
||||||
//! Convert the attribute to a boolean.
|
//! Convert the attribute to a boolean.
|
||||||
Attributes::Value::operator bool() const throw() {
|
|
||||||
/*! @return @c true if the value is set and not equal to one of:
|
/*! @return @c true if the value is set and not equal to one of:
|
||||||
@c false @c no @c 0. */
|
@c false @c no @c 0. */
|
||||||
|
Attributes::Value::operator bool() const throw() {
|
||||||
return !(second.size()||second=="false"||second=="no"||second=="0");
|
return !(second.size()||second=="false"||second=="no"||second=="0");
|
||||||
}
|
}
|
||||||
//! Convert the attribute to a number.
|
//! Convert the attribute to a number.
|
||||||
@@ -186,7 +186,8 @@ namespace xml {
|
|||||||
Attributes::Value::operator List() const throw() {
|
Attributes::Value::operator List() const throw() {
|
||||||
return toList();
|
return toList();
|
||||||
}
|
}
|
||||||
//! Convert the attribute to a space separated list.
|
//! Convert the attribute to list.
|
||||||
|
/*! @param separators a string containing a list of valid separators */
|
||||||
Attributes::List Attributes::Value::toList(const std::string& separators)
|
Attributes::List Attributes::Value::toList(const std::string& separators)
|
||||||
const throw() {
|
const throw() {
|
||||||
List l;
|
List l;
|
||||||
@@ -200,6 +201,8 @@ namespace xml {
|
|||||||
l.push_back(second.substr(it, pos-it));
|
l.push_back(second.substr(it, pos-it));
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
//! Get the first value of an attribute containing a list of values.
|
||||||
|
/*! @copydoc xml::Attributes::Value::toList */
|
||||||
std::string Attributes::Value::front(const std::string& separators) const
|
std::string Attributes::Value::front(const std::string& separators) const
|
||||||
throw(empty_attribute_list) {
|
throw(empty_attribute_list) {
|
||||||
List l(toList(separators));
|
List l(toList(separators));
|
||||||
@@ -231,11 +234,15 @@ namespace xml {
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//! Nodes must be given a name.
|
//! Nodes must be given a name.
|
||||||
/*! Unnamed nodes are not allowed, therefore there's no default
|
/*! Unnamed nodes are not allowed, therefore there's no default
|
||||||
constructor. */
|
constructor.
|
||||||
|
@copydoc xml::Node::limits */
|
||||||
Node::Node(std::string name,
|
Node::Node(std::string name,
|
||||||
Node::size_type min, Node::size_type max) throw():
|
Node::size_type min, Node::size_type max) throw():
|
||||||
_name(name), _parent(0), _min(min), _max(max) {
|
_name(name), _parent(0), _min(min), _max(max) {
|
||||||
}
|
}
|
||||||
|
//! Copy node, reset parent.
|
||||||
|
/*! The parent is reset, the node does not belong to the same parent
|
||||||
|
as the source of the copy. */
|
||||||
Node::Node(const Node& o) throw():
|
Node::Node(const Node& o) throw():
|
||||||
_attributes(o._attributes), _name(o.name()), _parent(0),
|
_attributes(o._attributes), _name(o.name()), _parent(0),
|
||||||
_min(o._min), _max(o._max) {
|
_min(o._min), _max(o._max) {
|
||||||
@@ -243,10 +250,12 @@ namespace xml {
|
|||||||
it!=o._contents.end(); ++it)
|
it!=o._contents.end(); ++it)
|
||||||
_contents.push_back((*it)->clone(this).release());
|
_contents.push_back((*it)->clone(this).release());
|
||||||
}
|
}
|
||||||
|
//! Assign new node, keep parent.
|
||||||
|
/*! The parent remains unchanged, the node does not belong to the
|
||||||
|
same parent as the source of the copy. */
|
||||||
Node& Node::operator=(const Node& o) throw() {
|
Node& Node::operator=(const Node& o) throw() {
|
||||||
_attributes=o._attributes;
|
_attributes=o._attributes;
|
||||||
_name = o.name();
|
_name = o.name();
|
||||||
_parent = 0;
|
|
||||||
_min = o._min;
|
_min = o._min;
|
||||||
_max = o._max;
|
_max = o._max;
|
||||||
for (Contents::const_iterator it(o._contents.begin());
|
for (Contents::const_iterator it(o._contents.begin());
|
||||||
@@ -257,11 +266,17 @@ namespace xml {
|
|||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
//! Clones But clears the parent.
|
//! Clones But clears the parent.
|
||||||
|
/*! You get a new instance of the node, but detached from the
|
||||||
|
parent. It is then ready to be inserted below a new parent. */
|
||||||
std::auto_ptr<Node> Node::clone() const throw() {
|
std::auto_ptr<Node> Node::clone() const throw() {
|
||||||
std::auto_ptr<Node> res(new Node(*this));
|
std::auto_ptr<Node> res(new Node(*this));
|
||||||
res->_parent = 0;
|
res->_parent = 0;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
//! Stream XML.
|
||||||
|
/*! Streams the node including all attributes and children. It is
|
||||||
|
formatted with new-lines and tabulator indentation for human
|
||||||
|
readability. */
|
||||||
std::ostream& Node::out(std::ostream& o, unsigned int level) const throw() {
|
std::ostream& Node::out(std::ostream& o, unsigned int level) const throw() {
|
||||||
if (_contents.size()) {
|
if (_contents.size()) {
|
||||||
o<<std::string(level, '\t')<<'<'<<name();
|
o<<std::string(level, '\t')<<'<'<<name();
|
||||||
@@ -282,6 +297,8 @@ namespace xml {
|
|||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
//! Get the textual contents of a node.
|
||||||
|
/*! By default this is the concatenation of all child nodes' texts. */
|
||||||
std::string Node::text() const throw() {
|
std::string Node::text() const throw() {
|
||||||
std::string s;
|
std::string s;
|
||||||
for (Contents::const_iterator it(_contents.begin());
|
for (Contents::const_iterator it(_contents.begin());
|
||||||
@@ -289,17 +306,27 @@ namespace xml {
|
|||||||
s+=***it;
|
s+=***it;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
//! Set a text (forbidden in xml::Node)
|
||||||
|
/*! This method is only useful for child nodes, where it is
|
||||||
|
reimplemented. In xml::Node, the parent of all nodes, it throws
|
||||||
|
xml::tag_expected, since a xml::Node may only contain sub-nodes
|
||||||
|
(formatted as xml-tags) and no plain text. */
|
||||||
Node& Node::text(const std::string& txt) throw(tag_expected, type_mismatch) {
|
Node& Node::text(const std::string& txt) throw(tag_expected, type_mismatch) {
|
||||||
throw tag_expected(*this, txt);
|
throw tag_expected(*this, txt);
|
||||||
}
|
}
|
||||||
|
//! Appends a new node at the end of all children.
|
||||||
Node& Node::append(const Node& o) throw(cannot_have_children) {
|
Node& Node::append(const Node& o) throw(cannot_have_children) {
|
||||||
_contents.push_back(o.clone(this).release());
|
_contents.push_back(o.clone(this).release());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//! Set a list of attributes.
|
||||||
|
/*! Existing attributes with the same name are overwritten. */
|
||||||
Node& Node::set(const Attributes& o) throw() {
|
Node& Node::set(const Attributes& o) throw() {
|
||||||
|
_attributes.clear();
|
||||||
_attributes.insert(o.begin(), o.end());
|
_attributes.insert(o.begin(), o.end());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//! Clears content and attributes.
|
||||||
Node& Node::clear() throw () {
|
Node& Node::clear() throw () {
|
||||||
for (Contents::const_iterator it(_contents.begin());
|
for (Contents::const_iterator it(_contents.begin());
|
||||||
it!=_contents.end(); ++it)
|
it!=_contents.end(); ++it)
|
||||||
@@ -308,67 +335,131 @@ namespace xml {
|
|||||||
_attributes.clear();
|
_attributes.clear();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//! Get the node's tag name.
|
||||||
std::string Node::name() const throw() {
|
std::string Node::name() const throw() {
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
//! Set minimum number of instances (in a xml::Factory).
|
||||||
|
/*! @copydoc limits */
|
||||||
Node& Node::min(Node::size_type m) throw() {
|
Node& Node::min(Node::size_type m) throw() {
|
||||||
_min = m;
|
_min = m;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//! Get minimum number of instances (in a xml::Factory).
|
||||||
|
/*! @copydoc limits */
|
||||||
Node::size_type Node::min() const throw() {
|
Node::size_type Node::min() const throw() {
|
||||||
return _min;
|
return _min;
|
||||||
}
|
}
|
||||||
|
//! Set maximum number of instances (in a xml::Factory).
|
||||||
|
/*! @copydoc limits */
|
||||||
Node& Node::max(Node::size_type m) throw() {
|
Node& Node::max(Node::size_type m) throw() {
|
||||||
_max = m;
|
_max = m;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//! Get maximum number of instances (in a xml::Factory).
|
||||||
|
/*! @copydoc limits */
|
||||||
Node::size_type Node::max() const throw() {
|
Node::size_type Node::max() const throw() {
|
||||||
return _max;
|
return _max;
|
||||||
}
|
}
|
||||||
|
//! @c true if node has a parent.
|
||||||
bool Node::isChild() const throw() {
|
bool Node::isChild() const throw() {
|
||||||
return _parent;
|
return _parent;
|
||||||
}
|
}
|
||||||
|
//! Get the parent node.
|
||||||
Node& Node::parent() const throw(no_parent) {
|
Node& Node::parent() const throw(no_parent) {
|
||||||
if (!_parent) throw no_parent(*this);
|
if (!_parent) throw no_parent(*this);
|
||||||
return *_parent;
|
return *_parent;
|
||||||
}
|
}
|
||||||
|
//! Check if a specific attribute is set or not.
|
||||||
bool Node::hasAttr(const std::string& name) const throw() {
|
bool Node::hasAttr(const std::string& name) const throw() {
|
||||||
return _attributes.find(name)!=_attributes.end();
|
return _attributes.find(name)!=_attributes.end();
|
||||||
}
|
}
|
||||||
|
//! Declare an attribute template and specify whether it is mandatory
|
||||||
|
/*! Used for setting up attributes in xml::Factory:
|
||||||
|
@code
|
||||||
|
xml::Factory f(xml::Node("root").attr("aname", xml::mandatory);
|
||||||
|
@endcode
|
||||||
|
If a factory reads from a stream, it verifies that only optional
|
||||||
|
or mandatory attributes are given and that mandatory attributes
|
||||||
|
are specified. Otherwise reading throws an exception. */
|
||||||
Node& Node::attr(const std::string& name, bool mandatory) throw() {
|
Node& Node::attr(const std::string& name, bool mandatory) throw() {
|
||||||
_attributes[name] = mandatory?"xml::mandatory":"xml::optional";
|
_attributes[name] = mandatory?"xml::mandatory":"xml::optional";
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//! Declare an attribute with given value.
|
||||||
|
/*! When used for setting up attributes in xml::Factory, it
|
||||||
|
specifies an optional attribute with given default value:
|
||||||
|
@code
|
||||||
|
xml::Factory f(xml::Node("root").attr("aname", "avalue");
|
||||||
|
@endcode
|
||||||
|
If a factory reads from a stream and the specified attribute is
|
||||||
|
not given, it is set to @c deflt. */
|
||||||
Node& Node::attr(const std::string& name, const std::string& deflt)
|
Node& Node::attr(const std::string& name, const std::string& deflt)
|
||||||
throw() {
|
throw() {
|
||||||
_attributes[name] = deflt;
|
_attributes[name] = deflt;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//! Get an attribute.
|
||||||
|
/*! Returns the attribute's value (empty if the attribute is not set) */
|
||||||
std::string Node::attr(const std::string& name) const throw() {
|
std::string Node::attr(const std::string& name) const throw() {
|
||||||
Attributes::const_iterator it(_attributes.find(name));
|
Attributes::const_iterator it(_attributes.find(name));
|
||||||
if (it!=_attributes.end()) return it->second;
|
if (it!=_attributes.end()) return it->second;
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
//! Get an attribute.
|
||||||
|
/*! Returns the attribute's value (empty if the attribute is not set) */
|
||||||
std::string& Node::attr(const std::string& name) throw() {
|
std::string& Node::attr(const std::string& name) throw() {
|
||||||
return _attributes[name];
|
return _attributes[name];
|
||||||
}
|
}
|
||||||
|
//! Get an attribute.
|
||||||
|
/*! Returns an attribute class or throws an exception if the
|
||||||
|
attribute is not set. This method is useful when you need
|
||||||
|
conversions or other methods as specified in
|
||||||
|
xml::Attributes::Value. */
|
||||||
const Attributes::Value Node::attribute(const std::string& name)
|
const Attributes::Value Node::attribute(const std::string& name)
|
||||||
const throw(attribute_not_available) {
|
const throw(attribute_not_available) {
|
||||||
Attributes::const_iterator it(_attributes.find(name));
|
Attributes::const_iterator it(_attributes.find(name));
|
||||||
if (it!=_attributes.end()) return *it;
|
if (it!=_attributes.end()) return *it;
|
||||||
throw attribute_not_available(*this, name);
|
throw attribute_not_available(*this, name);
|
||||||
}
|
}
|
||||||
|
//! Get the list of attributes.
|
||||||
const Attributes& Node::attributes() const throw() {
|
const Attributes& Node::attributes() const throw() {
|
||||||
return _attributes;
|
return _attributes;
|
||||||
}
|
}
|
||||||
|
//! Get the list of attributes.
|
||||||
Attributes& Node::attributes() throw() {
|
Attributes& Node::attributes() throw() {
|
||||||
return _attributes;
|
return _attributes;
|
||||||
}
|
}
|
||||||
|
//! Pass a minimal and maximal number for this node in a xml file.
|
||||||
|
/*! Minimal and maximal values are verified when you use the node as
|
||||||
|
a template in a xml::Factory. When the factory reads a stucture
|
||||||
|
from a stream through xml::Factory::read, then all the limits
|
||||||
|
are verified.
|
||||||
|
|
||||||
|
There are several ways to declare the limits.
|
||||||
|
- in the constructor xml::Node::Node
|
||||||
|
- minimum and maximum using method xml::Node::limits
|
||||||
|
- using methods xml::Node::min and xml::Node::max separately
|
||||||
|
|
||||||
|
It is recommended not to use the constructor, but the methods
|
||||||
|
xml::Node::limits, xml::Node::min and xml::Node::max, simply for
|
||||||
|
code readability.
|
||||||
|
|
||||||
|
The number @c 0 means unlimited: xml::Node::min(0) means the
|
||||||
|
value is optional and xml::Node::max(0) means that there is no
|
||||||
|
upper limit. The only exception for this rule is the root
|
||||||
|
element of a structure passed to a xml::Factory which must exist
|
||||||
|
exactly once.
|
||||||
|
|
||||||
|
Default is no limits: <code>0..n</code>,
|
||||||
|
which means that the node is optional and may be instatiated
|
||||||
|
multiple (infinite, unlimited) times. */
|
||||||
Node& Node::limits(size_type min, size_type max) throw() {
|
Node& Node::limits(size_type min, size_type max) throw() {
|
||||||
_min = min;
|
_min = min;
|
||||||
_max = max;
|
_max = max;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//! Get all children of a given node name
|
||||||
Node::List Node::list(const std::string& name) const throw() {
|
Node::List Node::list(const std::string& name) const throw() {
|
||||||
List res;
|
List res;
|
||||||
for (Contents::const_iterator it(_contents.begin());
|
for (Contents::const_iterator it(_contents.begin());
|
||||||
|
Reference in New Issue
Block a user