libzeep documentation
Author: Maarten L. Hekkelman

## Contents

- Introduction
- Examples
- Reference

## Introduction

### The XML library

libzeep is a library that consists of two main parts. The first and arguably most useful for many is the XML processing part. It consists of a SAX parser, a DOM implementation, an XML writing module and an XPath implementation. The parser can act as a validating parser using the Document Type Definition to check the content. Schema support is not yet implemented but will be in a future release.

The second part of libzeep (and the part it all started with, hence the name) is a skeleton to build SOAP server implementations. It uses the XML part as well as various Boost libraries to achieve its usefulness. It allows the creation of a SOAP server by implementing only the serving routines in C++ and calling a routine for each to export of them. Code is then automatically generated to do all the SOAP message parsing and WSDL's generation occurs on-the-fly at runtime.

libzeep comes with headers and libraries. The headers all have `zeep` as namespace. All code heavily depends on the boost libraries.

## Examples

Using libzeep is fairly straightforward. E.g., if we take the following XML file:

    <?xml version="1.0" encoding="UTF-8"?>
    <employees>
      <employee>
        <name id="1">Joe Doe</name>
        <address>Main street</address>
      </employee>
      <employee>
        <name id="2">Jack Daniels</name>
        <address>Backstreet</address>
      </employee>
    </employees>

Reading this file is simple:

    #include <zeep/xml/document.hpp>

    using namespace zeep;
    using namespace std;

    ifstream data("/tmp/myfile.xml");
    xml::document doc;
    data >> doc;

The result of this code is a DOM tree with `doc` as root. An `xml::document` is derived from `xml::element` and can only have one `xml::element` child. Since it is a DOM tree, and since it is implemented in the classic link-list approach, you can use the `next()`, `prev()`, `parent()` and `child()` methods to navigate the tree.

But to stick to STL coding styles, walking a tree can also be done using the `children()` method which returns a `std::list` of pointers to its children. This method is templated since an element can have non-element child nodes like comments and processing instruction but most often you're only interested in the element child nodes.

Using the `children` method, iterating over all employees can be done like this:

    // iterate over employees
    xml::element_set employees = doc.root()->children<xml::element>();
    for (xml::element_set::iterator employee = employees.begin(); employee != employees.end(); ++employee)
    {
    	// employee points to an element and we want its first child
    	xml::element* name = (*employee)->child();
    	// it really should be a name, right?
    	assert(name->qname() == "name");
        cout << "Name: " << name->content() << endl;
    }

Of course, using Boost's foreach this looks a lot nicer:

    // iterate over employees, boost foreach style
    #include <boost/foreach.hpp>
    #define foreach BOOST_FOREACH

    ...

    for (xml::element* employee, doc.root()->children<xml::element>())
    {
    	xml::element* name = (*employee)->child();
    	...
    }

Still, we can do better. Using XPaths. Just like the `children()` method of `xml::element` the xpath evaluation method returns all nodes, if you're only interested in `xml::element` nodes, you can specify this.

    #include <boost/foreach.hpp>
    #define foreach BOOST_FOREACH

    ...

    xpath p("//employee/name");

    for (xml::element* name, p.evaluate<xml::element>(doc))
    {
        cout << "Name: " << name->content() << endl;
    }

The `find` method of `xml::element` is a shortcut to `xpath::evaluate()`, it always returns `xml::element` nodes.

    for (xml::element* name = doc.find("//employee/name"))
        cout << "Name: " << name->content() << endl;

The XPath implementation in libzeep implements the full XPath 1.0 specification. That means you can also do this:

    // Fetch Jack's record by name:
    xml::element* jack = doc.find_first("//employee[name = 'Jack Daniels']");

    // or by id:
    jack = doc.find_first("//employee[@id='2']");

    // or by position in the list, jack is always last...
    jack = doc.find_first("//employee[position() = last()]");

You can even use variables:

    // Fetch Jack's record by name:
    xml::context context;
    context.set("var", "Jack Daniels");
    xml::xpath xpath("//employee[name = $var]");

    xml::element* jack = xpath.evaluate(*doc.root(), context).front();

### SOAP server

This comes from the man page for the 1.0 version of libzeep. I'll have to improve this one day:

    libzeep(3)                        subroutine                        libzeep(3)

    NAME
           libzeep - A C++ library to create SOAP servers

    SYNOPSIS
           #include <zeep/server.hpp>

           class my_server : public zeep::server
           {
             public:
               my_server(const char* addr, short port);
               void sum(int a, int b, int& c) { c = a + b; }
           };

           my_server::my_server(const char* addr, short port)
             : zeep::server("http//www.acme.org/...", addr, port)
           {
             const char kSumParameterNames[] = { "a", "b", "c" };
             register_action("sum", this, &my_server::sum, kSumParameterNames);
           }

            ...

           my_server server("0.0.0.0", 10333);
           boost::thread t(boost::bind(&my_server::run, &server));
           // and wait for a signal to stop using e.g. sigwait(3)

    DESCRIPTION
           Using   libzeep   you  can  create  a  SOAP  server  by  deriving  from
           zeep::server.  In the constructor of your server,  you  call  the  base
           class  constructor  with three arguments: ns, a namespace for your SOAP
           server, address, the address to listen to, usually "0.0.0.0" to  listen
           to all available addresses. And port, the port number to bind to.

           SOAP actions are simply members of the server object and are registered
           using the register_action member  function  of  the  zeep::server  base
           class.  After  initializing the server object, the run member is called
           and the server then starts listening to the address and port specified.

           The resulting web service application will  process  incoming  request.
           There  are  three kinds of requests, the server can return an automati-
           cally generated WSDL, it can process standard SOAP message send in SOAP
           envelopes  and  it  can  handle REST style requests which are mapped to
           corresponding SOAP messages internally.

           The signature of the registered actions are used to  generate  all  the
           code needed to serialize and deserialize SOAP envelopes and to create a
           corresponding WSDL file. The signature can be as simple as the  example
           above but can also be as complex as in this one:

             void myAction(
                    const std::vector<MyStructIn>& input,
                    MyStructOut& output);

           In  order to make this work, you have to notify the library of the map
           ping  of  your   structure   type   to   a   name   using   the   macro
           SOAP_XML_SET_STRUCT_NAME like this:

                    SOAP_XML_SET_STRUCT_NAME(MyStructIn);
                    SOAP_XML_SET_STRUCT_NAME(MyStructOut);

           Next  to  this,  you have to provide a way to serialize and deserialize
           your structure. For this,  libzeep  uses  the  same  mechanism  as  the
           Boost::serialize  library, which means you have to add a templated mem
           ber function called serialize to your structure. The result  will  look
           like this:

           struct MyStructIn {
             string myField1;
             int myField2;

             template<class Archive>
             void serialize(Archive& ar, const unsigned int version)
             {
               ar & BOOST_SERIALIZATION_NVP(myField1)
                  & BOOST_SERIALIZATION_NVP(myField2);
             }
           };

           Similarly  you  can  use  enum's in an action signature or as structure
           member variables. Again we need to tell the library the type  name  for
           the   enum  and  the  possible  enum  values.  We  do  this  using  the
           SOAP_XML_ADD_ENUM macro, like this:

              enum MyEnum { "one", "two" };
              SOAP_XML_ADD_ENUM(myEnum, one);
              SOAP_XML_ADD_ENUM(myEnum, two);

           As shown above, you can also use std::vector containers in  the  signa-
           ture  of  actions.  Support for other STL containers is not implemented
           yet.

           If the address used by clients of your server  is  different  from  the
           address  of  your  local  machine  (which can happen if you're behind a
           reverse proxy e.g.) you can specify the location using the set_location
           member  function  of  zeep::server.  The specified address will then be
           used in the WSDL file.

    BUGS
           Undoubtedly libzeep will contain bugs. One of the more obvious  one  is
           the  missing  support  for  signatures  using STL containers other than
           std::vector.

    version 1.0                       12-jan-2009                       libzeep(3)

## Reference

Well, read the code for now. If I can find the time I will do better.