diff --git a/doc/examples/address.cxx b/doc/examples/address.cxx index 52803ad..2e76989 100644 --- a/doc/examples/address.cxx +++ b/doc/examples/address.cxx @@ -5,7 +5,7 @@ // 1 2 3 4 5 6 7 8 // 45678901234567890123456789012345678901234567890123456789012345678901234567890 -// g++ -I../src ../src/xml.cxx address.cxx +// g++ -I../../src ../../src/xml.cxx address.cxx #include #include diff --git a/doc/examples/node_macros.cxx b/doc/examples/node_macros.cxx new file mode 100644 index 0000000..7ce2a97 --- /dev/null +++ b/doc/examples/node_macros.cxx @@ -0,0 +1,32 @@ +/*! @file + + @id $Id$ +*/ +// 1 2 3 4 5 6 7 8 +// 45678901234567890123456789012345678901234567890123456789012345678901234567890 + +// g++ -I../../src ../../src/xml.cxx node_macros.cxx + +#include +#include +#include + +XML_NODE(base); +XML_NODE(child); +XML_STRING(element); + +int main(int, char**) { + xml::Factory test(*xml::node::base.clone() + <<(*xml::node::child.clone() + <<*xml::string::element.clone())); + std::stringstream ss("\n" + " \n" + " Hello\n" + " \n" + ""); + std::auto_ptr file(test.read(ss)); + std::cout<<"The text in element is: " + <<(*file)[xml::name::child][xml::name::element].text() + < +#include +#include +/* +template class Stream: public STREAM { + public: + virtual ~Stream() {} + template virtual Stream& operator%(T& o); +}; + +template class IStream: public Stream { + public: + virtual template IStream& operator%(T& o) { + operator>>(o); + return *this; + } +}; + +template class OStream: public Stream { + public: + virtual template OStream& operator%(T& o) { + operator<<(o); + return *this; + } +}; + */ + +template + STREAM& operator%(STREAM& s, TYPE& o); +template + STREAM& operator%(STREAM& s, TYPE& o); + +class A { + public: + int a; + std::string txt; +}; + +int main(int, char**) { + return 0; +} diff --git a/src/xml-cxx/xml.hxx b/src/xml-cxx/xml.hxx index 73d0a96..85b7452 100644 --- a/src/xml-cxx/xml.hxx +++ b/src/xml-cxx/xml.hxx @@ -80,7 +80,7 @@ ... @endcode - @example doc/examples/address.cxx */ + @example address.cxx */ /*! @defgroup serialization Class Serialization @@ -201,28 +201,119 @@ xml::Factory _xmlFactory //@} -//! Deefine a string for a node name -/*! Put this macro in the global part of your header files. After - declaration of e.g. XML_NODE(tagname) you can use - xml::node::tagname as constant std::string with - contents @c "tagname" in your code. +/*! @defgroup xmlConst XML Constant Declarations - @code - XML_NAME(base); - XML_NAME(child); + There are macros to help you with declaring constants. Chose a C++ + header fiel, where you want to declare constant names for your xml + nodes. + + Then for every leaf xml::Node name you will use, call + XML_NODE(name) and for every xml::String call XML_STRING(name). + + For every node with children call XML_PARENT(name, child1, child2 ...). + + @note Node names must be unique. You can not even use the same + name for a XML_NODE and a XML_STRING declaration. + + This code is from the examples: + + @include node_macros.cxx + + @example node_macros.cxx + + The example code is equivalent to: + @code int main(int, char**) { - xml::Factory test(xml::Node(xml::node::base) + xml::Factory test(xml::Node("base") + <<(xml::Node("child") + <\n" + " \n" + " Hello\n" + " \n" + ""); + std::auto_ptr file(test.read(ss)); + std::cout<<"The element is: " + <<(*file)["child"]["element"] + <using + namespace xml::name in your C++ implementation files, since + names are more often used than nodes. (@em Never use @c using in a + C++ header file, you would pollute the scope of all the + includers.) */ +//@{ + +//! Define a string for a node name +/*! It is called inside XML_NODE and XML_STRING, so if you work with + these two, you don't have to care about XML_NAME. But you can use + XML_NAME alone if you don't want the other two macros. + @see XML_NODE + @see XML_STRING */ +#define XML_NAME(NAME) \ + namespace xml {\ + namespace name {\ + static const std::string NAME(#NAME); \ + }\ + } + +//! Define a constant for a xml::Node and for a string containing its name +/*! Put this macro in the global part of your header files. After + declaration of e.g. XML_NODE(tagname) you can use + xml::node::tagname as constant xml::Node and + xml::name::tagname as a constant std::string with + contents @c "tagname" in your code. + @see XML_STRING same for xml::String + @see XML_NAME called by XML_NODE */ +#define XML_NODE(NAME) \ + XML_NAME(NAME);\ namespace xml {\ namespace node {\ - static const std::string xml::Node NAME(#name);\ + static const xml::Node NAME(#NAME);\ }\ } +//! Define a constant for a xml::String and for a string containing its name +/*! Put this macro in the global part of your header files. After + declaration of e.g. XML_STRING(tagname) you can use + xml::string::tagname as constant xml::String and + xml::name::tagname as a constant std::string with + contents @c "tagname" in your code. + @see XML_NODE same for xml::Node + @see XML_NAME called by XML_STRING */ +#define XML_STRING(NAME) \ + XML_NAME(NAME);\ + namespace xml {\ + namespace string {\ + static const xml::String NAME(#NAME);\ + }\ + } + +//! @todo Define a constant for a xml::Node and for a string containing its name +/*! Put this macro in the global part of your header files. After + declaration of e.g. XML_NODE(tagname) you can use + xml::node::tagname as constant xml::Node and + xml::name::tagname as a constant std::string with + contents @c "tagname" in your code. + @see XML_STRING same for xml::String + @see XML_NAME called by XML_NODE */ +#define XML_PARENT(NAME, ...) \ + XML_NAME(NAME);\ + namespace xml {\ + namespace node {\ + static const xml::Node NAME(#NAME);\ + }\ + } + +//@} + //! 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++. @@ -564,8 +655,8 @@ namespace xml { typedef std::vector List; Node(std::string name, size_type min=0, size_type max=0) throw(); Node(const Node& o) throw(); - Node& operator=(const Node& o) throw(); virtual ~Node() throw(); + virtual Node& operator=(const Node& o) throw(); virtual std::auto_ptr clone() const throw(); virtual std::ostream& out(std::ostream& o, unsigned int level=0) const throw(); @@ -626,8 +717,8 @@ namespace xml { Node::size_type min=0, Node::size_type max=0) throw(); String(std::string name, const std::string& text, Node::size_type min=0, Node::size_type max=0) throw(); - virtual std::auto_ptr clone() const throw(); virtual ~String() throw() {} + virtual std::auto_ptr clone() const throw(); virtual std::string text() const throw(); virtual String& text(const std::string& txt) throw(tag_expected, type_mismatch); diff --git a/src/xml.cxx b/src/xml.cxx index a859727..013c726 100644 --- a/src/xml.cxx +++ b/src/xml.cxx @@ -252,6 +252,9 @@ namespace xml { it!=o._contents.end(); ++it) _contents.push_back((*it)->clone(this).release()); } + Node::~Node() throw() { + clear(); + } //! Assign new node, keep parent. /*! The parent remains unchanged, the node does not belong to the same parent as the source of the copy. @@ -265,9 +268,6 @@ namespace xml { it!=o._contents.end(); ++it) _contents.push_back((*it)->clone(this).release()); } - Node::~Node() throw() { - 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.