*/\r
\r
#include "internal.h"\r
-#include "DOMCachingXMLObject.h"\r
#include "exceptions.h"\r
#include "XMLObjectBuilder.h"\r
#include "io/AbstractXMLObjectUnmarshaller.h"\r
\r
#define XT_log (*static_cast<Category*>(m_log))\r
\r
-AbstractXMLObjectUnmarshaller::AbstractXMLObjectUnmarshaller(const XMLCh* targetNamespaceURI, const XMLCh* targetLocalName)\r
- : m_targetQName(targetNamespaceURI, targetLocalName),\r
- m_log(&Category::getInstance(XMLTOOLING_LOGCAT".Unmarshaller")) {\r
- if (!targetLocalName || !*targetLocalName)\r
- throw UnmarshallingException("targetLocalName cannot be null or empty");\r
-}\r
-\r
-XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool bindDocument) const\r
+XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool bindDocument)\r
{\r
#ifdef _DEBUG\r
xmltooling::NDC ndc("unmarshall");\r
#endif\r
\r
if (XT_log.isDebugEnabled()) {\r
- auto_ptr_char dname(element->getLocalName());\r
- XT_log.debug("unmarshalling DOM element %s", dname.get());\r
+ auto_ptr_char dname(element->getNodeName());\r
+ XT_log.debug("unmarshalling DOM element (%s)", dname.get());\r
}\r
\r
-#ifdef _DEBUG\r
- checkElementIsTarget(element);\r
-#endif\r
-\r
- XMLObject* xmlObject = buildXMLObject(element);\r
-\r
if (element->hasAttributes()) {\r
- unmarshallAttributes(element, xmlObject);\r
- }\r
-\r
- if (element->getTextContent()) {\r
- processElementContent(xmlObject, element->getTextContent());\r
+ unmarshallAttributes(element);\r
}\r
\r
- unmarshallChildElements(element, xmlObject);\r
+ unmarshallChildElements(element);\r
\r
/* TODO: Signing\r
if (xmlObject instanceof SignableXMLObject) {\r
}\r
*/\r
\r
- DOMCachingXMLObject* dc=dynamic_cast<DOMCachingXMLObject*>(xmlObject);\r
- if (dc)\r
- dc->setDOM(element,bindDocument);\r
- \r
- return xmlObject;\r
-}\r
-\r
-void AbstractXMLObjectUnmarshaller::checkElementIsTarget(const DOMElement* domElement) const\r
-{\r
- auto_ptr<QName> elementName(XMLHelper::getNodeQName(domElement));\r
-\r
- XT_log.debug("checking that root element meets target criteria");\r
-\r
- auto_ptr<QName> type(XMLHelper::getXSIType(domElement));\r
-\r
- if (type.get() && m_targetQName==*(type.get())) {\r
- XT_log.debug("schema type of element matches target");\r
- return;\r
- }\r
- else {\r
- if (m_targetQName==*(elementName.get())) {\r
- XT_log.debug("element name matches target");\r
- return;\r
- }\r
- else {\r
- XT_log.errorStream() << "unmarshaller for (" << m_targetQName.toString()\r
- << ") passed (" << elementName->toString() << ")" << CategoryStream::ENDLINE;\r
- throw UnmarshallingException("Incorrect element type passed to unmarshaller.");\r
- }\r
- }\r
-}\r
-\r
-XMLObject* AbstractXMLObjectUnmarshaller::buildXMLObject(const DOMElement* domElement) const\r
-{\r
- const XMLObjectBuilder* xmlObjectBuilder = XMLObjectBuilder::getBuilder(domElement);\r
- if (xmlObjectBuilder)\r
- return xmlObjectBuilder->buildObject();\r
- throw UnmarshallingException("Failed to locate XMLObjectBuilder for element.");\r
+ setDOM(element,bindDocument);\r
+ return this;\r
}\r
\r
-void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement, XMLObject* xmlObject) const\r
+void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement)\r
{\r
#ifdef _DEBUG\r
xmltooling::NDC ndc("unmarshallAttributes");\r
static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull};\r
\r
if (XT_log.isDebugEnabled()) {\r
- auto_ptr_char dname(domElement->getLocalName());\r
- XT_log.debug("unmarshalling attributes for DOM element %s", dname.get());\r
+ auto_ptr_char dname(domElement->getNodeName());\r
+ XT_log.debug("unmarshalling attributes for DOM element (%s)", dname.get());\r
}\r
\r
DOMNamedNodeMap* attributes = domElement->getAttributes();\r
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
+ 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
+ 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
+ setSchemaType(xsitype.get());\r
continue;\r
}\r
+ else if (nsuri && !XMLString::equals(nsuri,XMLConstants::XML_NS)) {\r
+ XT_log.debug("found namespace-qualified attribute, adding prefix to the list of namespaces on the XMLObject");\r
+ addNamespace(Namespace(nsuri, attribute->getPrefix()));\r
+ }\r
\r
XT_log.debug("processing generic attribute");\r
- processAttribute(xmlObject, attribute);\r
+ processAttribute(attribute);\r
}\r
}\r
\r
-void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement, XMLObject* xmlObject) const\r
+void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement)\r
{\r
#ifdef _DEBUG\r
xmltooling::NDC ndc("unmarshallChildElements");\r
#endif\r
\r
if (XT_log.isDebugEnabled()) {\r
- auto_ptr_char dname(domElement->getLocalName());\r
- XT_log.debug("unmarshalling child elements of DOM element %s", dname.get());\r
+ auto_ptr_char dname(domElement->getNodeName());\r
+ XT_log.debug("unmarshalling child elements of DOM element (%s)", dname.get());\r
}\r
\r
DOMNodeList* childNodes = domElement->getChildNodes();\r
DOMNode* childNode;\r
- const Unmarshaller* unmarshaller;\r
if (!childNodes || childNodes->getLength()==0) {\r
XT_log.debug("element had no children");\r
return;\r
for (XMLSize_t i = 0; i < childNodes->getLength(); i++) {\r
childNode = childNodes->item(i);\r
if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) {\r
- unmarshaller = Unmarshaller::getUnmarshaller(static_cast<DOMElement*>(childNode));\r
- if (!unmarshaller) {\r
- if (config.ignoreUnknownElements) {\r
- unmarshaller=Unmarshaller::getDefaultUnmarshaller();\r
- if (!unmarshaller) {\r
- auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
- XT_log.error("no default unmarshaller installed, detected unknown child element %s", cname->toString().c_str());\r
- throw UnmarshallingException("Unmarshaller detected unknown child element, but no default unmarshaller was found.");\r
- }\r
- else {\r
- XT_log.debug("using default unmarshaller");\r
- }\r
- }\r
- else {\r
- auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
- XT_log.error("detected unknown child element %s", cname->toString().c_str());\r
- throw UnknownElementException("Unmarshaller detected unknown child element.");\r
- }\r
+ const XMLObjectBuilder* builder = XMLObjectBuilder::getBuilder(static_cast<DOMElement*>(childNode));\r
+ if (!builder) {\r
+ auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
+ XT_log.error("no default builder installed, found unknown child element (%s)", cname->toString().c_str());\r
+ throw UnmarshallingException("Unmarshaller found unknown child element, but no default builder was found.");\r
}\r
\r
if (XT_log.isDebugEnabled()) {\r
auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
- XT_log.debug("unmarshalling child element %s", cname->toString().c_str());\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(builder->buildObject(static_cast<DOMElement*>(childNode)));\r
+ childObject->unmarshall(static_cast<DOMElement*>(childNode));\r
+ processChildElement(childObject.get(), static_cast<DOMElement*>(childNode));\r
+ childObject.release();\r
+ }\r
+ else if (childNode->getNodeType() == DOMNode::TEXT_NODE) {\r
+ XT_log.debug("processing element content");\r
+ processElementContent(childNode->getNodeValue());\r
}\r
}\r
}\r