diff --git a/CMake/FindLibXMLxx.cmake b/CMake/FindLibXMLxx.cmake
index ca3888b7f1077d3ea4ae2257ebb3a97b474e738f..ce73e576e7781471091d525798543b137113e69c 100644
--- a/CMake/FindLibXMLxx.cmake
+++ b/CMake/FindLibXMLxx.cmake
@@ -30,4 +30,12 @@ if(NOT LIBXMLXX_FOUND)
   include(FindPkgConfig)
   pkg_search_module(LIBXMLXX REQUIRED libxml++-2.8 libxml++-2.7 libxml++-2.6 libxml++-2.5)
   mark_as_advanced(LIBXMLXX_INCLUDE_DIRS LIBXMLXX_LIBRARIES)
+
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(LIBXMLXX DEFAULT_MSG
+    LIBXMLXX_LIBRARIES LIBXMLXX_INCLUDE_DIRS)
+
+  set(LIBXMLXX_LIBRARY     "${LIBXMLXX_LIBRARIES}"    CACHE LIST "LibXML++ libraries")
+  set(LIBXMLXX_INCLUDE_DIR "${LIBXMLXX_INCLUDE_DIRS}" CACHE LIST "LibXML++ include dirs")
+
 endif(NOT LIBXMLXX_FOUND)
diff --git a/LCS/MessageBus/CMakeLists.txt b/LCS/MessageBus/CMakeLists.txt
index 2a8d283d6ece24acb3cf4fb01c30b40e291ed247..41113fb9e24557eb4f044f12f7be3e99f53068a2 100644
--- a/LCS/MessageBus/CMakeLists.txt
+++ b/LCS/MessageBus/CMakeLists.txt
@@ -4,6 +4,7 @@ lofar_package(MessageBus 1.0 DEPENDS Common pyparameterset)
 
 include(LofarFindPackage)
 lofar_find_package(QPID)
+lofar_find_package(LibXMLxx)
 lofar_find_package(UnitTest++)
 
 add_subdirectory(include/MessageBus)
diff --git a/LCS/MessageBus/include/MessageBus/Message.h b/LCS/MessageBus/include/MessageBus/Message.h
index b6ada16d93f8221187e4e895756a11db348fc873..3cf9cc0439dc1958ef5011caeba312ce2a8b0641 100644
--- a/LCS/MessageBus/include/MessageBus/Message.h
+++ b/LCS/MessageBus/include/MessageBus/Message.h
@@ -30,6 +30,10 @@
 #include <MessageBus/NoQpidFallback.h>
 #endif
 
+#ifdef HAVE_LIBXMLXX
+#include <libxml++/parsers/domparser.h>
+#endif
+
 #include <string>
 #include <ostream>
 
@@ -91,13 +95,17 @@ public:
     void set(const std::string &value) { itsContent->setXMLvalue(itsKey, value); }
     std::string get() const { return itsContent->getXMLvalue(itsKey); }
 
-    // C++ operator overloading
-    void operator=(const std::string &value) { set(value); }
+    // C++ operator overloading (syntactic sugar)
+    Property &operator=(const std::string &value) { set(value); return *this; }
     operator std::string () const { return get(); }
 
-    bool operator==(const Property &other) const    { return (std::string)*this == (std::string)other; }
-    bool operator==(const std::string &other) const { return (std::string)*this == other; }
-    bool operator==(const char *other) const        { return (std::string)*this == std::string(other); }
+    bool operator==(const Property &other) const    { return this->get() == other.get(); }
+    bool operator==(const std::string &other) const { return this->get() == other; }
+    bool operator==(const char *other) const        { return this->get() == other; }
+
+    bool operator!=(const Property &other) const    { return this->get() != other.get(); }
+    bool operator!=(const std::string &other) const { return this->get() != other; }
+    bool operator!=(const char *other) const        { return this->get() != other; }
 
   private:
     Property(): itsContent(0), itsKey("") {}
@@ -142,11 +150,26 @@ public:
   // Set a value in the XML content.
   void setXMLvalue(const std::string& key, const std::string& data);
 
+protected:
+  // Import an XML subdocument under the given key.
+  void insertXML(const std::string& key, const std::string& xml);
+
+#ifdef HAVE_LIBXMLXX
+  // Locates and returns a node given by its XPATH key ("/a/b/c")
+  xmlpp::Element *getXMLnode(const std::string &name) const;
+#endif
+
 private:
+  void initContent(const std::string&);
   void addProperties();
 
   // -- datamembers -- 
+#ifdef HAVE_LIBXMLXX
+  xmlpp::DomParser itsParser; // NOTE: non-copyable
+  xmlpp::Document *itsDocument;
+#else
   std::string itsContent;
+#endif
 };
 
 inline std::ostream &operator<<(std::ostream &os, const MessageContent &msg)
@@ -175,17 +198,14 @@ public:
   qpid::messaging::Message& qpidMsg()             { return (itsQpidMsg); }
   const qpid::messaging::Message& qpidMsg() const { return (itsQpidMsg); }
 
-  // Return the content
-  MessageContent content() const { return MessageContent(itsQpidMsg); }
-  
   // Return the raw message content
   std::string rawContent() const { return itsQpidMsg.getContent(); }
 
   // Return a short (one line) description of the message
-  std::string short_desc() const { return content().short_desc(); }
+  std::string short_desc() const { MessageContent content(itsQpidMsg); return content.short_desc(); }
 
   // function for printing
-  std::ostream& print (std::ostream& os) const { return content().print(os); }
+  std::ostream& print (std::ostream& os) const { MessageContent content(itsQpidMsg); return content.print(os); }
 
 private:
   // -- datamembers -- 
diff --git a/LCS/MessageBus/src/Message.cc b/LCS/MessageBus/src/Message.cc
index a0490fd974684bbf463f85e3205c70aa2b14d99c..c9f282098bcf0b4032be8fcf922ad41a133e295a 100644
--- a/LCS/MessageBus/src/Message.cc
+++ b/LCS/MessageBus/src/Message.cc
@@ -33,6 +33,13 @@
 #include <qpid/types/Uuid.h>
 #endif
 
+#ifdef HAVE_LIBXMLXX
+#include <libxml++/parsers/domparser.h>
+#include <libxml++/nodes/textnode.h>
+
+using namespace xmlpp;
+#endif
+
 #include <time.h>
 
 
@@ -86,6 +93,7 @@ static string _uuid() {
 
 MessageContent::MessageContent()
 {
+  initContent(LOFAR_MSG_TEMPLATE);
   addProperties();
 }
 
@@ -96,9 +104,8 @@ MessageContent::MessageContent(const std::string &from,
 				 const std::string &protocolVersion,
 				 const std::string &momid,
 				 const std::string &sasid)
-:
-  itsContent(LOFAR_MSG_TEMPLATE)
 {
+  initContent(LOFAR_MSG_TEMPLATE);
   addProperties();
 
   this->system          = LOFAR::system;
@@ -116,9 +123,8 @@ MessageContent::MessageContent(const std::string &from,
 }
 
 MessageContent::MessageContent(const qpid::messaging::Message &qpidMsg)
-:
-  itsContent(qpidMsg.getContent())
 {
+  initContent(qpidMsg.getContent());
   addProperties();
 }
 
@@ -126,6 +132,16 @@ MessageContent::~MessageContent()
 {
 }
 
+void MessageContent::initContent(const std::string &content)
+{
+#ifdef HAVE_LIBXMLXX
+  itsParser.parse_memory(content);
+  itsDocument = itsParser.get_document();
+#else
+  itsContent = content;
+#endif
+}
+
 void MessageContent::addProperties()
 {
   system         .attach(this, "message/header/system");
@@ -151,7 +167,13 @@ void MessageContent::addProperties()
 qpid::messaging::Message MessageContent::qpidMsg() const {
   qpid::messaging::Message qpidMsg;
 
+#ifdef HAVE_LIBXMLXX
+  std::string content = itsDocument->write_to_string_formatted();
+  qpidMsg.setContent(content);
+#else
   qpidMsg.setContent(itsContent);
+#endif
+
   qpidMsg.setContentType("text/plain");
   qpidMsg.setDurable(true);
 
@@ -175,10 +197,8 @@ std::string MessageContent::short_desc() const
 
 std::ostream& MessageContent::print (std::ostream& os) const
 {
-    os << "system         : " << system << endl;
-    os << "systemversion  : " << headerVersion << endl;
-    os << "protocolName   : " << protocol << endl;
-    os << "protocolVersion: " << protocolVersion << endl;
+    os << "system         : " << system << " " << headerVersion << endl;
+    os << "protocol       : " << protocol << " " << protocolVersion << endl;
     os << "summary        : " << summary << endl;
     os << "timestamp      : " << timestamp << endl;
     os << "source (name)  : " << name << endl;
@@ -192,65 +212,134 @@ std::ostream& MessageContent::print (std::ostream& os) const
 
 string MessageContent::getXMLvalue(const string& key) const
 {
-	// get copy of content
-	vector<string>	labels = split(key, '/');
-
-	// loop over subkeys
-	string::size_type	offset = 0;
-	string::size_type	begin = string::npos;
-	string::size_type	end = string::npos;
-	string				startTag;
-	for (size_t i = 0; i <  labels.size(); ++i) {
-		// define tags to find
-		startTag = string("<"+labels[i]+">");
-		// search begin tag
-		begin  = itsContent.find(startTag, offset);
-		if (begin == string::npos) {
-			return ("???");
-		}
-		offset = begin;
-	}
-	// search end tag
-	string stopTag ("</"+labels[labels.size()-1]+">");
-	begin+=startTag.size();
-	end = itsContent.find(stopTag, begin);
-	if (end == string::npos) {
-		return ("???");
-	}
-	return (itsContent.substr(begin, end - begin));
+#ifdef HAVE_LIBXMLXX
+  Element *e = getXMLnode(key);
+  if (!e) return "???";
+
+  TextNode *t = e->get_child_text();
+  if (!t) return "";
+
+  return t->get_content();
+#else
+  // get copy of content
+  vector<string>  labels = split(key, '/');
+
+  // loop over subkeys
+  string::size_type  offset = 0;
+  string::size_type  begin = string::npos;
+  string::size_type  end = string::npos;
+  string        startTag;
+  for (size_t i = 0; i <  labels.size(); ++i) {
+    // define tags to find
+    startTag = string("<"+labels[i]+">");
+    // search begin tag
+    begin  = itsContent.find(startTag, offset);
+    if (begin == string::npos) {
+      return ("???");
+    }
+    offset = begin;
+  }
+  // search end tag
+  string stopTag ("</"+labels[labels.size()-1]+">");
+  begin+=startTag.size();
+  end = itsContent.find(stopTag, begin);
+  if (end == string::npos) {
+    return ("???");
+  }
+  return (itsContent.substr(begin, end - begin));
+#endif
 }
 
 void MessageContent::setXMLvalue(const string& key, const string &data)
 {
-	// get copy of content
-	vector<string>	labels = split(key, '/');
-
-	// loop over subkeys
-	string::size_type	offset = 0;
-	string::size_type	begin = string::npos;
-	string::size_type	end = string::npos;
-	string				startTag;
-	for (size_t i = 0; i <  labels.size(); ++i) {
-		// define tags to find
-		startTag = string("<"+labels[i]+">");
-		// search begin tag
-		begin  = itsContent.find(startTag, offset);
-		if (begin == string::npos) {
-			return;
-		}
-		offset = begin;
-	}
-	// search end tag
-	string stopTag ("</"+labels[labels.size()-1]+">");
-	begin+=startTag.size();
-	end = itsContent.find(stopTag, begin);
-	if (end == string::npos) {
-		return;
-	}
-
-	itsContent.replace(begin, end - begin, data);
+#ifdef HAVE_LIBXMLXX
+  Element *e = getXMLnode(key);
+  if (!e) return;
+
+  e->set_child_text(data);
+#else
+  // get copy of content
+  vector<string>  labels = split(key, '/');
+
+  // loop over subkeys
+  string::size_type  offset = 0;
+  string::size_type  begin = string::npos;
+  string::size_type  end = string::npos;
+  string        startTag;
+  for (size_t i = 0; i <  labels.size(); ++i) {
+    // define tags to find
+    startTag = string("<"+labels[i]+">");
+    // search begin tag
+    begin  = itsContent.find(startTag, offset);
+    if (begin == string::npos) {
+      return;
+    }
+    offset = begin;
+  }
+  // search end tag
+  string stopTag ("</"+labels[labels.size()-1]+">");
+  begin+=startTag.size();
+  end = itsContent.find(stopTag, begin);
+  if (end == string::npos) {
+    return;
+  }
+
+  itsContent.replace(begin, end - begin, data);
+#endif
+}
+
+void MessageContent::insertXML(const string &key, const string &xml)
+{
+#ifdef HAVE_LIBXMLXX
+  // Find insert spot
+  Element *e = getXMLnode(key);
+  if (!e) return;
+
+  // Parse provided XML
+  DomParser parser;
+  parser.parse_memory(xml);
+
+  Document *document = parser.get_document();
+  if (!document) return;
+
+  Element *root = document->get_root_node();
+  if (!root) return;
+
+  // Insert the XML into our document
+  e->import_node(root);
+#else
+  setXMLvalue(key, xml);
+#endif
 }
 
+#ifdef HAVE_LIBXMLXX
+Element *MessageContent::getXMLnode(const string &name) const
+{
+  Element *root = itsDocument->get_root_node();
+
+  if (!root) {
+    // Document is broken
+    return NULL;
+  }
+
+  // assume key is an XPath relative to root, see http://www.w3schools.com/xpath/xpath_syntax.asp
+  NodeSet nodeset = root->find("/"+name);
+  if (nodeset.empty()) {
+    // Element not found
+    return NULL;
+  }
+
+  Element *e = dynamic_cast<Element*>(nodeset[0]);
+
+  if (!e) {
+    // Key points to a special element
+    return NULL;
+  }
+
+  return e;
+}
+#endif
+
 Message::Message(const MessageContent &content)
 :
   itsQpidMsg(content.qpidMsg())
diff --git a/LCS/MessageBus/test/CMakeLists.txt b/LCS/MessageBus/test/CMakeLists.txt
index c433204fb7b7322a074783f95959ece05e08b157..d85a2d03c6733ff03e6bb88e9ac37c374805cc98 100644
--- a/LCS/MessageBus/test/CMakeLists.txt
+++ b/LCS/MessageBus/test/CMakeLists.txt
@@ -6,11 +6,11 @@ configure_file(
   ${CMAKE_CURRENT_SOURCE_DIR}/MessageFuncs.sh.in
   ${CMAKE_BINARY_DIR}/bin/MessageFuncs.sh @ONLY)
 
-if(HAVE_QPID)
-  if(HAVE_UNITTEST++)
-    lofar_add_test(tMessage tMessage.cc)
-  endif(HAVE_UNITTEST++)
+if(HAVE_UNITTEST++)
+  lofar_add_test(tMessage tMessage.cc)
+endif(HAVE_UNITTEST++)
 
+if(HAVE_QPID)
   lofar_add_test(tMsgBus tMsgBus.cc)
 
   lofar_add_test(tPyMsgBus)
diff --git a/LCS/MessageBus/test/tMessage.cc b/LCS/MessageBus/test/tMessage.cc
index d06b2d36da9bb6841d7d98a5a8d53dc0a6612d75..98ec3b345da5cf70f5141a34c8ca6c99dec7629c 100644
--- a/LCS/MessageBus/test/tMessage.cc
+++ b/LCS/MessageBus/test/tMessage.cc
@@ -26,6 +26,8 @@
 #include <UnitTest++.h>
 #include <MessageBus/Message.h>
 
+#include <iostream>
+
 using namespace LOFAR;
 using namespace std;
 
@@ -45,6 +47,9 @@ SUITE(MessageContent) {
     CHECK_EQUAL("1.2",      msg.protocolVersion.get());
     CHECK_EQUAL("MOMID",    msg.momid.get());
     CHECK_EQUAL("SASID",    msg.sasid.get());
+
+    std::cout << msg << std::endl;
+    std::cout << msg.qpidMsg().getContent() << std::endl;
   }
 
   TEST(existingmsg) {
@@ -61,6 +66,14 @@ SUITE(MessageContent) {
     CHECK_EQUAL(orig.momid,           copy.momid);
     CHECK_EQUAL(orig.sasid,           copy.sasid);
   }
+
+  TEST(modifymsg) {
+    MessageContent orig("NAME", "USER", "SUMMARY", "PROTOCOL", "1.2", "MOMID", "SASID");
+
+    orig.protocolVersion = "1.3";
+
+    CHECK_EQUAL("1.3", orig.protocolVersion.get());
+  }
 }
 
 int main() {
diff --git a/lofar_config.h.cmake b/lofar_config.h.cmake
index 46dbc719dbc0acee012f0fdc603331e08256d6e7..6ff3b27b94375aef27646ac65500b94fd0e3de61 100644
--- a/lofar_config.h.cmake
+++ b/lofar_config.h.cmake
@@ -130,7 +130,7 @@
 #cmakedefine HAVE_LIBSSH2 1
 
 /* Define if libxml++ is installed */
-#cmakedefine HAVE_LIBXML_CPP 1
+#cmakedefine HAVE_LIBXMLXX 1
 
 /* Define if LOG4CPLUS is installed */
 #cmakedefine HAVE_LOG4CPLUS 1