Bug fixes and API changes from second unit test.
authorScott Cantor <cantor.2@osu.edu>
Thu, 2 Mar 2006 05:54:02 +0000 (05:54 +0000)
committerScott Cantor <cantor.2@osu.edu>
Thu, 2 Mar 2006 05:54:02 +0000 (05:54 +0000)
18 files changed:
xmltooling/AbstractDOMCachingXMLObject.cpp
xmltooling/AbstractDOMCachingXMLObject.h
xmltooling/DOMCachingXMLObject.h
xmltooling/XMLObjectBuilder.cpp
xmltooling/base.h
xmltooling/impl/UnknownElement.h
xmltooling/internal.h
xmltooling/io/AbstractXMLObjectMarshaller.cpp
xmltooling/io/AbstractXMLObjectMarshaller.h
xmltooling/io/AbstractXMLObjectUnmarshaller.cpp
xmltooling/io/AbstractXMLObjectUnmarshaller.h
xmltooling/io/Unmarshaller.cpp
xmltoolingtest/UnknownTest.h
xmltoolingtest/UnmarshallingTest.h [new file with mode: 0644]
xmltoolingtest/XMLObjectBaseTestCase.h
xmltoolingtest/data/SimpleXMLObjectWithAttribute.xml [new file with mode: 0644]
xmltoolingtest/data/SimpleXMLObjectWithContent.xml [new file with mode: 0644]
xmltoolingtest/xmltoolingtest.vcproj

index 86f8bf7..750e3f9 100644 (file)
@@ -43,15 +43,9 @@ void AbstractDOMCachingXMLObject::setDOM(DOMElement* dom, bool bindDocument)
     m_dom=dom;\r
     if (dom) {\r
         if (bindDocument) {\r
-            DOMDocument* tmp=setDocument(dom->getOwnerDocument());\r
-            if (tmp)\r
-                tmp->release();\r
+            setDocument(dom->getOwnerDocument());\r
         }\r
     }\r
-    else if (m_document) {\r
-        m_document->release();\r
-        m_document=NULL;\r
-    }\r
 }\r
 \r
 void AbstractDOMCachingXMLObject::releaseDOM()\r
index dba39e7..453c634 100644 (file)
@@ -56,10 +56,10 @@ namespace xmltooling {
         /**\r
          * @see DOMCachingXMLObject::setDocument()\r
          */\r
-        DOMDocument* setDocument(DOMDocument* doc) {\r
-            DOMDocument* ret=m_document;\r
+        void setDocument(DOMDocument* doc) {\r
+            if (m_document)\r
+                m_document->release();\r
             m_document=doc;\r
-            return ret;\r
         }\r
     \r
         /**\r
@@ -112,7 +112,7 @@ namespace xmltooling {
             XMLCh* newString = XMLString::replicate(newValue);\r
             XMLString::trim(newString);\r
 \r
-            if (oldValue && !newValue || !oldValue && newValue || XMLString::compareString(oldValue,newValue))\r
+            if (!XMLString::equals(oldValue,newValue))\r
                 releaseThisandParentDOM();\r
     \r
             return newString;\r
index dfbe84c..84f33e2 100644 (file)
@@ -60,7 +60,7 @@ namespace xmltooling {
          * \r
          * @param doc DOM document bound to this object \r
          */\r
-        virtual DOMDocument* setDocument(DOMDocument* doc)=0;\r
+        virtual void setDocument(DOMDocument* doc)=0;\r
 \r
         /**\r
          * Releases the DOM representation of this XMLObject, if there is one.\r
index 24d434d..33c4225 100644 (file)
@@ -42,7 +42,7 @@ const XMLObjectBuilder* XMLObjectBuilder::getBuilder(const DOMElement* domElemen
     Category& log=Category::getInstance(XMLTOOLING_LOGCAT".XMLObjectBuilder");\r
  \r
     auto_ptr<QName> schemaType(XMLHelper::getXSIType(domElement));\r
-    const XMLObjectBuilder* xmlObjectBuilder = getBuilder(*(schemaType.get()));\r
+    const XMLObjectBuilder* xmlObjectBuilder = schemaType.get() ? getBuilder(*(schemaType.get())) : NULL;\r
     if (xmlObjectBuilder) {\r
         if (log.isDebugEnabled()) {\r
             log.debug("located XMLObjectBuilder for schema type: %s", schemaType->toString().c_str());\r
index d7c6016..5194776 100644 (file)
 #define NULL    0\r
 #endif\r
 \r
+#include <utility>\r
+\r
+namespace xmltooling {\r
+\r
+    /**\r
+     * Template function for cloning a sequence of XMLObjects.\r
+     * Invokes the clone() member on each element of the input sequence and adds the copy to\r
+     * the output sequence. Order is preserved.\r
+     * \r
+     * @param in    input sequence to clone\r
+     * @param out   output sequence to copy cloned pointers into\r
+     */\r
+    template<class InputSequence,class OutputSequence> void clone(const InputSequence& in, OutputSequence& out) {\r
+        for (InputSequence::const_iterator i=in.begin(); i!=in.end(); i++)\r
+            out.push_back((*i)->clone());\r
+    }\r
+\r
+    /*\r
+     * Functor for cleaning up heap objects in containers.\r
+     */\r
+    template<class T> struct cleanup\r
+    {\r
+        /**\r
+         * Function operator to delete an object.\r
+         * \r
+         * @param ptr   object to delete\r
+         */\r
+        void operator()(T* ptr) {delete ptr;}\r
+        \r
+        /**\r
+         * Function operator to delete an object stored as const.\r
+         * \r
+         * @param ptr   object to delete after casting away const\r
+         */\r
+        void operator()(const T* ptr) {delete const_cast<T*>(ptr);}\r
+    };\r
+\r
+    /*\r
+     * Functor for cleaning up heap objects in key/value containers.\r
+     */\r
+    template<class A,class B> struct cleanup_pair\r
+    {\r
+        /**\r
+         * Function operator to delete an object.\r
+         * \r
+         * @param p   a pair in which the second component is the object to delete\r
+         */\r
+        void operator()(const std::pair<A,B*>& p) {delete p.second;}\r
+    };\r
+};\r
+\r
 #endif /* __xmltooling_base_h__ */\r
index 787cea1..c22fa55 100644 (file)
@@ -46,9 +46,6 @@ namespace xmltooling {
     class XMLTOOL_DLLLOCAL UnknownElementImpl : public AbstractDOMCachingXMLObject\r
     {\r
     public:\r
-        UnknownElementImpl() {}\r
-        virtual ~UnknownElementImpl() {}\r
-\r
         /**\r
          * Overridden to ensure XML content of DOM isn't lost.\r
          * \r
@@ -92,9 +89,6 @@ namespace xmltooling {
     class XMLTOOL_DLLLOCAL UnknownElementBuilder : public virtual XMLObjectBuilder\r
     {\r
     public:\r
-        UnknownElementBuilder() {}\r
-        virtual ~UnknownElementBuilder() {}\r
-    \r
         /**\r
          * @see XMLObjectBuilder::buildObject()\r
          */\r
@@ -109,9 +103,6 @@ namespace xmltooling {
     class XMLTOOL_DLLLOCAL UnknownElementMarshaller : public virtual Marshaller\r
     {\r
     public:\r
-        UnknownElementMarshaller() {}\r
-        virtual ~UnknownElementMarshaller() {}\r
-    \r
         /**\r
          * @see Marshaller::marshall(XMLObject*,DOMDocument*)\r
          */\r
@@ -138,9 +129,6 @@ namespace xmltooling {
     class XMLTOOL_DLLLOCAL UnknownElementUnmarshaller : public virtual Unmarshaller\r
     {\r
     public:\r
-        UnknownElementUnmarshaller() {}\r
-        virtual ~UnknownElementUnmarshaller() {}\r
-    \r
         /**\r
          * @see Unmarshaller::unmarshall()\r
          */\r
index 199c644..2d7c6fa 100644 (file)
@@ -71,18 +71,6 @@ namespace xmltooling {
         //XSECProvider* m_xsec;\r
         //PlugManager m_plugMgr;\r
     };\r
-\r
-    // Template cleanup functors for use with for_each algorithm\r
-    template<class T> struct cleanup\r
-    {\r
-        void operator()(T* ptr) {delete ptr;}\r
-        void operator()(const T* ptr) {delete const_cast<T*>(ptr);}\r
-    };\r
-\r
-    template<class A,class B> struct cleanup_pair\r
-    {\r
-        void operator()(const std::pair<A,B*>& p) {delete p.second;}\r
-    };\r
 };\r
 \r
 #endif /* __xmltooling_internal_h__ */\r
index 0b09c3e..2c0d537 100644 (file)
@@ -92,7 +92,7 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMDocum
             xmlObject->getElementQName().getNamespaceURI(), xmlObject->getElementQName().getLocalPart()\r
             );\r
         setDocumentElement(document, domElement);\r
-        marshallInto(xmlObject, domElement);\r
+        marshallInto(*xmlObject, domElement);\r
 \r
         //Recache the DOM.\r
         if (dc) {\r
@@ -151,7 +151,7 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMEleme
         xmlObject->getElementQName().getNamespaceURI(), xmlObject->getElementQName().getLocalPart()\r
         );\r
     parentElement->appendChild(domElement);\r
-    marshallInto(xmlObject, domElement);\r
+    marshallInto(*xmlObject, domElement);\r
 \r
     //Recache the DOM.\r
     if (dc) {\r
@@ -163,9 +163,9 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMEleme
     return domElement;\r
 }\r
         \r
-void AbstractXMLObjectMarshaller::marshallInto(XMLObject* xmlObject, DOMElement* targetElement) const\r
+void AbstractXMLObjectMarshaller::marshallInto(XMLObject& xmlObject, DOMElement* targetElement) const\r
 {\r
-    targetElement->setPrefix(xmlObject->getElementQName().getPrefix());\r
+    targetElement->setPrefix(xmlObject.getElementQName().getPrefix());\r
     marshallElementType(xmlObject, targetElement);\r
     marshallNamespaces(xmlObject, targetElement);\r
     marshallAttributes(xmlObject, targetElement);\r
@@ -183,9 +183,9 @@ void AbstractXMLObjectMarshaller::marshallInto(XMLObject* xmlObject, DOMElement*
     */\r
 }\r
 \r
-void AbstractXMLObjectMarshaller::marshallElementType(XMLObject* xmlObject, DOMElement* domElement) const\r
+void AbstractXMLObjectMarshaller::marshallElementType(XMLObject& xmlObject, DOMElement* domElement) const\r
 {\r
-    const QName* type = xmlObject->getSchemaType();\r
+    const QName* type = xmlObject.getSchemaType();\r
     if (type) {\r
         XT_log.debug("setting xsi:type attribute for XMLObject");\r
         \r
@@ -213,7 +213,7 @@ void AbstractXMLObjectMarshaller::marshallElementType(XMLObject* xmlObject, DOME
             XMLString::release(&xsivalue);\r
 \r
         XT_log.debug("Adding XSI namespace to list of namespaces used by XMLObject");\r
-        xmlObject->addNamespace(Namespace(XMLConstants::XSI_NS, XMLConstants::XSI_PREFIX));\r
+        xmlObject.addNamespace(Namespace(XMLConstants::XSI_NS, XMLConstants::XSI_PREFIX));\r
     }\r
 }\r
 \r
@@ -243,10 +243,10 @@ public:
     }\r
 };\r
 \r
-void AbstractXMLObjectMarshaller::marshallNamespaces(const XMLObject* xmlObject, DOMElement* domElement) const\r
+void AbstractXMLObjectMarshaller::marshallNamespaces(const XMLObject& xmlObject, DOMElement* domElement) const\r
 {\r
     XT_log.debug("marshalling namespace attributes for XMLObject");\r
-    const set<Namespace>& namespaces = xmlObject->getNamespaces();\r
+    const set<Namespace>& namespaces = xmlObject.getNamespaces();\r
     for_each(namespaces.begin(),namespaces.end(),bind1st(_addns(),domElement));\r
 }\r
 \r
@@ -271,12 +271,12 @@ public:
     }\r
 };\r
 \r
-void AbstractXMLObjectMarshaller::marshallChildElements(const XMLObject* xmlObject, DOMElement* domElement) const\r
+void AbstractXMLObjectMarshaller::marshallChildElements(const XMLObject& xmlObject, DOMElement* domElement) const\r
 {\r
     XT_log.debug("marshalling child elements for XMLObject");\r
 \r
     vector<XMLObject*> children;\r
-    if (xmlObject->getOrderedChildren(children)) {\r
+    if (xmlObject.getOrderedChildren(children)) {\r
         for_each(children.begin(),children.end(),bind2nd(_marshallchild(m_log),domElement));\r
     }\r
 }\r
index e93a4b3..2fd6511 100644 (file)
@@ -80,7 +80,7 @@ namespace xmltooling {
          * @param targetElement the Element into which the XMLObject is marshalled into\r
          * @throws MarshallingException thrown if there is a problem marshalling the object\r
          */\r
-        void marshallInto(XMLObject* xmlObject, DOMElement* targetElement) const;\r
+        void marshallInto(XMLObject& xmlObject, DOMElement* targetElement) const;\r
     \r
         /**\r
          * Creates an xsi:type attribute, corresponding to the given type of the XMLObject, on the DOM element.\r
@@ -91,7 +91,7 @@ namespace xmltooling {
          * @throws MarshallingException thrown if the type on the XMLObject is doesn't contain\r
          * a local name, prefix, and namespace URI\r
          */\r
-        void marshallElementType(XMLObject* xmlObject, DOMElement* domElement) const;\r
+        void marshallElementType(XMLObject& xmlObject, DOMElement* domElement) const;\r
 \r
         /**\r
          * Creates the xmlns attributes for any namespaces set on the given XMLObject.\r
@@ -99,7 +99,7 @@ namespace xmltooling {
          * @param xmlObject the XMLObject\r
          * @param domElement the DOM element the namespaces will be added to\r
          */\r
-        void marshallNamespaces(const XMLObject* xmlObject, DOMElement* domElement) const;\r
+        void marshallNamespaces(const XMLObject& xmlObject, DOMElement* domElement) const;\r
     \r
         /**\r
          * Marshalls the child elements of the given XMLObject.\r
@@ -109,7 +109,7 @@ namespace xmltooling {
          * \r
          * @throws MarshallingException thrown if there is a problem marshalling a child element\r
          */\r
-        void marshallChildElements(const XMLObject* xmlObject, DOMElement* domElement) const;\r
+        void marshallChildElements(const XMLObject& xmlObject, DOMElement* domElement) const;\r
 \r
         /**\r
          * Marshalls the attributes from the given XMLObject into the given DOM element.\r
@@ -121,7 +121,7 @@ namespace xmltooling {
          * \r
          * @throws UnmarshallingException thrown if there is a problem unmarshalling an attribute\r
          */\r
-        virtual void marshallAttributes(const XMLObject* xmlObject, DOMElement* domElement) const=0;\r
+        virtual void marshallAttributes(const XMLObject& xmlObject, DOMElement* domElement) const=0;\r
 \r
         /**\r
          * Marshalls data from the XMLObject into content of the DOM Element.\r
@@ -129,7 +129,7 @@ namespace xmltooling {
          * @param xmlObject the XMLObject\r
          * @param domElement the DOM element recieving the content\r
          */\r
-        virtual void marshallElementContent(const XMLObject* xmlObject, DOMElement* domElement) const=0;\r
+        virtual void marshallElementContent(const XMLObject& xmlObject, DOMElement* domElement) const=0;\r
 \r
         void* m_log;\r
     private:\r
index 18b09cd..ad168d1 100644 (file)
@@ -59,14 +59,14 @@ XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool b
     XMLObject* xmlObject = buildXMLObject(element);\r
 \r
     if (element->hasAttributes()) {\r
-        unmarshallAttributes(element, xmlObject);\r
+        unmarshallAttributes(element, *xmlObject);\r
     }\r
 \r
     if (element->getTextContent()) {\r
-        processElementContent(xmlObject, element->getTextContent());\r
+        processElementContent(*xmlObject, element->getTextContent());\r
     }\r
 \r
-    unmarshallChildElements(element, xmlObject);\r
+    unmarshallChildElements(element, *xmlObject);\r
 \r
     /* TODO: Signing\r
     if (xmlObject instanceof SignableXMLObject) {\r
@@ -89,7 +89,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
@@ -123,18 +123,18 @@ void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domEl
         const XMLCh* nsuri=attribute->getNamespaceURI();\r
         if (XMLString::equals(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(), true));\r
+            xmlObject.addNamespace(Namespace(attribute->getValue(), attribute->getLocalName(), true));\r
             continue;\r
         }\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
+            xmlObject.addNamespace(Namespace(nsuri, attribute->getPrefix()));\r
         }\r
 \r
         XT_log.debug("processing generic attribute");\r
@@ -142,7 +142,7 @@ void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domEl
     }\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
index 56189c1..acab0d2 100644 (file)
@@ -77,7 +77,7 @@ namespace xmltooling {
          * \r
          * @throws UnmarshallingException thrown if there is a problem unmarshalling an attribute\r
          */\r
-        virtual void unmarshallAttributes(const DOMElement* domElement, XMLObject* xmlObject) const;\r
+        virtual void unmarshallAttributes(const DOMElement* domElement, XMLObject& xmlObject) const;\r
 \r
         /**\r
          * Unmarshalls a given Element's children. For each child an unmarshaller is retrieved using\r
@@ -89,17 +89,17 @@ namespace xmltooling {
          * \r
          * @throws UnmarshallingException thrown if an error occurs unmarshalling the child elements\r
          */\r
-        virtual void unmarshallChildElements(const DOMElement* domElement, XMLObject* xmlObject) const;\r
+        virtual void unmarshallChildElements(const DOMElement* domElement, XMLObject& xmlObject) const;\r
 \r
         /**\r
          * Called after a child element has been unmarshalled so that it can be added to the parent XMLObject.\r
          * \r
          * @param parent the parent XMLObject\r
-         * @param child the child XMLObject\r
+         * @param child pointer to the child XMLObject\r
          * \r
          * @throws UnmarshallingException thrown if there is a problem adding the child to the parent\r
          */\r
-        virtual void processChildElement(XMLObject* parent, XMLObject* child) const=0;\r
+        virtual void processChildElement(XMLObject& parent, XMLObject* child) const=0;\r
     \r
         /**\r
          * Called after an attribute has been unmarshalled so that it can be added to the XMLObject.\r
@@ -109,7 +109,7 @@ namespace xmltooling {
          * \r
          * @throws UnmarshallingException thrown if there is a problem adding the attribute to the XMLObject\r
          */\r
-        virtual void processAttribute(XMLObject* xmlObject, const DOMAttr* attribute) const=0;\r
+        virtual void processAttribute(XMLObject& xmlObject, const DOMAttr* attribute) const=0;\r
     \r
         /**\r
          * Called if the element being unmarshalled contained textual content so that it can be added to the XMLObject.\r
@@ -117,7 +117,7 @@ namespace xmltooling {
          * @param xmlObject XMLObject the content will be given to\r
          * @param elementContent the Element's text content\r
          */\r
-        virtual void processElementContent(XMLObject* xmlObject, const XMLCh* elementContent) const=0;\r
+        virtual void processElementContent(XMLObject& xmlObject, const XMLCh* elementContent) const=0;\r
 \r
         void* m_log;\r
     private:\r
index 41acae8..4c3aef4 100644 (file)
@@ -43,7 +43,7 @@ const Unmarshaller* Unmarshaller::getUnmarshaller(const DOMElement* domElement)
     Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Unmarshaller");\r
  \r
     auto_ptr<QName> schemaType(XMLHelper::getXSIType(domElement));\r
-    const Unmarshaller* m = getUnmarshaller(*(schemaType.get()));\r
+    const Unmarshaller* m = schemaType.get() ? getUnmarshaller(*(schemaType.get())) : NULL;\r
     if (m) {\r
         if (log.isDebugEnabled()) {\r
             log.debug("located Unmarshaller for schema type: %s", schemaType->toString().c_str());\r
index 46196e5..31dbec9 100644 (file)
@@ -17,8 +17,6 @@
 #include "XMLObjectBaseTestCase.h"\r
 \r
 #include <fstream>\r
-#include <xmltooling/io/Marshaller.h>\r
-#include <xmltooling/io/Unmarshaller.h>\r
 \r
 \r
 class UnknownTest : public CxxTest::TestSuite {\r
diff --git a/xmltoolingtest/UnmarshallingTest.h b/xmltoolingtest/UnmarshallingTest.h
new file mode 100644 (file)
index 0000000..efe505f
--- /dev/null
@@ -0,0 +1,75 @@
+/*\r
+ *  Copyright 2001-2005 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "XMLObjectBaseTestCase.h"\r
+\r
+#include <fstream>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+\r
+const XMLCh SimpleXMLObject::NAMESPACE[] = {\r
+    chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash,\r
+    chLatin_w, chLatin_w, chLatin_w, chPeriod,\r
+    chLatin_e, chLatin_x, chLatin_a, chLatin_m, chLatin_p, chLatin_l, chLatin_e, chPeriod,\r
+    chLatin_o, chLatin_r, chLatin_g, chForwardSlash,\r
+    chLatin_t, chLatin_e, chLatin_s, chLatin_t,\r
+    chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_s, chNull\r
+};\r
+\r
+const XMLCh SimpleXMLObject::NAMESPACE_PREFIX[] = {\r
+    chLatin_t, chLatin_e, chLatin_s, chLatin_t, chNull\r
+};\r
+\r
+const XMLCh SimpleXMLObject::LOCAL_NAME[] = {\r
+    chLatin_S, chLatin_i, chLatin_m, chLatin_p, chLatin_l, chLatin_e,\r
+    chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull\r
+};\r
+\r
+const XMLCh SimpleXMLObject::ID_ATTRIB_NAME[] = {\r
+    chLatin_I, chLatin_d, chNull\r
+};\r
+\r
+class UnmarshallingTest : public CxxTest::TestSuite {\r
+    QName m_qname;\r
+public:\r
+    UnmarshallingTest() : m_qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME) {}\r
+\r
+    void setUp() {
+        XMLObjectBuilder::registerBuilder(m_qname, new SimpleXMLObjectBuilder());
+        Marshaller::registerMarshaller(m_qname, new SimpleXMLObjectMarshaller());
+        Unmarshaller::registerUnmarshaller(m_qname, new SimpleXMLObjectUnmarshaller());
+    }
+
+    void tearDown() {
+        XMLObjectBuilder::deregisterBuilder(m_qname);
+        Marshaller::deregisterMarshaller(m_qname);
+        Unmarshaller::deregisterUnmarshaller(m_qname);
+    }
+\r
+    void testUnmarshallingWithAttributes() {\r
+        ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithAttribute.xml");\r
+        DOMDocument* doc=nonvalidatingPool->parse(fs);\r
+        TS_ASSERT(doc!=NULL);\r
+\r
+        const Unmarshaller* u = Unmarshaller::getUnmarshaller(doc->getDocumentElement());\r
+        TS_ASSERT(u!=NULL);\r
+\r
+        auto_ptr<SimpleXMLObject> sxObject(dynamic_cast<SimpleXMLObject*>(u->unmarshall(doc->getDocumentElement(),true)));\r
+        TS_ASSERT(sxObject.get()!=NULL);\r
+\r
+        auto_ptr_XMLCh expectedId("Firefly");\r
+        TSM_ASSERT_SAME_DATA("ID was not expected value", expectedId.get(), sxObject->getId(), XMLString::stringLen(expectedId.get()));\r
+    }\r
+};\r
index 99e878a..d0fb2d0 100644 (file)
  */\r
 \r
 #include <cxxtest/TestSuite.h>\r
+#include <xmltooling/AbstractDOMCachingXMLObject.h>\r
+#include <xmltooling/exceptions.h>\r
+#include <xmltooling/XMLObjectBuilder.h>\r
 #include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/io/AbstractXMLObjectMarshaller.h>\r
+#include <xmltooling/io/AbstractXMLObjectUnmarshaller.h>\r
 #include <xmltooling/util/ParserPool.h>\r
 #include <xmltooling/util/XMLHelper.h>\r
 \r
@@ -25,3 +30,124 @@ using namespace std;
 extern ParserPool* validatingPool;\r
 extern ParserPool* nonvalidatingPool;\r
 \r
+#if defined (_MSC_VER)\r
+    #pragma warning( push )\r
+    #pragma warning( disable : 4250 4251 )\r
+#endif\r
+\r
+class SimpleXMLObjectUnmarshaller;\r
+\r
+class SimpleXMLObject : public AbstractDOMCachingXMLObject\r
+{\r
+public:\r
+    static const XMLCh NAMESPACE[];\r
+    static const XMLCh NAMESPACE_PREFIX[];\r
+    static const XMLCh LOCAL_NAME[];\r
+    static const XMLCh ID_ATTRIB_NAME[];\r
+    \r
+    SimpleXMLObject() : AbstractDOMCachingXMLObject(NAMESPACE, LOCAL_NAME, NAMESPACE_PREFIX), m_id(NULL), m_value(NULL) {}\r
+    virtual ~SimpleXMLObject() {\r
+        XMLString::release(&m_id);\r
+        XMLString::release(&m_value);\r
+        for_each(m_children.begin(), m_children.end(), cleanup<SimpleXMLObject>());\r
+    }\r
+    \r
+    const XMLCh* getId() const { return m_id; }\r
+    void setId(const XMLCh* id) { m_id=prepareForAssignment(m_id,id); }\r
+\r
+    const XMLCh* getValue() const { return m_value; }\r
+    void setValue(const XMLCh* value) { m_value=prepareForAssignment(m_value,value); }\r
+    \r
+    const list<SimpleXMLObject*>& getSimpleXMLObjects() const { return m_children; }\r
+    \r
+    bool hasChildren() const { return !m_children.empty(); }\r
+    size_t getOrderedChildren(vector<XMLObject*>& children) const {\r
+        children.assign(m_children.begin(),m_children.end());\r
+        return children.size();\r
+    }\r
+    SimpleXMLObject* clone() const {\r
+        SimpleXMLObject* ret=new SimpleXMLObject();\r
+        ret->setId(m_id);\r
+        ret->setValue(m_value);\r
+        xmltooling::clone(m_children, ret->m_children);\r
+        return ret;\r
+    }\r
+\r
+private:\r
+    XMLCh* m_id;\r
+    XMLCh* m_value;\r
+    list<SimpleXMLObject*> m_children;\r
+    \r
+    friend class SimpleXMLObjectUnmarshaller;\r
+};\r
+\r
+class SimpleXMLObjectBuilder : public XMLObjectBuilder\r
+{\r
+public:\r
+    XMLObject* buildObject() const {\r
+        return new SimpleXMLObject();\r
+    }\r
+};\r
+\r
+class SimpleXMLObjectMarshaller : public AbstractXMLObjectMarshaller\r
+{\r
+public:\r
+    SimpleXMLObjectMarshaller() : AbstractXMLObjectMarshaller(SimpleXMLObject::NAMESPACE, SimpleXMLObject::LOCAL_NAME) {}\r
+\r
+private:\r
+    void marshallAttributes(const XMLObject& xmlObject, DOMElement* domElement) const {\r
+        const SimpleXMLObject& simpleXMLObject = dynamic_cast<const SimpleXMLObject&>(xmlObject);\r
+        \r
+        if(simpleXMLObject.getId()) {\r
+            domElement->setAttributeNS(NULL, SimpleXMLObject::ID_ATTRIB_NAME, simpleXMLObject.getId());\r
+            domElement->setIdAttributeNS(NULL, SimpleXMLObject::ID_ATTRIB_NAME);\r
+        }\r
+    }\r
+\r
+    void marshallElementContent(const XMLObject& xmlObject, DOMElement* domElement) const {\r
+        const SimpleXMLObject& simpleXMLObject = dynamic_cast<const SimpleXMLObject&>(xmlObject);\r
+\r
+        if(simpleXMLObject.getValue()) {\r
+            domElement->setTextContent(simpleXMLObject.getValue());\r
+        }\r
+    }\r
+};\r
+\r
+class SimpleXMLObjectUnmarshaller : public AbstractXMLObjectUnmarshaller\r
+{\r
+public:\r
+    SimpleXMLObjectUnmarshaller() : AbstractXMLObjectUnmarshaller(SimpleXMLObject::NAMESPACE, SimpleXMLObject::LOCAL_NAME) {}\r
+\r
+private:\r
+    void processChildElement(XMLObject& parentXMLObject, XMLObject* childXMLObject) const {\r
+        SimpleXMLObject& simpleXMLObject = dynamic_cast<SimpleXMLObject&>(parentXMLObject);\r
+\r
+        SimpleXMLObject* child = dynamic_cast<SimpleXMLObject*>(childXMLObject);\r
+        if (child) {\r
+            simpleXMLObject.m_children.push_back(child);\r
+        }\r
+        else {\r
+            throw UnmarshallingException("Unknown child element cannot be added to parent object.");\r
+        }\r
+    }\r
+\r
+    void processAttribute(XMLObject& xmlObject, const DOMAttr* attribute) const {\r
+        SimpleXMLObject& simpleXMLObject = dynamic_cast<SimpleXMLObject&>(xmlObject);\r
+\r
+        if (XMLString::equals(attribute->getLocalName(),SimpleXMLObject::ID_ATTRIB_NAME)) {\r
+            simpleXMLObject.setId(attribute->getValue());\r
+        }\r
+    }\r
+\r
+    void processElementContent(XMLObject& xmlObject, const XMLCh* elementContent) const {\r
+        SimpleXMLObject& simpleXMLObject = dynamic_cast<SimpleXMLObject&>(xmlObject);\r
+        \r
+        simpleXMLObject.setValue(elementContent);\r
+    }\r
+\r
+};\r
+\r
+\r
+#if defined (_MSC_VER)\r
+    #pragma warning( pop )\r
+#endif\r
diff --git a/xmltoolingtest/data/SimpleXMLObjectWithAttribute.xml b/xmltoolingtest/data/SimpleXMLObjectWithAttribute.xml
new file mode 100644 (file)
index 0000000..0b75784
Binary files /dev/null and b/xmltoolingtest/data/SimpleXMLObjectWithAttribute.xml differ
diff --git a/xmltoolingtest/data/SimpleXMLObjectWithContent.xml b/xmltoolingtest/data/SimpleXMLObjectWithContent.xml
new file mode 100644 (file)
index 0000000..d6df345
Binary files /dev/null and b/xmltoolingtest/data/SimpleXMLObjectWithContent.xml differ
index a19b4f1..1da845b 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\UnmarshallingTest.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\xmltoolingtest.cpp"\r
                                >\r
                        </File>\r
                                </FileConfiguration>\r
                        </File>\r
                        <File\r
+                               RelativePath=".\UnmarshallingTest.h"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCustomBuildTool"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               Outputs="&quot;$(InputName)&quot;.cpp"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCustomBuildTool"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               Outputs="&quot;$(InputName)&quot;.cpp"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\xmltoolingtest.h"\r
                                >\r
                                <FileConfiguration\r