diff --git a/doc/dbusxml.doc b/doc/dbusxml.doc
new file mode 100644
index 0000000..a8710cb
--- /dev/null
+++ b/doc/dbusxml.doc
@@ -0,0 +1,141 @@
+/*! \page dbusxml DBus XML output format
+
+\addindex dbusxml
+
+<p>Doxygen can generate documentation for DBus XML files.  This way
+DBus interfaces can be annotated with doxygen style comments, and
+without writing custom XML parsers.  Doxygen extracts its text from
+all XML comments starting with '*' or '!'.  An additional '<' can be
+used to assign the documentation string to the previous entity instead
+of the one following the comment.
+
+\section dbusxml_supported Supported XML elements and attributes
+
+<p>The following DBus XML elemets can be annotated:
+
+<ul>
+<li><b>interface</b>
+
+<li><b>method</b> or <b>signal</b>
+
+<li><b>arg</b>
+
+<li><b>property</b>
+
+</ul>
+
+Additional elements are supported. These are available once
+the xmlns "http://psiamp.org/dtd/doxygen_dbusxml.dtd" is
+available.
+
+<ul>
+<li><b>namespace</b>: This can be used to group other more of the
+additional elemets.  This element requires a <b>name</b> attribute.
+
+<li><b>enum</b> is used to define enums.  <b>value</b> element is
+    then used to define the individual values in the enum.  This element
+    requires the <b>name</b> and <b>type</b> attributes.  A
+    optional <b>named-type</b> attribute is allowed, referrencing typed
+    previously defined by one of the additional elements.  A enum name
+    can be used anywhere a type is required using the <b>named-type</b>
+    attribute.
+
+<li><b>flagset</b> is used to define sets of flags. Required and
+    optional attributes are identical to the ones used by <b>enum</b>.
+    While <b>enum</b>s assume the values to be consecutive, while
+    a <b>flagset</b> is values suitable for flags.  A flagset name
+    can be used anywhere a type is required using the <b>named-type</b>
+    attribute.
+
+<li><b>struct</b> is used to define structures. A <b>name</b>
+    attribute is required.
+
+<li><b>member</b> is used to define members of <b>structs</b>.  It
+    is valid inside <b>struct</b> elements. This
+    element requires <b>name</b> and <b>type</b> attributes.  In
+    addition to (or even instead of) the <b>type</b> attribute a
+    <b>named-type</b> attribute may be used to reference types defined
+    by <b>enum</b>, <b>flagset</b> or <b>struct</b>.
+
+\section dbusxml_example Example
+
+<pre>
+<?xml version="1.0" ?>
+<!-- Comment -->
+<!--*< File comment -->
+<node name="/SomeNode" xmlns:dx="http://psiamp.org/dtd/doxygen_dbusxml.dtd">
+  <!--* test struct outside a namespace and interface -->
+  <dx:struct name="StructOutsideNamespace">
+    <!--* member 1 -->
+    <dx:member name="member1" type="s"/>
+    <!--* complex member 1 -->
+    <dx:member name="complexMember1" type="(ssu)"/>
+  </dx:struct>
+
+  <!--* Test flag set -->
+  <dx:flagset name="flagset">
+    <!--* Flag 1 of flagset. -->
+    <dx:value name="FLAG1"/>
+  </dx:flagset>
+
+  <!--* namespace comment -->
+  <dx:namespace name="SomeNamespace">
+    <!--* struct inside a namespace -->
+    <dx:struct name="StructInNamespace">
+       <!--* member 2 -->
+       <dx:member name="member2" type="s"/>
+    </dx:struct>
+  </dx:namespace>
+  <!--* Documentation on the interface -->
+  <interface name="nl.stack.doxygen.test.interface">
+    <!--* Test Enum documentation -->
+    <dx:enum name="TestEnum">
+      <!--* key 1 with value 13 -->
+      <dx:value name="KEY1" value="13"/>
+      <!--* key 2 without a value -->
+      <dx:value name="KEY2"/>
+    </dx:enum>
+
+    <!--* struct inside a interface -->
+    <dx:struct name="StructInInterface">
+      <!--* member 3 -->
+      <dx:member name="member3" type="s"/>
+      <!--* Struct in a struct -->
+      <dx:struct name="StructInAStruct">
+        <!--* member4 -->
+        <dx:member name="member4" type="s"/>
+      </dx:struct>
+      <!--* struct member -->
+      <dx:member name="structMembor" type="(s)" named-type="StructInAStruct"/>
+    </dx:struct>
+    <!--* Document method
+
+          Some extended documentation for the method.
+
+          @param[in] input blah.
+          @param[out] output blub
+     -->
+    <method name="method">
+      <arg direction="in" name="input" type="(s(s))" named-type="::nl::stack::doxygen::test::interface::StructInInterface"/>
+      <arg direction="out" type="v" name="output"/>
+    </method>
+
+    <signal name="signal">
+      <!--*< Documentation for signal.
+
+             @param parameter some parameter.
+        -->
+      <arg name="parameter" type="s"/>
+    </signal>
+
+    <!--* property documentation -->
+    <property name="property" type="s" access="readwrite"/>
+
+    <!--* property documentation read-only -->
+    <property name="propertyRead" type="s" access="read"/>
+    <!--* property documentation write-only -->
+    <property name="propertyWrite" type="s" access="write"/>
+  </interface>
+</node>
+</pre>
+*/
diff --git a/examples/dbusxml.cfg b/examples/dbusxml.cfg
new file mode 100644
index 0000000..e5f6b18
--- /dev/null
+++ b/examples/dbusxml.cfg
@@ -0,0 +1,10 @@
+PROJECT_NAME      = "DBusXMLDocs"
+OUTPUT_DIRECTORY  = dbusxml
+GENERATE_LATEX    = NO
+GENERATE_MAN      = NO
+GENERATE_RTF      = NO
+CASE_SENSE_NAMES  = NO
+INPUT             = dbusxml.xml
+QUIET             = YES
+JAVADOC_AUTOBRIEF = YES
+EXTRACT_ALL       = YES
diff --git a/examples/dbusxml.xml b/examples/dbusxml.xml
new file mode 100644
index 0000000..4ab7f78
--- /dev/null
+++ b/examples/dbusxml.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" ?>
+<!-- Comment -->
+<!--*< File comment -->
+<node name="/SomeNode" xmlns:dx="http://psiamp.org/dtd/doxygen_dbusxml.dtd">
+  <!--* test struct outside a namespace and interface -->
+  <dx:struct name="StructOutsideNamespace">
+    <!--* member 1 -->
+    <dx:member name="member1" type="s"/>
+    <!--* complex member 1 -->
+    <dx:member name="complexMember1" type="(ssu)"/>
+  </dx:struct>
+
+  <!--* Test flag set -->
+  <dx:flagset name="flagset">
+    <!--* Flag 1 of flagset. -->
+    <dx:value name="FLAG1"/>
+  </dx:flagset>
+
+  <!--* namespace comment -->
+  <dx:namespace name="SomeNamespace">
+    <!--* struct inside a namespace -->
+    <dx:struct name="StructInNamespace">
+       <!--* member 2 -->
+       <dx:member name="member2" type="s"/>
+    </dx:struct>
+  </dx:namespace>
+  <!--* Documentation on the interface -->
+  <interface name="nl.stack.doxygen.test.interface">
+    <!--* Test Enum documentation -->
+    <dx:enum name="TestEnum">
+      <!--* key 1 with value 13 -->
+      <dx:value name="KEY1" value="13"/>
+      <!--* key 2 without a value -->
+      <dx:value name="KEY2"/>
+    </dx:enum>
+
+    <!--* struct inside a interface -->
+    <dx:struct name="StructInInterface">
+      <!--* member 3 -->
+      <dx:member name="member3" type="s"/>
+      <!--* Struct in a struct -->
+      <dx:struct name="StructInAStruct">
+        <!--* member4 -->
+        <dx:member name="member4" type="s"/>
+      </dx:struct>
+      <!--* struct member -->
+      <dx:member name="structMembor" type="(s)" named-type="StructInAStruct"/>
+    </dx:struct>
+    <!--* Document method
+
+          Some extended documentation for the method.
+
+          @param[in] input blah.
+          @param[out] output blub
+     -->
+    <method name="method">
+      <arg direction="in" name="input" type="(s(s))" named-type="::nl::stack::doxygen::test::interface::StructInInterface"/>
+      <arg direction="out" type="v" name="output"/>
+    </method>
+
+    <signal name="signal">
+      <!--*< Documentation for signal.
+
+             @param parameter some parameter.
+        -->
+      <arg name="parameter" type="s"/>
+    </signal>
+
+    <!--* property documentation -->
+    <property name="property" type="s" access="readwrite"/>
+
+    <!--* property documentation read-only -->
+    <property name="propertyRead" type="s" access="read"/>
+    <!--* property documentation write-only -->
+    <property name="propertyWrite" type="s" access="write"/>
+  </interface>
+</node>
+<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/src/dbusxmlscanner.cpp b/src/dbusxmlscanner.cpp
new file mode 100644
index 0000000..70845c4
--- /dev/null
+++ b/src/dbusxmlscanner.cpp
@@ -0,0 +1,874 @@
+/******************************************************************************
+ *
+ *
+ *
+ * Copyright (C) 2009 by Tobias Hunger <tobias@aquazul.com>
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#include "dbusxmlscanner.h"
+
+#include "commentscan.h"
+#include "entry.h"
+
+#include <qfile.h>
+#include <qxml.h>
+#include <qstring.h>
+
+#include "message.h"
+#include "util.h"
+
+// -----------------------------------------------------------------------
+// Convenience defines:
+// -----------------------------------------------------------------------
+
+#define CONDITION(cond, msg) \
+    do {\
+        if (cond)\
+        {\
+            if (m_errorString.isEmpty()) { m_errorString = msg; }\
+            return false;\
+        }\
+    }\
+    while (0)
+
+#define DOC_ERROR(msg) \
+    warn_doc_error(m_fileName.utf8().data(), lineNumber(), msg.utf8().data())
+
+#define COND_DOC_ERROR(cond, msg) \
+    do {\
+        if (cond)\
+        {\
+             DOC_ERROR(msg);\
+             return true;\
+        }\
+    }\
+    while (0)
+
+#define DBUS(name) isDBusElement(namespaceURI, localName, qName, name)
+#define EXTENSION(name) isExtensionElement(namespaceURI, localName, qName, name)
+
+// -----------------------------------------------------------------------
+// DBusXMLHandler class
+// -----------------------------------------------------------------------
+
+const QString EXTENSION_URI("http://psiamp.org/dtd/doxygen_dbusxml.dtd");
+
+class DBusXMLHandler : public QXmlDefaultHandler
+{
+public:
+    DBusXMLHandler(ParserInterface * parser,
+                   QXmlSimpleReader * reader,
+                   const char * file_name,
+                   Entry * root) :
+        m_parser(parser),
+        m_locator(reader),
+        m_currentEntry(0),
+        m_currentInterface(0),
+        m_currentMethod(0),
+        m_currentArgument(0),
+        m_currentProperty(0),
+        m_currentEnum(0),
+        m_fileName(file_name),
+        m_currentComment(0)
+    {
+        setDocumentLocator(&m_locator);
+
+        m_scopeCount = 0;
+
+        // Set up stack cleanup:
+        m_structStack.setAutoDelete(TRUE);
+        m_elementStack.setAutoDelete(TRUE);
+        m_scopeStack.setAutoDelete(TRUE);
+
+        openScopes(root);
+    }
+
+    ~DBusXMLHandler()
+    { closeScopes(); }
+
+    QString errorString()
+    { return m_errorString; }
+
+    bool startElement(const QString &namespaceURI,
+                      const QString &localName,
+                      const QString &qName,
+                      const QXmlAttributes &attributes)
+    {
+        // add to elements stack:
+        m_elementStack.append(new ElementData(qName));
+
+        // First we need a node.
+        if (DBUS("node"))
+        {
+            CONDITION(!m_currentNode.isEmpty(), "Node inside a node.");
+
+            const int idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(idx < 0, QString("Anonymous node found."));
+
+            m_currentNode = attributes.value(idx);
+            // A node is actually of little interest, so do nothing here.
+            return true;
+        }
+
+        // Then we need an interface.
+        if (DBUS("interface"))
+        {
+            // We need a nodeName for interfaces:
+            CONDITION(m_currentNode.isEmpty(), "Interface without a node.");
+            CONDITION(m_currentInterface, "Interface within another interface.");
+
+            const int idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(idx < 0, QString("Interface without a name found."));
+
+            // A interface is roughly equivalent to a class:
+            m_currentInterface = createEntry();
+
+            m_currentInterface->section = Entry::CLASS_SEC;
+            m_currentInterface->spec |= Entry::Interface;
+            m_currentInterface->type = "Interface";
+            m_currentInterface->name = substitute(attributes.value(idx), ".", "::");
+
+            openScopes(m_currentInterface);
+
+            return true;
+        }
+
+        if (DBUS("method") || DBUS("signal"))
+        {
+            // We need a interfaceName for methods and signals:
+            CONDITION(!m_currentInterface, "Method or signal found outside a interface.");
+            CONDITION(m_currentMethod, "Method or signal found inside another method or signal.");
+            CONDITION(m_currentProperty, "Methor or signal found inside a property.");
+            CONDITION(!m_structStack.isEmpty(), "Method or signal found inside a struct.");
+            CONDITION(m_currentEnum, "Methor or signal found inside a enum.");
+
+            const int idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(idx < 0, QString("Method or signal without a name found."));
+
+            m_currentMethod = createEntry();
+
+            m_currentMethod->section = Entry::FUNCTION_SEC;
+            m_currentMethod->name = attributes.value(idx);
+            m_currentMethod->mtype = Method;
+            m_currentMethod->type = "void";
+
+            if (DBUS("signal"))
+            { m_currentMethod->mtype = Signal; }
+        }
+
+        if (DBUS("arg"))
+        {
+            // We need a method for arguments:
+            CONDITION(!m_currentMethod, "Argument found outside a method or signal.");
+            CONDITION(m_currentArgument, "Argument found inside another argument.");
+
+            const int name_idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(name_idx < 0, QString("Argument without a name found."));
+            COND_DOC_ERROR(!hasType(attributes), QString("Argument without a type found."));
+
+            const int direction_idx(indexOf(attributes, "direction"));
+
+            if ((m_currentMethod->mtype == Signal &&
+                 direction_idx >= 0 &&
+                 attributes.value(direction_idx) != "in") ||
+                (m_currentMethod->mtype == Method &&
+                 direction_idx >= 0 &&
+                 attributes.value(direction_idx) != "in" &&
+                 attributes.value(direction_idx) != "out"))
+            {
+                m_errorString = "Invalid direction found.";
+                return false;
+            }
+
+            m_currentArgument = new Argument;
+            m_currentArgument->type = getType(attributes);
+            m_currentArgument->name = attributes.value(name_idx);
+            if (direction_idx >= 0)
+            { m_currentArgument->attrib = attributes.value(direction_idx); }
+            else
+            {
+                if (m_currentMethod->mtype == Signal)
+                { m_currentArgument->attrib = "in"; }
+                else
+                { m_currentArgument->attrib = "out"; }
+            }
+        }
+
+        if (DBUS("property"))
+        {
+            CONDITION(m_currentMethod, "Property found inside a method or signal.");
+            CONDITION(!m_currentInterface, "Property found outside an interface.");
+            CONDITION(m_currentProperty, "Property found inside another property.");
+            CONDITION(!m_structStack.isEmpty(), "Property found inside a struct.");
+            CONDITION(m_currentEnum, "Property found inside a enum.");
+
+            const int name_idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(name_idx < 0, QString("Anonymous property found."));
+            COND_DOC_ERROR(!hasType(attributes), QString("Property without a type found."));
+
+            const int access_idx(indexOf(attributes, "access"));
+            COND_DOC_ERROR(access_idx < 0, QString("Property without a access attribute found."));
+            COND_DOC_ERROR(attributes.value(access_idx) != "read" &&
+                           attributes.value(access_idx) != "write" &&
+                           attributes.value(access_idx) != "readwrite",
+                           QString("Property with invalid access attribute \"%1\" found.").
+                           arg(attributes.value(access_idx)));
+
+            m_currentProperty = createEntry();
+
+            m_currentProperty->section = Entry::FUNCTION_SEC;
+
+            if (attributes.value(access_idx) == "read" ||
+                attributes.value(access_idx) == "readwrite")
+            { m_currentProperty->spec |= Entry::Readable; }
+
+            if (attributes.value(access_idx) == "write" ||
+                attributes.value(access_idx) == "readwrite")
+            { m_currentProperty->spec |= Entry::Writable; }
+
+            m_currentProperty->name = attributes.value(name_idx);
+            m_currentProperty->mtype = Property;
+            m_currentProperty->type = getType(attributes);
+        }
+
+        if (EXTENSION("namespace"))
+        {
+            CONDITION(m_currentNode.isEmpty(), "Namespace found outside a node.");
+            CONDITION(m_currentInterface, "Namespace found inside an interface.");
+
+            const int idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(idx < 0, QString("Anonymous namespace found."));
+
+            m_namespaceStack.append(openNamespace(attributes.value(idx)));
+            openScopes(m_namespaceStack.last());
+        }
+
+        if (EXTENSION("struct"))
+        {
+            CONDITION(m_currentMethod, "Struct found inside a method or signal.");
+            CONDITION(m_currentProperty, "Struct found inside a property.");
+            CONDITION(m_currentEnum, "Struct found inside an enum.");
+
+            const int idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(idx < 0, QString("Anonymous struct found."));
+
+            Entry * current_struct = createEntry();
+            current_struct->section = Entry::CLASS_SEC;
+            current_struct->spec = Entry::Struct;
+            current_struct->name = attributes.value(idx);
+
+            openScopes(current_struct);
+
+            current_struct->type = current_struct->name + " struct";
+
+            m_structStack.append(new StructData(current_struct));
+        }
+
+        if (EXTENSION("member"))
+        {
+            CONDITION(m_structStack.isEmpty(), "Member found outside of struct.");
+
+            const int name_idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(name_idx < 0, QString("Anonymous member found."));
+            COND_DOC_ERROR(!hasType(attributes), QString("Member without a type found."));
+
+            createEntry();
+
+            m_currentEntry->section = Entry::VARIABLE_SEC;
+            m_currentEntry->name = attributes.value(name_idx);
+            m_currentEntry->type = getType(attributes);
+
+            QString type(getDBusType(m_currentEntry->type));
+            m_structStack.last()->type.append(type);
+        }
+
+        if (EXTENSION("enum") || EXTENSION("flagset"))
+        {
+            CONDITION(m_currentMethod, "Enum found inside a method or signal.");
+            CONDITION(m_currentProperty, "Enum found inside a property.");
+
+            const int name_idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(name_idx < 0, QString("Anonymous enum found."));
+
+            const int type_idx(indexOf(attributes, "type"));
+            QString type = "u";
+            if (type_idx >= 0)
+            { type = attributes.value(type_idx); }
+            if (type != "y" && type != "q" && type != "u" && type != "t")
+            { DOC_ERROR(QString("Invalid enum type \"%1\" found.").arg(type)); }
+
+            m_currentEnum = createEntry();
+            m_currentEnum->section = Entry::ENUM_SEC;
+            m_currentEnum->name = attributes.value(name_idx);
+
+            openScopes(m_currentEnum);
+
+            m_currentEnum->type = m_currentEntry->name + " enum";
+
+            addNamedType(type);
+        }
+
+        if (EXTENSION("value"))
+        {
+            CONDITION(!m_currentEnum, "Value found outside an enum.");
+
+            const int name_idx(indexOf(attributes, "name"));
+            COND_DOC_ERROR(name_idx < 0, QString("Anonymous value found."));
+
+            const int value_idx(indexOf(attributes, "value"));
+
+            createEntry();
+
+            m_currentEntry->section = Entry::VARIABLE_SEC;
+            m_currentEntry->name = attributes.value(name_idx);
+            m_currentEntry->type = m_currentEnum->name; // "@"; // enum marker!
+            if (value_idx >= 0)
+            { m_currentEntry->initializer = attributes.value(value_idx); }
+        }
+
+        return true;
+    }
+
+    bool endElement(const QString &namespaceURI,
+                    const QString &localName,
+                    const QString &qName)
+    {
+        // Clean up elements stack:
+        // Since we made sure to get the elements in the proper order when
+        // adding we do not need to do so again here.
+        COND_DOC_ERROR(m_elementStack.last()->element != qName,
+                       QString("Malformed XML: Unexpected closing element found.").
+                       arg(m_elementStack.last()->element));
+        m_elementStack.removeLast();
+
+        // Interface:
+        if (DBUS("interface"))
+        {
+            m_currentInterface->endBodyLine = lineNumber();
+            closeScopes();
+            m_currentInterface = 0;
+        }
+
+        if (DBUS("method") || DBUS("signal"))
+        {
+            m_currentMethod->endBodyLine = lineNumber();
+            m_currentInterface->addSubEntry(m_currentMethod);
+            m_currentMethod = 0;
+        }
+
+        if (DBUS("property"))
+        {
+            m_currentProperty->endBodyLine = lineNumber();
+            m_currentInterface->addSubEntry(m_currentProperty);
+            m_currentProperty = 0;
+        }
+
+        if (DBUS("arg"))
+        {
+            m_currentMethod->argList->append(m_currentArgument);
+            m_currentArgument = 0;
+        }
+
+        if (EXTENSION("namespace"))
+        {
+            Entry * current = m_namespaceStack.last();
+            m_namespaceStack.removeLast();
+
+            current->endBodyLine = lineNumber();
+            closeScopes();
+        }
+
+        if (EXTENSION("struct"))
+        {
+            StructData * data = m_structStack.last();
+
+            data->entry->endBodyLine = lineNumber();
+
+            QString current_type;
+            current_type.append(QString("("));
+            current_type.append(data->type);
+            current_type.append(QString(")"));
+
+            addNamedType(current_type);
+
+            closeScopes();
+
+            m_structStack.removeLast();
+        }
+
+        if (EXTENSION("member"))
+        {
+           m_structStack.last()->entry->addSubEntry(m_currentEntry);
+        }
+
+        if (EXTENSION("enum") || EXTENSION("flagset"))
+        {
+            m_currentEnum->endBodyLine = lineNumber();
+            closeScopes();
+
+            m_currentEnum = 0;
+        }
+
+        if (EXTENSION("value"))
+        {
+            m_currentEntry->endBodyLine = lineNumber();
+
+            m_currentEnum->addSubEntry(m_currentEntry);
+        }
+
+        return true;
+    }
+
+    bool characters(const QString & chars)
+    { return true; }
+
+    bool comment(const QString & comment_)
+    {
+        if (m_currentComment)
+        { handleComment(); }
+
+        m_currentComment = new CommentData(m_fileName, lineNumber(), comment_);
+
+        if (!m_currentComment->shouldIgnore)
+        {
+            delete m_currentComment;
+            m_currentComment = 0;
+            return true;
+        }
+
+        if (m_currentComment->associateWithPrevious)
+        { handleComment(); }
+
+        return true;
+    }
+
+    void handleComment()
+    {
+        if (m_currentComment == 0 || m_currentEntry == 0)
+        { return; }
+
+        QCString text(m_currentComment->text);
+
+        m_currentEntry->docFile = m_currentComment->fileName;
+        m_currentEntry->docLine = m_currentComment->line;
+
+        int position(0);
+        bool needs_entry(false);
+        bool brief(false);
+        Protection prot(Public);
+
+        while (parseCommentBlock(m_parser,
+                                 m_currentEntry,
+                                 text, m_fileName.utf8().data(), lineNumber(),
+                                 brief, m_currentComment->isJavaStyle,
+                                 false,
+                                 prot,
+                                 position,
+                                 needs_entry))
+        {
+            if (needs_entry) { createEntry(); }
+        }
+        if (needs_entry) { createEntry(); }
+
+        delete m_currentComment;
+        m_currentComment = 0;
+    }
+
+    QXmlLocator * locator()
+    { return &m_locator; }
+
+    int lineNumber()
+    { return m_locator.lineNumber(); }
+
+    void setSection()
+    {
+        Entry * current = createEntry();
+        current->reset();
+
+        current->name    = m_fileName.utf8();
+        current->section = Entry::SOURCE_SEC;
+
+        // Open/Close the scope to do the bookkeeping:
+        openScopes(current);
+        closeScopes();
+    }
+
+private:
+    bool isDBusElement(const QString & namespaceURI,
+                       const QString & localName,
+                       const QString & qName,
+                       const QString & element)
+    {
+        return (namespaceURI.isEmpty() && localName == element && qName == element) ||
+               (namespaceURI.isEmpty() && localName.isEmpty() && qName == element);
+    }
+
+    bool isExtensionElement(const QString & namespaceURI,
+                            const QString & localName,
+                            const QString & qName,
+                            const QString & element)
+    {
+        // isNull happens in startelement if no URI is used.
+        if (namespaceURI.isNull())
+        { return false; }
+
+        // We are in a endElement: URI is always empty there:-(
+        if (namespaceURI.isEmpty())
+        { return qName == m_scopeStack.last()->extensionPrefix + element; }
+
+        // startElemennt: We need to save the qName prefix
+        // since endElement will forget about the namespaceURi:-(
+        if (namespaceURI == EXTENSION_URI)
+        {
+            int pos = qName.find(':');
+            m_scopeStack.last()->extensionPrefix = qName.left(pos + 1);
+        }
+
+        return namespaceURI == EXTENSION_URI && localName == element;
+    }
+
+    bool hasType(const QXmlAttributes & attributes)
+    {
+        const int type_idx(indexOf(attributes, "type"));
+        const int named_type_idx(indexOf(attributes, "named-type"));
+
+        return named_type_idx >= 0 || type_idx >= 0;
+    }
+
+    QString getType(const QXmlAttributes & attributes)
+    {
+        const int type_idx(indexOf(attributes, "type"));
+        const int named_type_idx(indexOf(attributes, "named-type"));
+
+        QString type;
+
+        if (named_type_idx >= 0)
+        {
+            type = attributes.value(named_type_idx);
+            if (!type.startsWith("::"))
+            { type = getCurrentScope(attributes.value(named_type_idx)); }
+            else
+            { type = type.mid(2); }
+            if (m_namedTypeMap.contains(type))
+            {
+                if (type_idx >= 0)
+                {
+                    const QString dbus_type(attributes.value(type_idx));
+                    if (dbus_type != m_namedTypeMap[type])
+                    {
+                        DOC_ERROR(QString("Type \"%1\" does not match up with "
+                                          "previous definition of named type \"%2\" (which was \"%3\".").
+                                          arg(dbus_type).
+                                          arg(type).
+                                          arg(m_namedTypeMap[type]));
+                    }
+                }
+                return type;
+            }
+
+            DOC_ERROR(QString("Undefined named type \"%1\" used.").arg(type));
+        }
+
+        if (type_idx >= 0)
+        {
+            type = attributes.value(type_idx);
+
+            QRegExp reg_exp(QString("(a?[ybnqiuxdtsogv]|a[{]sv[}])"));
+            if (reg_exp.match(type))
+            { return type; }
+
+            DOC_ERROR(QString("Unnamed complex D-Bus type \"%1\" found.").arg(type));
+        }
+
+        return QString();
+    }
+
+    QString getDBusType(const QString & type)
+    {
+        QString scoped_type = type;
+        if (!scoped_type.contains("::"))
+        { scoped_type = getCurrentScope(type); }
+
+        if (m_namedTypeMap.contains(scoped_type))
+        { return m_namedTypeMap[scoped_type]; }
+        else
+        { return type; }
+    }
+
+    void addNamedType(const QString type)
+    {
+        QString scoped_name(getCurrentScope());
+
+        if (m_namedTypeMap.contains(scoped_name))
+        {
+            DOC_ERROR(QString("Named type \"%1\" is already defined.").arg(scoped_name));
+            return;
+        }
+
+        m_namedTypeMap.insert(scoped_name, type);
+    }
+
+    QString getCurrentScope(const QString & type = QString())
+    {
+        QString scoped_name;
+        if (!m_scopeStack.isEmpty())
+        {
+            scoped_name = m_scopeStack.last()->scope->name;
+            scoped_name.append("::");
+        }
+        if (!type.isEmpty())
+        { scoped_name.append(type); }
+        else
+        { scoped_name = scoped_name.left(scoped_name.length() - 2); }
+
+        return scoped_name;
+    }
+
+    int indexOf(const QXmlAttributes & attributes, const QString & name,
+                 const QString & type = "CDATA", const bool mandatory = true)
+    {
+        const int idx(attributes.index(name));
+        if (idx < 0 || idx > attributes.length()) { return -1; }
+        if (attributes.type(idx) != type) { return -1; }
+        if (mandatory && attributes.value(idx).isEmpty()) { return -1; }
+
+        return idx;
+    }
+
+    Entry * createEntry()
+    {
+        Entry * entry = new Entry();
+
+        entry->protection = Public ;
+        entry->virt       = Normal;
+        entry->stat       = false;
+        entry->objc       = false;
+        entry->spec       = 0;
+
+        entry->fileName  = m_fileName;
+        entry->startLine = lineNumber();
+        entry->bodyLine = lineNumber();
+
+        entry->callGraph = false;
+        entry->callerGraph = false;
+
+        initGroupInfo(entry);
+
+        m_currentEntry = entry;
+
+        handleComment();
+
+        return entry;
+    }
+
+    void openScopes(Entry * object)
+    {
+        int cur_scope_separator_pos = 0;
+        int last_scope_separator_pos = 0;
+        while (0 <= (cur_scope_separator_pos = object->name.find("::", last_scope_separator_pos)))
+        {
+            QString scope = object->name.mid(last_scope_separator_pos,
+                                             cur_scope_separator_pos - last_scope_separator_pos);
+            last_scope_separator_pos = cur_scope_separator_pos + 2;
+
+            Entry * current_namespace = openNamespace(scope);
+
+            if (!m_scopeStack.isEmpty())
+            { m_scopeStack.last()->scope->addSubEntry(current_namespace); }
+
+            m_scopeStack.append(new ScopeData(current_namespace, m_scopeCount));
+        }
+
+        QString scoped_name(getCurrentScope());
+        if (!scoped_name.isEmpty())
+        { scoped_name.append("::"); }
+        scoped_name.append(object->name.mid(last_scope_separator_pos));
+
+        object->name = scoped_name;
+
+        if (!m_scopeStack.isEmpty())
+        { m_scopeStack.last()->scope->addSubEntry(object); }
+        m_scopeStack.append(new ScopeData(object, m_scopeCount));
+
+        ++m_scopeCount;
+    }
+
+    Entry * openNamespace(const QString & name)
+    {
+        Entry * current_namespace = createEntry();
+        QString scoped_name(getCurrentScope());
+        if (!scoped_name.isEmpty())
+        { scoped_name.append("::"); }
+        scoped_name.append(name);
+        current_namespace->name = scoped_name;
+        current_namespace->section = Entry::NAMESPACE_SEC;
+        current_namespace->type = "namespace" ;
+
+        return current_namespace;
+    }
+
+    void closeScopes()
+    {
+        const int current_scope_count(m_scopeStack.last()->count);
+
+        // Do not close the root scope.
+        if (current_scope_count == 0)
+        { return; }
+
+        while (current_scope_count == m_scopeStack.last()->count)
+        { m_scopeStack.removeLast(); }
+    }
+
+    ParserInterface * m_parser;
+
+    QXmlLocator m_locator;
+    QString m_currentNode; // Nodes can not be nested, no entry necessary.
+
+    struct ElementData
+    {
+        ElementData(const QString & e) :
+            element(e)
+        { }
+        ~ElementData() { }
+
+        QString element; //*< The element name
+        QString extensionPrefix; //*< The prefix used for our extension.
+        QString text; //*< The actual xml code.
+    };
+    QList<ElementData> m_elementStack;
+
+    Entry * m_currentEntry; // The currently open entry.
+
+    Entry * m_currentInterface; // Interfaces can not be nested.
+    Entry * m_currentMethod; // Methods can not be nested.
+    Argument * m_currentArgument; // Arguments can not be nested.
+    Entry * m_currentProperty; // Properties can not be nested.
+    Entry * m_currentEnum; // Enums can not be nested.
+    QList<Entry> m_namespaceStack;
+
+    struct StructData
+    {
+        StructData(Entry * e) : entry(e) { }
+        ~StructData() { }
+
+        QString type;
+        Entry * entry;
+    };
+    QList<StructData> m_structStack; // Structs can be nested.
+
+    struct ScopeData
+    {
+        ScopeData(Entry * s, int c) :
+            scope(s),
+            count(c)
+        { }
+        ~ScopeData() { }
+
+        Entry * scope;
+        QString extensionPrefix;
+        int count;
+    };
+    QList<ScopeData> m_scopeStack; // Scopes are nested.
+
+    QString m_fileName;
+
+    struct CommentData
+    {
+        CommentData(const QString & f, const int l, const QString & t) :
+            isJavaStyle(false),
+            isQtStyle(false),
+            line(l),
+            fileName(f)
+        {
+            isJavaStyle = t.startsWith(QChar('*'));
+            isQtStyle = t.startsWith(QChar('!'));
+            shouldIgnore = (!isJavaStyle && !isQtStyle);
+            associateWithPrevious = (t.at(1) == QChar('<'));
+            if (associateWithPrevious)
+            { text = t.mid(2); }
+            else
+            { text = t.mid(1); }
+        }
+        ~CommentData() { }
+
+        QString text;
+        bool isJavaStyle;
+        bool isQtStyle;
+        bool shouldIgnore;
+        bool associateWithPrevious;
+        int line;
+        QString fileName;
+    };
+    CommentData * m_currentComment;
+
+    int m_scopeCount; //*< unique scope id.
+
+    QString m_errorString;
+
+    QMap<QString, QString> m_namedTypeMap;
+};
+
+// -----------------------------------------------------------------------
+// DBusXMLScanner
+// -----------------------------------------------------------------------
+
+DBusXMLScanner::DBusXMLScanner()
+{ }
+
+DBusXMLScanner::~DBusXMLScanner()
+{ }
+
+void DBusXMLScanner::parseInput(const char * fileName,
+                                const char * /* fileBuf */,
+                                Entry * root)
+{
+    QFile inputFile(fileName);
+
+    QXmlInputSource inputSource(inputFile);
+    QXmlSimpleReader reader;
+
+    DBusXMLHandler handler(this, &reader, fileName, root);
+    reader.setContentHandler(&handler);
+    reader.setErrorHandler(&handler);
+    reader.setLexicalHandler(&handler);
+
+    groupEnterFile(fileName, 1);
+    handler.setSection();
+    reader.parse(inputSource);
+
+    if (handler.errorString())
+    { err("ERROR parsing XML: %s\n", handler.errorString().utf8().data()); }
+
+    groupLeaveFile(fileName, 1);
+}
+
+bool DBusXMLScanner::needsPreprocessing(const QCString & /* extension */)
+{ return (false); }
+
+void DBusXMLScanner::parseCode(CodeOutputInterface & /* codeOutIntf */,
+                               const char * /* scopeName */,
+                               const QCString & /* input */,
+                               bool /* isExampleBlock */,
+                               const char * /* exampleName */,
+                               FileDef * /* fileDef */,
+                               int /* startLine */,
+                               int /* endLine */,
+                               bool /* inlineFragment */,
+                               MemberDef * /* memberDef */)
+{ }
+
+void DBusXMLScanner::resetCodeParserState()
+{ }
+
+void DBusXMLScanner::parsePrototype(const char * /* text */)
+{ }
diff --git a/src/dbusxmlscanner.h b/src/dbusxmlscanner.h
new file mode 100644
index 0000000..3a4994e
--- /dev/null
+++ b/src/dbusxmlscanner.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ *
+ *
+ * Copyright (C) 2009 by Tobias Hunger <tobias@aquazul.com>
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#ifndef SCANNER_DBUSXML_H
+#define SCANNER_DBUSXML_H
+
+#include "parserintf.h"
+
+/** \brief D-Bus XML parser.
+ *
+ *  This is the D-Bus XML parser for doxygen.
+ */
+class DBusXMLScanner : public ParserInterface
+{
+public:
+    DBusXMLScanner();
+    virtual ~DBusXMLScanner();
+    void parseInput(const char *fileName,
+                    const char *fileBuf,
+                    Entry *root);
+
+    bool needsPreprocessing(const QCString &extension);
+
+    void parseCode(CodeOutputInterface &codeOutIntf,
+                   const char *scopeName,
+                   const QCString &input,
+                   bool isExampleBlock,
+                   const char *exampleName=0,
+                   FileDef *fileDef=0,
+                   int startLine=-1,
+                   int endLine=-1,
+                   bool inlineFragment=FALSE,
+                   MemberDef *memberDef=0
+                  );
+
+    void resetCodeParserState();
+
+    void parsePrototype(const char *text);
+
+private:
+};
+
+#endif
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index 51bd291..7a7abde 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -71,6 +71,7 @@
 #include "htags.h"
 #include "pyscanner.h"
 #include "fortranscanner.h"
+#include "dbusxmlscanner.h"
 #include "code.h"
 #include "objcache.h"
 #include "store.h"
@@ -6572,7 +6573,7 @@ static void addEnumValuesToEnums(EntryNav *rootNav)
               SrcLangExt sle;
               if (rootNav->fileDef() &&
                   ( (sle=getLanguageFromFileName(rootNav->fileDef()->name()))==SrcLangExt_CSharp
-                  || sle==SrcLangExt_Java
+                  || sle==SrcLangExt_Java || sle==SrcLangExt_XML
                   )
                  )
               {
@@ -9105,6 +9106,7 @@ void initDoxygen()
   Doxygen::parserManager->registerParser("python",  new PythonLanguageScanner);
   Doxygen::parserManager->registerParser("fortran", new FortranLanguageScanner);
   Doxygen::parserManager->registerParser("vhdl",    new VHDLLanguageScanner);
+  Doxygen::parserManager->registerParser("dbusxml", new DBusXMLScanner);
 
   // register any additional parsers here...
 
diff --git a/src/libdoxygen.pro.in b/src/libdoxygen.pro.in
index 2eabf69..ec2e93c 100644
--- a/src/libdoxygen.pro.in
+++ b/src/libdoxygen.pro.in
@@ -88,6 +88,7 @@ HEADERS      =	bufstr.h \
                 pyscanner.h \
                 fortrancode.h \
                 fortranscanner.h \
+                dbusxmlscanner.h \
 		qhp.h \
 		qhpxmlwriter.h \
 		qtbc.h \
@@ -229,6 +230,7 @@ SOURCES      =	ce_lex.cpp \
 		vhdlscanner.cpp \
 		xmldocvisitor.cpp \
                 xmlgen.cpp \
+                dbusxmlscanner.cpp \
 
 win32:TMAKE_CXXFLAGS       += -DQT_NODLL 
 win32-msvc:TMAKE_CXXFLAGS  += -Zm200
diff --git a/src/util.cpp b/src/util.cpp
index 5072721..ef6131b 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -305,7 +305,8 @@ int guessSection(const char *name)
       n.right(4)==".ixx"  ||
       n.right(4)==".ipp"  ||
       n.right(4)==".i++"  ||
-      n.right(4)==".inl"
+      n.right(4)==".inl"  ||
+      n.right(4)==".xml"
      ) return Entry::SOURCE_SEC;
   if (n.right(2)==".h"   || // header
       n.right(3)==".hh"  ||
@@ -6443,6 +6444,7 @@ g_lang2extMap[] =
   { "python",      "python",  SrcLangExt_Python },
   { "fortran",     "fortran", SrcLangExt_F90    },
   { "vhdl",        "vhdl",    SrcLangExt_VHDL   },
+  { "dbusxml",     "dbusxml", SrcLangExt_XML    },
   { 0,             0,        (SrcLangExt)0      }
 };
 
@@ -6505,6 +6507,7 @@ void initDefaultExtensionMapping()
   updateLanguageMapping(".f90",   "fortran");
   updateLanguageMapping(".vhd",   "vhdl");
   updateLanguageMapping(".vhdl",  "vhdl");
+  updateLanguageMapping(".xml",   "dbusxml");
 }
 
 SrcLangExt getLanguageFromFileName(const QCString fileName)
diff --git a/src/util.h b/src/util.h
index 2b248a3..1c56e90 100644
--- a/src/util.h
+++ b/src/util.h
@@ -95,7 +95,8 @@ enum SrcLangExt
   SrcLangExt_JS     = 0x0400,
   SrcLangExt_Python = 0x0800,
   SrcLangExt_F90    = 0x1000,
-  SrcLangExt_VHDL   = 0x2000
+  SrcLangExt_VHDL   = 0x2000,
+  SrcLangExt_XML    = 0x4000
 };
 
 //--------------------------------------------------------------------
