more docu; other behaviour for parent

master
Marc Wäckerlin 16 years ago
parent 2261c5b77d
commit 4e59d4cd01
  1. 4
      doc/doxyfile.in
  2. 5
      src/xml-cxx/xml.hxx
  3. 101
      src/xml.cxx

@ -639,13 +639,13 @@ SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body
# 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
# doxygen to hide any special comment blocks from generated source code
# 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)
# then for each documented function all documented

@ -424,9 +424,10 @@ namespace xml {
//----------------------------------------------------------------------------
class String: public Node {
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,
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 ~String() throw() {}
virtual std::string text() const throw();

@ -170,9 +170,9 @@ namespace xml {
return second;
}
//! Convert the attribute to a boolean.
/*! @return @c true if the value is set and not equal to one of:
@c false @c no @c 0. */
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");
}
//! Convert the attribute to a number.
@ -186,7 +186,8 @@ namespace xml {
Attributes::Value::operator List() const throw() {
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)
const throw() {
List l;
@ -200,6 +201,8 @@ namespace xml {
l.push_back(second.substr(it, pos-it));
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
throw(empty_attribute_list) {
List l(toList(separators));
@ -231,11 +234,15 @@ namespace xml {
//----------------------------------------------------------------------------
//! Nodes must be given a name.
/*! Unnamed nodes are not allowed, therefore there's no default
constructor. */
constructor.
@copydoc xml::Node::limits */
Node::Node(std::string name,
Node::size_type min, Node::size_type max) throw():
_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():
_attributes(o._attributes), _name(o.name()), _parent(0),
_min(o._min), _max(o._max) {
@ -243,10 +250,12 @@ namespace xml {
it!=o._contents.end(); ++it)
_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() {
_attributes=o._attributes;
_name = o.name();
_parent = 0;
_min = o._min;
_max = o._max;
for (Contents::const_iterator it(o._contents.begin());
@ -257,11 +266,17 @@ namespace xml {
clear();
}
//! 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> res(new Node(*this));
res->_parent = 0;
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() {
if (_contents.size()) {
o<<std::string(level, '\t')<<'<'<<name();
@ -282,6 +297,8 @@ namespace xml {
}
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 s;
for (Contents::const_iterator it(_contents.begin());
@ -289,17 +306,27 @@ namespace xml {
s+=***it;
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) {
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) {
_contents.push_back(o.clone(this).release());
return *this;
}
//! Set a list of attributes.
/*! Existing attributes with the same name are overwritten. */
Node& Node::set(const Attributes& o) throw() {
_attributes.clear();
_attributes.insert(o.begin(), o.end());
return *this;
}
//! Clears content and attributes.
Node& Node::clear() throw () {
for (Contents::const_iterator it(_contents.begin());
it!=_contents.end(); ++it)
@ -308,67 +335,131 @@ namespace xml {
_attributes.clear();
return *this;
}
//! Get the node's tag name.
std::string Node::name() const throw() {
return _name;
}
//! Set minimum number of instances (in a xml::Factory).
/*! @copydoc limits */
Node& Node::min(Node::size_type m) throw() {
_min = m;
return *this;
}
//! Get minimum number of instances (in a xml::Factory).
/*! @copydoc limits */
Node::size_type Node::min() const throw() {
return _min;
}
//! Set maximum number of instances (in a xml::Factory).
/*! @copydoc limits */
Node& Node::max(Node::size_type m) throw() {
_max = m;
return *this;
}
//! Get maximum number of instances (in a xml::Factory).
/*! @copydoc limits */
Node::size_type Node::max() const throw() {
return _max;
}
//! @c true if node has a parent.
bool Node::isChild() const throw() {
return _parent;
}
//! Get the parent node.
Node& Node::parent() const throw(no_parent) {
if (!_parent) throw no_parent(*this);
return *_parent;
}
//! Check if a specific attribute is set or not.
bool Node::hasAttr(const std::string& name) const throw() {
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() {
_attributes[name] = mandatory?"xml::mandatory":"xml::optional";
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)
throw() {
_attributes[name] = deflt;
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() {
Attributes::const_iterator it(_attributes.find(name));
if (it!=_attributes.end()) return it->second;
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() {
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 throw(attribute_not_available) {
Attributes::const_iterator it(_attributes.find(name));
if (it!=_attributes.end()) return *it;
throw attribute_not_available(*this, name);
}
//! Get the list of attributes.
const Attributes& Node::attributes() const throw() {
return _attributes;
}
//! Get the list of attributes.
Attributes& Node::attributes() throw() {
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() {
_min = min;
_max = max;
return *this;
}
//! Get all children of a given node name
Node::List Node::list(const std::string& name) const throw() {
List res;
for (Contents::const_iterator it(_contents.begin());

Loading…
Cancel
Save