## Introduction

### XML Parser

Libzeep comes with a validating XML parser. Using this parser is as simple as writing:

    #include <zeep/xml/document.hpp>
    #include <fstream>

    int main()
    {
    	std::ifstream file("test.xml");
    	zeep::xml::document doc(file);
    	...
    }

This will parse the file `text.xml` and create an object `doc` containing the DOM tree. To traverse this tree you can use the various member functions of doc which derives from the generic `zeep::xml::container` class. Siblings in the DOM tree are stored as linked lists and some elements can have children. To make life easier, you can iterate over elements using STL iterators.

Suppose our `test.xml` file contains the following XML:

    <persons>
    	<person>
    		<firstname>John</firstname>
    		<lastname>Doe</lastname>
    	</person>
    	<person>
    		<firstname>Jane</firstname>
    		<lastname>Jones</lastname>
    	</person>
    </persons>

You could print out the file like this:

    // a document contains at most one child node
    zeep::xml::element* persons = doc.child();

    // begin/end will return iterators to elements
    for (zeep::xml::container::iterator person = persons->begin(); person != persons->end(); ++person)
    {
    	for (zeep::xml::container::iterator name = (*person)->begin(); name != (*person)->end(); ++name)
    		std::cout << (*name)->name() << " = " << (*name)->content() << std::endl;
    }

Of course, using the new for loop construct, this code would be much more readable:

    for (auto person : *persons)
    {
    	for (auto name : *person)
    		std::cout << name->name() << " = " << name->content() << std::endl;
    }

But if your compiler does not support that syntax, you can always use `boost::range` instead:

    BOOST_FOREACH (zeep::xml::element* person, *persons)
    {
    	BOOST_FOREACH (zeep::xml::element* name, *person)
    		std::cout << name->name() << " = " << name->content() << std::endl;
    }

Accessing attributes is done using the member function `element::get_attribute()`.

### XML Serialization

An alternative way to read/write XML files is using serialization. To do this, we first construct a structure called Person. We add a templated function to this struct just like in `boost::serialize` and then we can read the file.

    #include <zeep/xml/document.hpp>
    #include <zeep/xml/serialize.hpp>
    #include <vector>
    #include <fstream>

    struct Person
    {
    	std::string firstname;
    	std::string lastname;

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

    int main()
    {
    	std::ifstream file("test.xml");
    	zeep::xml::document doc(file);

    	zeep::xml::deserializer ds(doc.child());
    	std::vector<Person> person;

    	// the variable name person must be the same as the name of the XML element person
    	ds & BOOST_SERIALIZATION_NVP(person);

    	// alternative is to use which allows another variable name:
    	// ds & boost::serialization::make_nvp("person", person);
    }

Since libzeep 3.0 we can reduce the code required.

    int main()
    {
    	std::ifstream file("test.xml");
    	zeep::xml::document doc(file);

    	std::vector<Person> persons;

    	// New way of deserializing persons
    	doc.deserialize("persons", persons);
    }

And to write out the persons, we do something similar.

    zeep::xml::document doc;
    doc.serialize("persons", persons);

    std::ofstream file("test-out.xml");
    file << doc;

To find out more about serialization, look at the reference for `zeep::xml::serializer`

### XPath 1.0

Libzeep comes with a XPath 1.0 implementation. You can use this to locate elements in a DOM tree easily. For a complete description of the XPath specification you should read the documentation at e.g. http://www.w3.org/TR/xpath/ or http://www.w3schools.com/xpath/default.asp.

The way it works in libzeep is that you can call `find()` on an `zeep::xml::element` object and it will return a zeep::xml::element_set object which is actually a `std::list` of `zeep::xml::element` pointers of the elements that conform to the specification in XPath passed as parameter to `find()`. An alternative method `find_first()` can be used to return only the first element.

An example where we look for the first person in our test file with the lastname Jones:

    zeep::xml::element* jones = doc.child()->find_first("//person[lastname='Jones']");

### HTTP Server

Creating a HTTP server with libzeep is as simple as:

    #include <zeep/http/server.hpp>

    class my_server : public zeep::http::server
    {
    	virtual void handle_request(const zeep::http::request& req, zeep::http::reply& rep)
    	{
    		...	// do something useful
    	}
    };

    int main()
    {
    	my_server server;
    	server.bind("0.0.0.0", 80);
    	server.run(1);
    }

Of course you will have to fill in the `handle_request` part...

### SOAP Server

Setting up a SOAP server is very easy. Let's continue with our test file and serve it as a SOAP/REST server. We already created the Person struct. The most simple server we can create is one that lists all persons in the test file:

    #include <zeep/server.hpp>
    #include <fstream>

    using namespace std;

    ... // define the Person struct as above

    class my_server : public zeep::server
    {
      public:
    	my_server();

    	// The method we want to export
    	void ListPersons(vector<Person>& result);
    };

    void my_server::ListPersons(vector<Person>& result)
    {
    	std::ifstream file("test.xml");
    	zeep::xml::document doc(file);

    	zeep::xml::deserializer ds(doc.child());
    	ds & boost::serialization::make_nvp("person", result);
    }

    my_server::my_server() : zeep::server("http://www.example.org/soaptest", "soaptest")
    {
    	// assign a name to the Person struct (will appear in the WSDL e.g.)
    	zeep::xml::serialize_struct<Person>::set_struct_name("person");

    	// assign names to the parameters of the exported method, in this case there's only
    	// one return value to name
    	const char* kListPersonsParameterNames[] = { "response" };
    	register_action("ListPersons", this, &my_server::ListPersons, kListPersonsParameterNames);
    }

    int main()
    {
    	my_server server;
    	server.bind("192.168.0.1", 8083);
    	server.run(1);	// keep our server single threaded
    }

After building this server and running it, you can access the REST version of this routine at http://192.168.0.1:8083/rest/ListPersons and there's a WSDL at http://192.168.0.1:8083/wsdl