Index: /trunk/include/iprt/cpp/xml.h
===================================================================
--- /trunk/include/iprt/cpp/xml.h	(revision 28163)
+++ /trunk/include/iprt/cpp/xml.h	(revision 28164)
@@ -467,5 +467,6 @@
     xmlNode     *m_plibNode;            // != NULL if this is an element or content node
     xmlAttr     *m_plibAttr;            // != NULL if this is an attribute node
-    const char  *m_pcszNamespace;
+    const char  *m_pcszNamespacePrefix; // not always set
+    const char  *m_pcszNamespaceHref;   // full http:// spec
     const char  *m_pcszName;            // element or attribute name, points either into plibNode or plibAttr;
                                         // NULL if this is a content node
@@ -478,9 +479,11 @@
     Node(const Node &x);      // no copying
 
-    void buildChildren();
+    void buildChildren(const ElementNode &elmRoot);
 
     /* Obscure class data */
     struct Data;
     Data *m;
+
+    friend class AttributeNode;
 };
 
@@ -530,6 +533,8 @@
 protected:
     // hide the default constructor so people use only our factory methods
-    ElementNode(Node *pParent, xmlNode *plibNode);
+    ElementNode(const ElementNode *pelmRoot, Node *pParent, xmlNode *plibNode);
     ElementNode(const ElementNode &x);      // no copying
+
+    const ElementNode *m_pelmRoot;
 
     friend class Node;
@@ -557,6 +562,11 @@
 protected:
     // hide the default constructor so people use only our factory methods
-    AttributeNode(Node *pParent, xmlAttr *plibAttr);
+    AttributeNode(const ElementNode &elmRoot,
+                  Node *pParent,
+                  xmlAttr *plibAttr,
+                  const char **ppcszKey);
     AttributeNode(const AttributeNode &x);      // no copying
+
+    iprt::MiniString    m_strKey;
 
     friend class Node;
Index: /trunk/src/VBox/Runtime/r3/xml.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/xml.cpp	(revision 28163)
+++ /trunk/src/VBox/Runtime/r3/xml.cpp	(revision 28164)
@@ -445,5 +445,6 @@
       m_plibNode(plibNode),
       m_plibAttr(plibAttr),
-      m_pcszNamespace(NULL),
+      m_pcszNamespacePrefix(NULL),
+      m_pcszNamespaceHref(NULL),
       m_pcszName(NULL),
       m(new Data)
@@ -456,5 +457,5 @@
 }
 
-void Node::buildChildren()       // private
+void Node::buildChildren(const ElementNode &elmRoot)       // private
 {
     // go thru this element's attributes
@@ -462,8 +463,8 @@
     while (plibAttr)
     {
-        const char *pcszAttribName = (const char*)plibAttr->name;
-        boost::shared_ptr<AttributeNode> pNew(new AttributeNode(this, plibAttr));
+        const char *pcszKey;
+        boost::shared_ptr<AttributeNode> pNew(new AttributeNode(elmRoot, this, plibAttr, &pcszKey));
         // store
-        m->attribs[pcszAttribName] = pNew;
+        m->attribs[pcszKey] = pNew;
 
         plibAttr = plibAttr->next;
@@ -477,5 +478,5 @@
 
         if (plibNode->type == XML_ELEMENT_NODE)
-            pNew = boost::shared_ptr<Node>(new ElementNode(this, plibNode));
+            pNew = boost::shared_ptr<Node>(new ElementNode(&elmRoot, this, plibNode));
         else if (plibNode->type == XML_TEXT_NODE)
             pNew = boost::shared_ptr<Node>(new ContentNode(this, plibNode));
@@ -486,5 +487,5 @@
 
             // recurse for this child element to get its own children
-            pNew->buildChildren();
+            pNew->buildChildren(elmRoot);
         }
 
@@ -519,8 +520,8 @@
         return true;
     // caller wants namespace:
-    if (!m_pcszNamespace)
+    if (!m_pcszNamespacePrefix)
         // but node has no namespace:
         return false;
-    return !strcmp(m_pcszNamespace, pcszNamespace);
+    return !strcmp(m_pcszNamespacePrefix, pcszNamespace);
 }
 
@@ -629,5 +630,7 @@
 }
 
-ElementNode::ElementNode(Node *pParent, xmlNode *plibNode)
+ElementNode::ElementNode(const ElementNode *pelmRoot,
+                         Node *pParent,
+                         xmlNode *plibNode)
     : Node(IsElement,
            pParent,
@@ -635,10 +638,15 @@
            NULL)
 {
+    if (!(m_pelmRoot = pelmRoot))
+        // NULL passed, then this is the root element
+        m_pelmRoot = this;
+
     m_pcszName = (const char*)plibNode->name;
 
-    if (    plibNode->ns
-         && plibNode->ns->prefix
-       )
-        m_pcszNamespace = (const char*)m_plibNode->ns->prefix;
+    if (plibNode->ns)
+    {
+        m_pcszNamespacePrefix = (const char*)m_plibNode->ns->prefix;
+        m_pcszNamespaceHref = (const char*)m_plibNode->ns->href;
+    }
 }
 
@@ -735,4 +743,20 @@
 
 /**
+ * Looks up the given attribute node in this element's attribute map.
+ *
+ * With respect to namespaces, the internal attributes map stores namespace
+ * prefixes with attribute names only if the attribute uses a non-default
+ * namespace. As a result, the following rules apply:
+ *
+ *  -- To find attributes from a non-default namespace, pcszMatch must not
+ *     be prefixed with a namespace.
+ *
+ *  -- To find attributes from the default namespace (or if the document does
+ *     not use namespaces), pcszMatch must be prefixed with the namespace
+ *     prefix and a colon.
+ *
+ * For example, if the document uses the "vbox:" namespace by default, you
+ * must omit "vbox:" from pcszMatch to find such attributes, whether they
+ * are specifed in the xml or not.
  *
  * @param pcszMatch
@@ -754,5 +778,5 @@
  * name and returns its value as a string.
  *
- * @param pcszMatch name of attribute to find.
+ * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
  * @param ppcsz out: attribute value
  * @return TRUE if attribute was found and str was thus updated.
@@ -774,5 +798,5 @@
  * name and returns its value as a string.
  *
- * @param pcszMatch name of attribute to find.
+ * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
  * @param str out: attribute value; overwritten only if attribute was found
  * @return TRUE if attribute was found and str was thus updated.
@@ -796,5 +820,5 @@
  * function returns no error.
  *
- * @param pcszMatch name of attribute to find.
+ * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
  * @param i out: attribute value; overwritten only if attribute was found
  * @return TRUE if attribute was found and str was thus updated.
@@ -817,5 +841,5 @@
  * function returns no error.
  *
- * @param pcszMatch name of attribute to find.
+ * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
  * @param i out: attribute value; overwritten only if attribute was found
  * @return TRUE if attribute was found and str was thus updated.
@@ -838,5 +862,5 @@
  * function returns no error.
  *
- * @param pcszMatch name of attribute to find.
+ * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
  * @param i out: attribute value
  * @return TRUE if attribute was found and str was thus updated.
@@ -859,5 +883,5 @@
  * function returns no error.
  *
- * @param pcszMatch name of attribute to find.
+ * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
  * @param i out: attribute value; overwritten only if attribute was found
  * @return TRUE if attribute was found and str was thus updated.
@@ -879,5 +903,5 @@
  * "yes", "no", "1" or "0" as valid values.
  *
- * @param pcszMatch name of attribute to find.
+ * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
  * @param f out: attribute value; overwritten only if attribute was found
  * @return TRUE if attribute was found and str was thus updated.
@@ -930,5 +954,5 @@
 
     // now wrap this in C++
-    ElementNode *p = new ElementNode(this, plibNode);
+    ElementNode *p = new ElementNode(m_pelmRoot, this, plibNode);
     boost::shared_ptr<ElementNode> pNew(p);
     m->children.push_back(pNew);
@@ -981,10 +1005,10 @@
         // libxml side: xmlNewProp creates an attribute
         xmlAttr *plibAttr = xmlNewProp(m_plibNode, (xmlChar*)pcszName, (xmlChar*)pcszValue);
-        const char *pcszAttribName = (const char*)plibAttr->name;
 
         // C++ side: create an attribute node around it
-        boost::shared_ptr<AttributeNode> pNew(new AttributeNode(this, plibAttr));
+        const char *pcszKey;
+        boost::shared_ptr<AttributeNode> pNew(new AttributeNode(*m_pelmRoot, this, plibAttr, &pcszKey));
         // store
-        m->attribs[pcszAttribName] = pNew;
+        m->attribs[pcszKey] = pNew;
     }
     else
@@ -1048,5 +1072,18 @@
 }
 
-AttributeNode::AttributeNode(Node *pParent, xmlAttr *plibAttr)
+/**
+ * Private constructur for a new attribute node. This one is special:
+ * in ppcszKey, it returns a pointer to a string buffer that should be
+ * used to index the attribute correctly with namespaces.
+ *
+ * @param pParent
+ * @param elmRoot
+ * @param plibAttr
+ * @param ppcszKey
+ */
+AttributeNode::AttributeNode(const ElementNode &elmRoot,
+                             Node *pParent,
+                             xmlAttr *plibAttr,
+                             const char **ppcszKey)
     : Node(IsAttribute,
            pParent,
@@ -1055,4 +1092,26 @@
 {
     m_pcszName = (const char*)plibAttr->name;
+
+    *ppcszKey = m_pcszName;
+
+    if (    plibAttr->ns
+         && plibAttr->ns->prefix
+       )
+    {
+        m_pcszNamespacePrefix = (const char*)plibAttr->ns->prefix;
+        m_pcszNamespaceHref = (const char*)plibAttr->ns->href;
+
+        if (    !elmRoot.m_pcszNamespaceHref
+             || (strcmp(m_pcszNamespaceHref, elmRoot.m_pcszNamespaceHref))
+           )
+        {
+            // not default namespace:
+            m_strKey = m_pcszNamespacePrefix;
+            m_strKey.append(':');
+            m_strKey.append(m_pcszName);
+
+            *ppcszKey = m_strKey.c_str();
+        }
+    }
 }
 
@@ -1191,7 +1250,7 @@
 void Document::refreshInternals() // private
 {
-    m->pRootElement = new ElementNode(NULL, xmlDocGetRootElement(m->plibDocument));
-
-    m->pRootElement->buildChildren();
+    m->pRootElement = new ElementNode(NULL, NULL, xmlDocGetRootElement(m->plibDocument));
+
+    m->pRootElement->buildChildren(*m->pRootElement);
 }
 
@@ -1234,5 +1293,5 @@
 
     // now wrap this in C++
-    m->pRootElement = new ElementNode(NULL, plibRootNode);
+    m->pRootElement = new ElementNode(NULL, NULL, plibRootNode);
 
     return m->pRootElement;
