Index: /trunk/include/iprt/cpp/xml.h
===================================================================
--- /trunk/include/iprt/cpp/xml.h	(revision 79676)
+++ /trunk/include/iprt/cpp/xml.h	(revision 79677)
@@ -58,4 +58,11 @@
 typedef struct _xmlNode xmlNode;
 
+#define RT_XML_CONTENT_SMALL _8K
+#define RT_XML_CONTENT_LARGE _128K
+#define RT_XML_ATTR_TINY 64
+#define RT_XML_ATTR_SMALL _1K
+#define RT_XML_ATTR_MEDIUM _8K
+#define RT_XML_ATTR_LARGE _64K
+
 /** @} */
 
@@ -253,5 +260,5 @@
      * Opens a file with the given name in the given mode. If @a aMode is Read
      * or ReadWrite, the file must exist. If @a aMode is Write, the file must
-     * not exist. Otherwise, an EIPRTFailure excetion will be thrown.
+     * not exist. Otherwise, an EIPRTFailure exception will be thrown.
      *
      * @param aMode     File mode.
@@ -410,4 +417,5 @@
 
     const char *getValue() const;
+    const char *getValueN(size_t cchValueLimit) const;
     bool copyValue(int32_t &i) const;
     bool copyValue(uint32_t &i) const;
@@ -594,4 +602,25 @@
         if (pElem)
             return pElem->getValue();
+        return NULL;
+    }
+
+    /** Finds the first child with matching the give name and optionally namspace,
+     *  returning its value. Checks the length against the limit.
+     *
+     * @returns Pointer to the child string value, NULL if not found or no value.
+     * @param   pcszPath        Path to the child element.  Slashes can be used to
+     *                          make a simple path to any decendant.
+     * @param   cchValueLimit   If the length of the returned value exceeds this
+     *                          limit a EIPRTFailure exception will be thrown.
+     * @param   pcszNamespace   The namespace to match, NULL (default) match any
+     *                          namespace.  When using a path, this matches all
+     *                          elements along the way.
+     * @see     findChildElement, findChildElementP
+     */
+    const char *findChildElementValuePN(const char *pcszPath, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+    {
+        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+        if (pElem)
+            return pElem->getValueN(cchValueLimit);
         return NULL;
     }
@@ -646,4 +675,31 @@
     }
 
+    /** Combines findChildElementP and findAttributeValueN.
+     *
+     * @returns Pointer to attribute string value, NULL if either the element or
+     *          the attribute was not found.
+     * @param   pcszPath            The attribute name.  Slashes can be used to make a
+     *                              simple path to any decendant.
+     * @param   pcszAttribute       The attribute name.
+     * @param   cchValueLimit       If the length of the returned value exceeds this
+     *                              limit a EIPRTFailure exception will be thrown.
+     * @param   pcszPathNamespace   The namespace to match @a pcszPath with, NULL
+     *                              (default) match any namespace.  When using a
+     *                              path, this matches all elements along the way.
+     * @param   pcszAttributeNamespace  The namespace prefix to apply to the
+     *                              attribute, NULL (default) match any namespace.
+     * @see     findChildElementP and findAttributeValue
+     */
+    const char *findChildElementAttributeValuePN(const char *pcszPath, const char *pcszAttribute,
+                                                 size_t cchValueLimit,
+                                                 const char *pcszPathNamespace = NULL,
+                                                 const char *pcszAttributeNamespace = NULL) const
+    {
+        const ElementNode *pElem = findChildElementP(pcszPath, pcszPathNamespace);
+        if (pElem)
+            return pElem->findAttributeValueN(pcszAttribute, cchValueLimit, pcszAttributeNamespace);
+        return NULL;
+    }
+
 
     /** @name Tree enumeration.
@@ -733,4 +789,20 @@
         if (pAttr)
             return pAttr->getValue();
+        return NULL;
+    }
+    /** Find the first attribute with the given name, returning its value string.
+     * @returns Pointer to the attribute string value.
+     * @param   pcszName        The attribute name.
+     * @param   cchValueLimit   If the length of the returned value exceeds this
+     *                          limit a EIPRTFailure exception will be thrown.
+     * @param   pcszNamespace   The namespace name, default is NULL which means
+     *                          anything goes.
+     * @see getAttributeValue
+     */
+    const char *findAttributeValueN(const char *pcszName, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+    {
+        const AttributeNode *pAttr = findAttribute(pcszName, pcszNamespace);
+        if (pAttr)
+            return pAttr->getValueN(cchValueLimit);
         return NULL;
     }
@@ -752,4 +824,10 @@
     bool getAttributeValue(const char *pcszMatch, bool &f, const char *pcszNamespace = NULL) const
     { return getAttributeValue(pcszMatch, &f, pcszNamespace); }
+    bool getAttributeValueN(const char *pcszMatch, const char *&pcsz, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+    { return getAttributeValueN(pcszMatch, &pcsz, cchValueLimit, pcszNamespace); }
+    bool getAttributeValueN(const char *pcszMatch, RTCString &str, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+    { return getAttributeValueN(pcszMatch, &str, cchValueLimit, pcszNamespace); }
+    bool getAttributeValuePathN(const char *pcszMatch, RTCString &str, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+    { return getAttributeValueN(pcszMatch, &str, cchValueLimit, pcszNamespace); }
 
     /** @name Variants that for clarity does not use references for output params.
@@ -763,4 +841,7 @@
     bool getAttributeValue(const char *pcszMatch, uint64_t *pu, const char *pcszNamespace = NULL) const;
     bool getAttributeValue(const char *pcszMatch, bool *pf, const char *pcszNamespace = NULL) const;
+    bool getAttributeValueN(const char *pcszMatch, const char **ppcsz, size_t cchValueLimit, const char *pcszNamespace = NULL) const;
+    bool getAttributeValueN(const char *pcszMatch, RTCString *pStr, size_t cchValueLimit, const char *pcszNamespace = NULL) const;
+    bool getAttributeValuePathN(const char *pcszMatch, RTCString *pStr, size_t cchValueLimit, const char *pcszNamespace = NULL) const;
     /** @} */
 
Index: /trunk/src/VBox/Main/src-all/ExtPackUtil.cpp
===================================================================
--- /trunk/src/VBox/Main/src-all/ExtPackUtil.cpp	(revision 79676)
+++ /trunk/src/VBox/Main/src-all/ExtPackUtil.cpp	(revision 79677)
@@ -113,5 +113,5 @@
 
     RTCString strFormatVersion;
-    if (!pVBoxExtPackElm->getAttributeValue("version", strFormatVersion))
+    if (!pVBoxExtPackElm->getAttributeValueN("version", strFormatVersion, RT_XML_ATTR_TINY))
         return new RTCString("Missing format version");
     if (!strFormatVersion.equals("1.0"))
@@ -124,5 +124,5 @@
     if (!pNameElm)
         return new RTCString("The 'Name' element is missing");
-    const char *pszName = pNameElm->getValue();
+    const char *pszName = pNameElm->getValueN(RT_XML_CONTENT_SMALL);
     if (!VBoxExtPackIsValidName(pszName))
         return &(new RTCString("Invalid name: "))->append(pszName);
@@ -131,5 +131,5 @@
     if (!pDescElm)
         return new RTCString("The 'Description' element is missing");
-    const char *pszDesc = pDescElm->getValue();
+    const char *pszDesc = pDescElm->getValueN(RT_XML_CONTENT_LARGE);
     if (!pszDesc || *pszDesc == '\0')
         return new RTCString("The 'Description' element is empty");
@@ -140,5 +140,5 @@
     if (!pVersionElm)
         return new RTCString("The 'Version' element is missing");
-    const char *pszVersion = pVersionElm->getValue();
+    const char *pszVersion = pVersionElm->getValueN(RT_XML_CONTENT_SMALL);
     if (!pszVersion || *pszVersion == '\0')
         return new RTCString("The 'Version' element is empty");
@@ -151,5 +151,5 @@
 
     const char *pszEdition;
-    if (!pVersionElm->getAttributeValue("edition", pszEdition))
+    if (!pVersionElm->getAttributeValueN("edition", pszEdition, RT_XML_ATTR_TINY))
         pszEdition = "";
     if (!VBoxExtPackIsValidEditionString(pszEdition))
@@ -159,5 +159,5 @@
     if (!pMainModuleElm)
         return new RTCString("The 'MainModule' element is missing");
-    const char *pszMainModule = pMainModuleElm->getValue();
+    const char *pszMainModule = pMainModuleElm->getValueN(RT_XML_CONTENT_SMALL);
     if (!pszMainModule || *pszMainModule == '\0')
         return new RTCString("The 'MainModule' element is empty");
@@ -173,5 +173,5 @@
     if (pMainVMModuleElm)
     {
-        pszMainVMModule = pMainVMModuleElm->getValue();
+        pszMainVMModule = pMainVMModuleElm->getValueN(RT_XML_CONTENT_SMALL);
         if (!pszMainVMModule || *pszMainVMModule == '\0')
             pszMainVMModule = NULL;
@@ -188,5 +188,5 @@
     if (pVrdeModuleElm)
     {
-        pszVrdeModule = pVrdeModuleElm->getValue();
+        pszVrdeModule = pVrdeModuleElm->getValueN(RT_XML_CONTENT_SMALL);
         if (!pszVrdeModule || *pszVrdeModule == '\0')
             pszVrdeModule = NULL;
@@ -282,5 +282,12 @@
      * Hand the xml doc over to the common code.
      */
-    return vboxExtPackLoadDescFromDoc(&Doc, a_pExtPackDesc);
+    try
+    {
+        return vboxExtPackLoadDescFromDoc(&Doc, a_pExtPackDesc);
+    }
+    catch (RTCError &rXcpt)      // includes all XML exceptions
+    {
+        return new RTCString(rXcpt.what());
+    }
 }
 
@@ -358,5 +365,12 @@
      */
     if (RT_SUCCESS(rc))
-        pstrErr = vboxExtPackLoadDescFromDoc(&Doc, a_pExtPackDesc);
+        try
+        {
+            pstrErr = vboxExtPackLoadDescFromDoc(&Doc, a_pExtPackDesc);
+        }
+        catch (RTCError &rXcpt)      // includes all XML exceptions
+        {
+            return new RTCString(rXcpt.what());
+        }
 
     return pstrErr;
Index: /trunk/src/VBox/Main/xml/ovfreader.cpp
===================================================================
--- /trunk/src/VBox/Main/xml/ovfreader.cpp	(revision 79676)
+++ /trunk/src/VBox/Main/xml/ovfreader.cpp	(revision 79677)
@@ -107,5 +107,5 @@
     if ((pTypeAttr = pRootElem->findAttribute("lang", "xml")))
     {
-        pcszTypeAttr = pTypeAttr->getValue();
+        pcszTypeAttr = pTypeAttr->getValueN(RT_XML_ATTR_TINY);
         m_envelopeData.lang = pcszTypeAttr;
     }
@@ -148,5 +148,5 @@
         const char *pcszElemName = pElem->getName();
         const xml::AttributeNode *pTypeAttr = pElem->findAttribute("type");
-        const char *pcszTypeAttr = pTypeAttr ? pTypeAttr->getValue() : "";
+        const char *pcszTypeAttr = pTypeAttr ? pTypeAttr->getValueN(RT_XML_ATTR_TINY) : "";
 
         if (    !strcmp(pcszElemName, "DiskSection")
@@ -226,7 +226,7 @@
         const char *pcszDiskId;
         const char *pcszFormat;
-        if (!pelmDisk->getAttributeValue("diskId", pcszDiskId))
+        if (!pelmDisk->getAttributeValueN("diskId", pcszDiskId, RT_XML_ATTR_TINY))
             pcszBad = "diskId";
-        else if (!pelmDisk->getAttributeValue("format", pcszFormat))
+        else if (!pelmDisk->getAttributeValueN("format", pcszFormat, RT_XML_ATTR_SMALL))
             pcszBad = "format";
         else if (!pelmDisk->getAttributeValue("capacity", d.iCapacity))
@@ -242,8 +242,8 @@
 
             // optional vbox:uuid attribute (if OVF was exported by VirtualBox != 3.2)
-            pelmDisk->getAttributeValue("uuid", d.uuidVBox, "vbox");
+            pelmDisk->getAttributeValueN("uuid", d.uuidVBox, RT_XML_ATTR_TINY, "vbox");
 
             const char *pcszFileRef;
-            if (pelmDisk->getAttributeValue("fileRef", pcszFileRef)) // optional
+            if (pelmDisk->getAttributeValueN("fileRef", pcszFileRef, RT_XML_ATTR_SMALL)) // optional
             {
                 // look up corresponding /References/File nodes (list built above)
@@ -257,5 +257,5 @@
                     const char *pcszBadInFile = NULL;
                     const char *pcszHref;
-                    if (!pFileElem->getAttributeValue("href", pcszHref))
+                    if (!pFileElem->getAttributeValueN("href", pcszHref, RT_XML_ATTR_SMALL))
                         pcszBadInFile = "href";
                     else if (!pFileElem->getAttributeValue("size", d.iSize))
@@ -267,5 +267,5 @@
                     d.iChunkSize = -1;       // optional
                     const char *pcszCompression;
-                    if (pFileElem->getAttributeValue("compression", pcszCompression))
+                    if (pFileElem->getAttributeValueN("compression", pcszCompression, RT_XML_ATTR_TINY))
                         d.strCompression = pcszCompression;
 
@@ -350,5 +350,5 @@
     const xml::AttributeNode *pIdAttr = pelmVirtualSystem->findAttribute("id");
     if (pIdAttr)
-        vsys.strName = pIdAttr->getValue();
+        vsys.strName = pIdAttr->getValueN(RT_XML_ATTR_SMALL);
 
     xml::NodesLoop loop(*pelmVirtualSystem);      // all child elements
@@ -362,5 +362,5 @@
             const xml::AttributeNode *pTypeAttr = pelmThis->findAttribute("type");
             if (pTypeAttr)
-                pcszTypeAttr = pTypeAttr->getValue();
+                pcszTypeAttr = pTypeAttr->getValueN(RT_XML_ATTR_TINY);
             else
                 throw OVFLogicError(N_("Error reading \"%s\": element \"Section\" has no \"type\" attribute, line %d"),
@@ -380,5 +380,5 @@
             const xml::ElementNode *pelmLicense;
             if ((pelmLicense = pelmThis->findChildElement("License")))
-                vsys.strLicenseText = pelmLicense->getValue();
+                vsys.strLicenseText = pelmLicense->getValueN(RT_XML_CONTENT_LARGE);
         }
         if (    !strcmp(pcszElemName, "ProductSection")
@@ -396,17 +396,17 @@
             const xml::ElementNode *pelmProduct;
             if ((pelmProduct = pelmThis->findChildElement("Product")))
-                vsys.strProduct = pelmProduct->getValue();
+                vsys.strProduct = pelmProduct->getValueN(RT_XML_CONTENT_SMALL);
             const xml::ElementNode *pelmVendor;
             if ((pelmVendor = pelmThis->findChildElement("Vendor")))
-                vsys.strVendor = pelmVendor->getValue();
+                vsys.strVendor = pelmVendor->getValueN(RT_XML_CONTENT_SMALL);
             const xml::ElementNode *pelmVersion;
             if ((pelmVersion = pelmThis->findChildElement("Version")))
-                vsys.strVersion = pelmVersion->getValue();
+                vsys.strVersion = pelmVersion->getValueN(RT_XML_CONTENT_SMALL);
             const xml::ElementNode *pelmProductUrl;
             if ((pelmProductUrl = pelmThis->findChildElement("ProductUrl")))
-                vsys.strProductUrl = pelmProductUrl->getValue();
+                vsys.strProductUrl = pelmProductUrl->getValueN(RT_XML_CONTENT_SMALL);
             const xml::ElementNode *pelmVendorUrl;
             if ((pelmVendorUrl = pelmThis->findChildElement("VendorUrl")))
-                vsys.strVendorUrl = pelmVendorUrl->getValue();
+                vsys.strVendorUrl = pelmVendorUrl->getValueN(RT_XML_CONTENT_SMALL);
         }
         else if (    !strcmp(pcszElemName, "VirtualHardwareSection")
@@ -425,5 +425,5 @@
                 </System>*/
                 if ((pelmVirtualSystemType = pelmSystem->findChildElement("VirtualSystemType")))
-                    vsys.strVirtualSystemType = pelmVirtualSystemType->getValue();
+                    vsys.strVirtualSystemType = pelmVirtualSystemType->getValueN(RT_XML_CONTENT_SMALL);
             }
 
@@ -792,10 +792,10 @@
             const xml::ElementNode *pelmCIMOSDescription;
             if ((pelmCIMOSDescription = pelmThis->findChildElement("Description")))
-                vsys.strCimosDesc = pelmCIMOSDescription->getValue();
+                vsys.strCimosDesc = pelmCIMOSDescription->getValueN(RT_XML_CONTENT_SMALL);
 
             const xml::ElementNode *pelmVBoxOSType;
             if ((pelmVBoxOSType = pelmThis->findChildElementNS("vbox",            // namespace
                                                                "OSType")))        // element name
-                vsys.strTypeVBox = pelmVBoxOSType->getValue();
+                vsys.strTypeVBox = pelmVBoxOSType->getValueN(RT_XML_CONTENT_SMALL);
         }
         else if (    (!strcmp(pcszElemName, "AnnotationSection"))
@@ -805,5 +805,5 @@
             const xml::ElementNode *pelmAnnotation;
             if ((pelmAnnotation = pelmThis->findChildElement("Annotation")))
-                vsys.strDescription = pelmAnnotation->getValue();
+                vsys.strDescription = pelmAnnotation->getValueN(RT_XML_CONTENT_SMALL);
         }
     }
@@ -818,14 +818,14 @@
         const char *pcszItemChildName = pelmItemChild->getName();
         if (!strcmp(pcszItemChildName, "Description"))
-            strDescription = pelmItemChild->getValue();
+            strDescription = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "Caption"))
-            strCaption = pelmItemChild->getValue();
+            strCaption = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "ElementName"))
-            strElementName = pelmItemChild->getValue();
+            strElementName = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (   !strcmp(pcszItemChildName, "InstanceID")
                  || !strcmp(pcszItemChildName, "InstanceId") )
             pelmItemChild->copyValue(ulInstanceID);
         else if (!strcmp(pcszItemChildName, "HostResource"))
-            strHostResource = pelmItemChild->getValue();
+            strHostResource = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "ResourceType"))
         {
@@ -835,5 +835,5 @@
             fResourceRequired = true;
             const char *pcszAttValue;
-            if (item->getAttributeValue("required", pcszAttValue))
+            if (item->getAttributeValueN("required", pcszAttValue, RT_XML_ATTR_TINY))
             {
                 if (!strcmp(pcszAttValue, "false"))
@@ -842,24 +842,24 @@
         }
         else if (!strcmp(pcszItemChildName, "OtherResourceType"))
-            strOtherResourceType = pelmItemChild->getValue();
+            strOtherResourceType = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "ResourceSubType"))
-            strResourceSubType = pelmItemChild->getValue();
+            strResourceSubType = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "AutomaticAllocation"))
-            fAutomaticAllocation = (!strcmp(pelmItemChild->getValue(), "true")) ? true : false;
+            fAutomaticAllocation = (!strcmp(pelmItemChild->getValueN(RT_XML_CONTENT_SMALL), "true")) ? true : false;
         else if (!strcmp(pcszItemChildName, "AutomaticDeallocation"))
-            fAutomaticDeallocation = (!strcmp(pelmItemChild->getValue(), "true")) ? true : false;
+            fAutomaticDeallocation = (!strcmp(pelmItemChild->getValueN(RT_XML_CONTENT_SMALL), "true")) ? true : false;
         else if (!strcmp(pcszItemChildName, "Parent"))
             pelmItemChild->copyValue(ulParent);
         else if (!strcmp(pcszItemChildName, "Connection"))
-            strConnection = pelmItemChild->getValue();
+            strConnection = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "Address"))
         {
-            strAddress = pelmItemChild->getValue();
+            strAddress = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
             pelmItemChild->copyValue(lAddress);
         }
         else if (!strcmp(pcszItemChildName, "AddressOnParent"))
-            strAddressOnParent = pelmItemChild->getValue();
+            strAddressOnParent = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "AllocationUnits"))
-            strAllocationUnits = pelmItemChild->getValue();
+            strAllocationUnits = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "VirtualQuantity"))
             pelmItemChild->copyValue(ullVirtualQuantity);
@@ -871,9 +871,9 @@
             pelmItemChild->copyValue(ullWeight);
         else if (!strcmp(pcszItemChildName, "ConsumerVisibility"))
-            strConsumerVisibility = pelmItemChild->getValue();
+            strConsumerVisibility = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "MappingBehavior"))
-            strMappingBehavior = pelmItemChild->getValue();
+            strMappingBehavior = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "PoolID"))
-            strPoolID = pelmItemChild->getValue();
+            strPoolID = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "BusNumber"))
             pelmItemChild->copyValue(ulBusNumber);
@@ -921,11 +921,11 @@
         const char *pcszItemChildName = pelmItemChild->getName();
         if (!strcmp(pcszItemChildName, "HostExtentName"))
-            strHostExtentName = pelmItemChild->getValue();
+            strHostExtentName = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "OtherHostExtentNameFormat"))
-            strOtherHostExtentNameFormat = pelmItemChild->getValue();
+            strOtherHostExtentNameFormat = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "OtherHostExtentNameNamespace"))
-            strOtherHostExtentNameNamespace = pelmItemChild->getValue();
+            strOtherHostExtentNameNamespace = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "VirtualQuantityUnits"))
-            strVirtualQuantityUnits = pelmItemChild->getValue();
+            strVirtualQuantityUnits = pelmItemChild->getValueN(RT_XML_CONTENT_SMALL);
         else if (!strcmp(pcszItemChildName, "Access"))
         {
Index: /trunk/src/VBox/Runtime/r3/xml.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/xml.cpp	(revision 79676)
+++ /trunk/src/VBox/Runtime/r3/xml.cpp	(revision 79677)
@@ -565,4 +565,34 @@
 
 /**
+ * Returns the value of a node. If this node is an attribute, returns
+ * the attribute value; if this node is an element, then this returns
+ * the element text content.
+ * @return
+ * @param   cchValueLimit   If the length of the returned value exceeds this
+ *                          limit a EIPRTFailure exception will be thrown.
+ */
+const char *Node::getValueN(size_t cchValueLimit) const
+{
+    if (   m_pLibAttr
+        && m_pLibAttr->children
+        )
+    {
+        // libxml hides attribute values in another node created as a
+        // single child of the attribute node, and it's in the content field
+        AssertStmt(strlen((const char *)m_pLibAttr->children->content) <= cchValueLimit, throw EIPRTFailure(VERR_BUFFER_OVERFLOW, "Attribute '%s' exceeds limit of %zu bytes", m_pcszName, cchValueLimit));
+        return (const char *)m_pLibAttr->children->content;
+    }
+
+    if (   m_pLibNode
+        && m_pLibNode->children)
+    {
+        AssertStmt(strlen((const char *)m_pLibNode->children->content) <= cchValueLimit, throw EIPRTFailure(VERR_BUFFER_OVERFLOW, "Element '%s' exceeds limit of %zu bytes", m_pcszName, cchValueLimit));
+        return (const char *)m_pLibNode->children->content;
+    }
+
+    return NULL;
+}
+
+/**
  * Copies the value of a node into the given integer variable.
  * Returns TRUE only if a value was found and was actually an
@@ -1152,4 +1182,75 @@
             return true;
         }
+    }
+
+    return false;
+}
+
+/**
+ * Convenience method which attempts to find the attribute with the given
+ * name and returns its value as a string.
+ *
+ * @param   pcszMatch       Name of attribute to find.
+ * @param   ppcsz           Where to return the attribute.
+ * @param   cchValueLimit   If the length of the returned value exceeds this
+ *                          limit a EIPRTFailure exception will be thrown.
+ * @param   pcszNamespace   The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
+ */
+bool ElementNode::getAttributeValueN(const char *pcszMatch, const char **ppcsz, size_t cchValueLimit, const char *pcszNamespace /*= NULL*/) const
+{
+    const AttributeNode *pAttr = findAttribute(pcszMatch, pcszNamespace);
+    if (pAttr)
+    {
+        *ppcsz = pAttr->getValueN(cchValueLimit);
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Convenience method which attempts to find the attribute with the given
+ * name and returns its value as a string.
+ *
+ * @param   pcszMatch       Name of attribute to find.
+ * @param   pStr            Pointer to the string object that should receive the
+ *                          attribute value.
+ * @param   cchValueLimit   If the length of the returned value exceeds this
+ *                          limit a EIPRTFailure exception will be thrown.
+ * @param   pcszNamespace   The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
+ *
+ * @throws  Whatever the string class may throw on assignment.
+ */
+bool ElementNode::getAttributeValueN(const char *pcszMatch, RTCString *pStr, size_t cchValueLimit, const char *pcszNamespace /*= NULL*/) const
+{
+    const AttributeNode *pAttr = findAttribute(pcszMatch, pcszNamespace);
+    if (pAttr)
+    {
+        *pStr = pAttr->getValueN(cchValueLimit);
+        return true;
+    }
+
+    return false;
+}
+
+/**
+ * Like getAttributeValue (ministring variant), but makes sure that all backslashes
+ * are converted to forward slashes.
+ *
+ * @param   pcszMatch       Name of attribute to find.
+ * @param   pStr            Pointer to the string object that should
+ *                          receive the attribute path value.
+ * @param   cchValueLimit   If the length of the returned value exceeds this
+ *                          limit a EIPRTFailure exception will be thrown.
+ * @param   pcszNamespace   The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
+ */
+bool ElementNode::getAttributeValuePathN(const char *pcszMatch, RTCString *pStr, size_t cchValueLimit, const char *pcszNamespace /*= NULL*/) const
+{
+    if (getAttributeValueN(pcszMatch, pStr, cchValueLimit, pcszNamespace))
+    {
+        pStr->findReplace('\\', '/');
+        return true;
     }
 
