Fixed inheritance hierarchy, namespace handling
[shibboleth/cpp-xmltooling.git] / xmltooling / io / AbstractXMLObjectUnmarshaller.cpp
index e6bdf7e..939311f 100644 (file)
@@ -56,17 +56,19 @@ XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool b
         XT_log.debug("unmarshalling DOM element %s", dname.get());\r
     }\r
 \r
-    XMLObject* xmlObject = buildXMLObject(element);\r
+    auto_ptr<XMLObject> xmlObject(buildXMLObject(element));\r
 \r
     if (element->hasAttributes()) {\r
-        unmarshallAttributes(element, xmlObject);\r
+        unmarshallAttributes(element, *(xmlObject.get()));\r
     }\r
 \r
-    if (element->getTextContent()) {\r
-        processElementContent(xmlObject, element->getTextContent());\r
+    const XMLCh* textContent=element->getTextContent();\r
+    if (textContent && *textContent) {\r
+        XT_log.debug("processing element content");\r
+        processElementContent(*(xmlObject.get()), textContent);\r
     }\r
 \r
-    unmarshallChildElements(element, xmlObject);\r
+    unmarshallChildElements(element, *(xmlObject.get()));\r
 \r
     /* TODO: Signing\r
     if (xmlObject instanceof SignableXMLObject) {\r
@@ -74,11 +76,13 @@ XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool b
     }\r
     */\r
 \r
-    DOMCachingXMLObject* dc=dynamic_cast<DOMCachingXMLObject*>(xmlObject);\r
+    DOMCachingXMLObject* dc=dynamic_cast<DOMCachingXMLObject*>(xmlObject.get());\r
     if (dc)\r
         dc->setDOM(element,bindDocument);\r
+    else if (bindDocument)\r
+        throw UnmarshallingException("Unable to bind document to non-DOM caching XMLObject instance.");\r
         \r
-    return xmlObject;\r
+    return xmlObject.release();\r
 }\r
 \r
 XMLObject* AbstractXMLObjectUnmarshaller::buildXMLObject(const DOMElement* domElement) const\r
@@ -89,7 +93,7 @@ XMLObject* AbstractXMLObjectUnmarshaller::buildXMLObject(const DOMElement* domEl
     throw UnmarshallingException("Failed to locate XMLObjectBuilder for element.");\r
 }\r
 \r
-void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement, XMLObject* xmlObject) const\r
+void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement, XMLObject& xmlObject) const\r
 {\r
 #ifdef _DEBUG\r
     xmltooling::NDC ndc("unmarshallAttributes");\r
@@ -121,25 +125,35 @@ void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domEl
         attribute = static_cast<DOMAttr*>(childNode);\r
         \r
         const XMLCh* nsuri=attribute->getNamespaceURI();\r
-        if (!XMLString::compareString(nsuri,XMLConstants::XMLNS_NS)) {\r
-            XT_log.debug("found namespace declaration, adding it to the list of namespaces on the XMLObject");\r
-            xmlObject->addNamespace(Namespace(attribute->getValue(), attribute->getLocalName()));\r
-            continue;\r
+        if (XMLString::equals(nsuri,XMLConstants::XMLNS_NS)) {\r
+            if (XMLString::equals(attribute->getLocalName(),XMLConstants::XMLNS_PREFIX)) {\r
+                XT_log.debug("found default namespace declaration, adding it to the list of namespaces on the XMLObject");\r
+                xmlObject.addNamespace(Namespace(attribute->getValue(), NULL, true));\r
+                continue;\r
+            }\r
+            else {\r
+                XT_log.debug("found namespace declaration, adding it to the list of namespaces on the XMLObject");\r
+                xmlObject.addNamespace(Namespace(attribute->getValue(), attribute->getLocalName(), true));\r
+                continue;\r
+            }\r
         }\r
-        else if (!XMLString::compareString(nsuri,XMLConstants::XSI_NS) &&\r
-                    !XMLString::compareString(attribute->getLocalName(),type)) {\r
+        else if (XMLString::equals(nsuri,XMLConstants::XSI_NS) && XMLString::equals(attribute->getLocalName(),type)) {\r
             XT_log.debug("found xsi:type declaration, setting the schema type of the XMLObject");\r
             auto_ptr<QName> xsitype(XMLHelper::getAttributeValueAsQName(attribute));\r
-            xmlObject->setSchemaType(xsitype.get());\r
+            xmlObject.setSchemaType(xsitype.get());\r
             continue;\r
         }\r
+        else if (nsuri) {\r
+            XT_log.debug("found namespace-qualified attribute, adding prefix to the list of namespaces on the XMLObject");\r
+            xmlObject.addNamespace(Namespace(nsuri, attribute->getPrefix()));\r
+        }\r
 \r
         XT_log.debug("processing generic attribute");\r
         processAttribute(xmlObject, attribute);\r
     }\r
 }\r
 \r
-void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement, XMLObject* xmlObject) const\r
+void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement, XMLObject& xmlObject) const\r
 {\r
 #ifdef _DEBUG\r
     xmltooling::NDC ndc("unmarshallChildElements");\r
@@ -175,7 +189,11 @@ void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* do
                 auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
                 XT_log.debug("unmarshalling child element %s", cname->toString().c_str());\r
             }\r
-            processChildElement(xmlObject, unmarshaller->unmarshall(static_cast<DOMElement*>(childNode)));\r
+\r
+            // Retain ownership of the unmarshalled child until it's processed by the parent.\r
+            auto_ptr<XMLObject> childObject(unmarshaller->unmarshall(static_cast<DOMElement*>(childNode)));\r
+            processChildElement(xmlObject, childObject.get());\r
+            childObject.release();\r
         }\r
     }\r
 }\r