more docu
This commit is contained in:
@@ -11,9 +11,4 @@ nobase_include_HEADERS = xml-cxx/xml.hxx
|
||||
|
||||
libxml_cxx_la_SOURCES = xml.cxx
|
||||
|
||||
if BUILD_WIN
|
||||
else
|
||||
endif
|
||||
|
||||
CLEANFILES =
|
||||
MAINTAINERCLEANFILES = makefile.in
|
||||
|
@@ -15,17 +15,72 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
/*! @page limitations Known Limitations
|
||||
/*! @mainpage
|
||||
|
||||
- Templates cannot specify number of sub-elements.
|
||||
- XML-Comments are only ignored.
|
||||
@section maintitle C++ XML Class Library
|
||||
|
||||
- Specify your XML schema in C++ using common C++ syntax,
|
||||
such as shift, dereference, etc.
|
||||
- Verify the schema of XML files while they are read from a stream.
|
||||
|
||||
From the README file:
|
||||
@include README
|
||||
|
||||
@page Known Limitations
|
||||
|
||||
- XML-Comments are only ignored, not read, not stored.
|
||||
- Mixed tags and text is not supported. Tags may either contain
|
||||
other tags only (type xml::Node) or text only (type
|
||||
xml::String).
|
||||
xml::String). -> This is intended behaviour!
|
||||
- Unlimited recursion is not possible
|
||||
(e.g. <p><p><p></p></p></p>)
|
||||
- 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")
|
||||
|
||||
@page rationale Rationale - Limitations of other libraries
|
||||
|
||||
The initial idea was to map C++ data structures to XML files
|
||||
(e.g. for configuration files) that can easily be edited by
|
||||
hand. This library does not need any kind of C++ code parser or
|
||||
proprietary pre compiler. You can specify a schema entirly in
|
||||
native C++. Access to the XML structures is through typical C++
|
||||
operators which rresults in a simple and intuitive syntax. The
|
||||
schema is verified when XML is read and exceptions are thrown when
|
||||
the XML to be pares is invalid. Exceptions specify exactly the
|
||||
location and reason of the problem, so that the editor of the XML
|
||||
file can easily find and correct the problem. Due to the
|
||||
verification, it is not necessary to check every access: Only
|
||||
optional attributes and tags must be tested for their existence,
|
||||
before they can be accessed.
|
||||
|
||||
There are a lot of different approaches for using XML in C++, all
|
||||
of them have their specific limitations. This library should be
|
||||
better.
|
||||
|
||||
The design is based on my experiance with gsoap
|
||||
(http://gsoap.sf.net), boost serialization (http://boost.org) and
|
||||
Qt XML (http://qtsoftware.com).
|
||||
|
||||
@section Qt XML, a typical DOM approach
|
||||
|
||||
One is the XML part of the Qt library. These classes can read XML
|
||||
into a DOM tree, but then the user has to check for every detail.
|
||||
This looks like:
|
||||
|
||||
@code
|
||||
QDomDocument doc;
|
||||
if (!doc.setContent(_http.readAll())); // error
|
||||
QDomNodeList releases(doc.elementsByTagName("release"));
|
||||
for(int i(0); i<releases.size(); ++i)
|
||||
if (releases.at(i).attributes().contains("type") &&
|
||||
releases.at(i).attributes().namedItem("type").nodeValue()==_name) {
|
||||
_software = releases.at(i).firstChildElement("software");
|
||||
_firmware = releases.at(i).firstChildElement("firmware");
|
||||
if (_software.isNull() || _firmware.isNull() ||
|
||||
releases.at(i).firstChildElement("notes").isNull()); // error
|
||||
...
|
||||
@endcode
|
||||
|
||||
@example doc/examples/address.cxx */
|
||||
|
||||
//! 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++.
|
||||
|
68
src/xml.cxx
68
src/xml.cxx
@@ -244,7 +244,7 @@ namespace xml {
|
||||
//! Copy node, reset parent.
|
||||
/*! The parent is reset, the node does not belong to the same parent
|
||||
as the source of the copy.
|
||||
@see xml::Node::clone for more information on the parenting. */
|
||||
@see xml::Node::clone() for more information on the parenting. */
|
||||
Node::Node(const Node& o) throw():
|
||||
_attributes(o._attributes), _name(o.name()), _parent(0),
|
||||
_min(o._min), _max(o._max) {
|
||||
@@ -255,7 +255,7 @@ namespace xml {
|
||||
//! Assign new node, keep parent.
|
||||
/*! The parent remains unchanged, the node does not belong to the
|
||||
same parent as the source of the copy.
|
||||
@see xml::Node::clone for more information on the parenting. */
|
||||
@see xml::Node::clone() for more information on the parenting. */
|
||||
Node& Node::operator=(const Node& o) throw() {
|
||||
_attributes=o._attributes;
|
||||
_name = o.name();
|
||||
@@ -270,7 +270,18 @@ namespace xml {
|
||||
}
|
||||
//! 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. */
|
||||
parent. It is then ready to be inserted below a new parent.
|
||||
|
||||
If you clone (or copy) a node, the parent is not copied. This is
|
||||
because otherwise the new now would need to be appended to the
|
||||
parent's child list. That's most probably not
|
||||
intended. Therefore, in a normal copy construction the parent is
|
||||
set to @c 0 (no parent). Then the new node can be appended to a
|
||||
parent if needed. In a copy assignment, the parent remains
|
||||
uncanged and the other data is copied.
|
||||
|
||||
The user of this library doesn't have to and is not able to care
|
||||
about the parenting. */
|
||||
std::auto_ptr<Node> Node::clone() const throw() {
|
||||
std::auto_ptr<Node> res(new Node(*this));
|
||||
res->_parent = 0;
|
||||
@@ -544,13 +555,6 @@ namespace xml {
|
||||
return 0;
|
||||
}
|
||||
//! Clone a node, but assign a new parent.
|
||||
/*! If you clone (or copy) a node, the parent is not copied. This is
|
||||
because otherwise the new now would need to be appended to the
|
||||
parent's child list. That's most probably not
|
||||
intended. Therefore, in a normal copy operation (copy-construct
|
||||
or copy-assign) the parent is set to @c 0 (no parent). Then the
|
||||
new node can be appended to a parent if needed. In this method,
|
||||
the new parent can be given in the same step. */
|
||||
std::auto_ptr<Node> Node::clone(Node* p) const throw() {
|
||||
std::auto_ptr<Node> c(clone());
|
||||
c->_parent = p;
|
||||
@@ -643,9 +647,11 @@ namespace xml {
|
||||
_text = ss.str();
|
||||
return *this;
|
||||
}
|
||||
//! Returns the contents as number.
|
||||
unsigned long UnsignedInteger::number() const throw() {
|
||||
return number(*this);
|
||||
}
|
||||
//! Returns the contents as number.
|
||||
unsigned long UnsignedInteger::number(const Node& node) throw() {
|
||||
unsigned long i(0);
|
||||
std::stringstream ss(node.text());
|
||||
@@ -654,6 +660,48 @@ namespace xml {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//! To instanciate a factory, a template must be given.
|
||||
/*! The template is a node that specifies the schema of the data
|
||||
that can be loaded from streams through a xml::Factory
|
||||
instance.
|
||||
|
||||
The root element has automatically set the limits 1..1
|
||||
(<code>xml::Node::limits(1, 1)</code>, see xml::Node::limits),
|
||||
which means that the root element must exist exactly once. If
|
||||
you pass another limit, your limit is overwritten.
|
||||
|
||||
E.g. to load an address, that contains a tag <address>
|
||||
with at least a name and optional an address in it's body, you
|
||||
may write:
|
||||
|
||||
@code
|
||||
xml::Factory addrTpl(xml::Node("address")
|
||||
(<<xml::Node("name").limit(1, 1)
|
||||
(<<xml::String("first").limit(1, 1)
|
||||
<<xml::String("middle") // 0..n -> .limit(0, 0)
|
||||
<<xml::String("last").limit(1, 1))
|
||||
<<(xml::Node("location").max(1)
|
||||
<<xml::String("line").min(1))
|
||||
<<xml::String("country").max(1)));
|
||||
@endcode
|
||||
|
||||
According to this example, a valid XML file could be:
|
||||
|
||||
@verbatim
|
||||
<address>
|
||||
<name>
|
||||
<first>Marc</first>
|
||||
<middle>Roman</middle>
|
||||
<last>Wäckerlin</last>
|
||||
</name>
|
||||
<location>
|
||||
<line>SwissSign AG</line>
|
||||
<line>Pfingstweidstrasse 60b</line>
|
||||
<line>8005 Zürich</line>
|
||||
</location>
|
||||
<country>Schweiz</country>
|
||||
</address>
|
||||
@endverbatim */
|
||||
Factory::Factory(const Node& t) throw():
|
||||
_template(xml::Node("<xml::start>")<<t), _line(0) {
|
||||
_template[0].min(1);
|
||||
|
Reference in New Issue
Block a user