Initial unit test plus fixes
authorScott Cantor <cantor.2@osu.edu>
Wed, 1 Mar 2006 21:18:40 +0000 (21:18 +0000)
committerScott Cantor <cantor.2@osu.edu>
Wed, 1 Mar 2006 21:18:40 +0000 (21:18 +0000)
26 files changed:
.cdtproject
.gitignore
cpp-xmltooling.sln
xmltooling/AbstractDOMCachingXMLObject.cpp
xmltooling/AbstractDOMCachingXMLObject.h
xmltooling/AbstractXMLObject.h
xmltooling/Namespace.cpp
xmltooling/Namespace.h
xmltooling/QName.cpp
xmltooling/QName.h
xmltooling/XMLObjectBuilder.cpp
xmltooling/impl/UnknownElement.cpp
xmltooling/impl/UnknownElement.h
xmltooling/io/AbstractXMLObjectMarshaller.cpp
xmltooling/io/AbstractXMLObjectUnmarshaller.cpp
xmltooling/io/Marshaller.cpp
xmltooling/io/Unmarshaller.cpp
xmltooling/util/XMLHelper.cpp
xmltooling/util/XMLHelper.h
xmltoolingtest/.gitignore [new file with mode: 0644]
xmltoolingtest/UnknownTest.h [new file with mode: 0644]
xmltoolingtest/XMLObjectBaseTestCase.h [new file with mode: 0644]
xmltoolingtest/data/SimpleXMLObjectWithChildren.xml [new file with mode: 0644]
xmltoolingtest/data/catalog.xml [new file with mode: 0644]
xmltoolingtest/xmltoolingtest.h [new file with mode: 0644]
xmltoolingtest/xmltoolingtest.vcproj [new file with mode: 0644]

index 74757f5..ddee21c 100644 (file)
 <item id="org.eclipse.cdt.core.pathentry">\r
 <pathentry include="C:/log4cpp-0.3.5rc1/include" kind="inc" path="" system="true"/>\r
 <pathentry include="C:/xerces-c2_7_0-win32/include" kind="inc" path="" system="true"/>\r
+<pathentry include="C:/xml-security-c-1.2.0/include" kind="inc" path="" system="true"/>\r
+<pathentry include="C:/cxxtest" kind="inc" path="" system="true"/>\r
 <pathentry base-path="XMLTooling-C" include="" kind="inc" path="" system="true"/>\r
 <pathentry base-path="XMLTooling-C" include="xmltooling" kind="inc" path="" system="true"/>\r
 <pathentry kind="mac" name="_MSC_VER" path="" value=""/>\r
-<pathentry kind="src" path=""/>\r
+<pathentry kind="mac" name="WIN32" path="" value=""/>\r
 <pathentry kind="out" path=""/>\r
 <pathentry kind="con" path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>\r
+<pathentry excluding="util/|io/|impl/" kind="src" path="xmltooling"/>\r
+<pathentry kind="src" path="xmltooling/util"/>\r
+<pathentry kind="src" path="xmltooling/io"/>\r
+<pathentry kind="src" path="xmltooling/impl"/>\r
+<pathentry kind="src" path="xmltoolingtest"/>\r
 </item>\r
 </data>\r
 </cdtproject>\r
index 7dc697f..f0b5094 100644 (file)
@@ -17,3 +17,6 @@
 # Simulated Subversion default ignores end here
 # The contents of the svn:ignore property on the branch root.
 /debug
+/*.ncb
+/*.suo
+/release
index 9ff2d25..dabb78b 100644 (file)
@@ -3,6 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 9.00
 # Visual Studio 2005\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmltooling", "xmltooling\xmltooling.vcproj", "{06B55A46-D3B3-41AE-B5A5-B57830BA010D}"\r
 EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmltoolingtest", "xmltoolingtest\xmltoolingtest.vcproj", "{3E34CDCC-FCBA-490D-A165-1CB6F4559799}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {06B55A46-D3B3-41AE-B5A5-B57830BA010D} = {06B55A46-D3B3-41AE-B5A5-B57830BA010D}\r
+       EndProjectSection\r
+EndProject\r
 Global\r
        GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
                Debug|Win32 = Debug|Win32\r
@@ -13,6 +18,10 @@ Global
                {06B55A46-D3B3-41AE-B5A5-B57830BA010D}.Debug|Win32.Build.0 = Debug|Win32\r
                {06B55A46-D3B3-41AE-B5A5-B57830BA010D}.Release|Win32.ActiveCfg = Release|Win32\r
                {06B55A46-D3B3-41AE-B5A5-B57830BA010D}.Release|Win32.Build.0 = Release|Win32\r
+               {3E34CDCC-FCBA-490D-A165-1CB6F4559799}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {3E34CDCC-FCBA-490D-A165-1CB6F4559799}.Debug|Win32.Build.0 = Debug|Win32\r
+               {3E34CDCC-FCBA-490D-A165-1CB6F4559799}.Release|Win32.ActiveCfg = Release|Win32\r
+               {3E34CDCC-FCBA-490D-A165-1CB6F4559799}.Release|Win32.Build.0 = Release|Win32\r
        EndGlobalSection\r
        GlobalSection(SolutionProperties) = preSolution\r
                HideSolutionNode = FALSE\r
index 8a23062..86f8bf7 100644 (file)
@@ -57,23 +57,21 @@ void AbstractDOMCachingXMLObject::setDOM(DOMElement* dom, bool bindDocument)
 void AbstractDOMCachingXMLObject::releaseDOM()\r
 {\r
     Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM");\r
-    if (log.isDebugEnabled())\r
-        log.debug("releasing cached DOM reprsentation for %s", getElementQName().toString().c_str());\r
+    if (log.isDebugEnabled()) {\r
+        string qname=getElementQName().toString();\r
+        log.debug("releasing cached DOM representation for (%s)", qname.empty() ? "unknown" : qname.c_str());\r
+    }\r
     setDOM(NULL);\r
 }\r
 \r
 void AbstractDOMCachingXMLObject::releaseParentDOM(bool propagateRelease)\r
 {\r
-    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM");\r
-    if (log.isDebugEnabled()) {\r
-        log.debug(\r
-            "releasing cached DOM representation for parent of %s with propagation set to %s",\r
-            getElementQName().toString().c_str(), propagateRelease ? "true" : "false"\r
-            );\r
-    }\r
-\r
     DOMCachingXMLObject* domCachingParent = dynamic_cast<DOMCachingXMLObject*>(getParent());\r
     if (domCachingParent) {\r
+        Category::getInstance(XMLTOOLING_LOGCAT".DOM").debug(\r
+            "releasing cached DOM representation for parent object with propagation set to %s",\r
+            propagateRelease ? "true" : "false"\r
+            );\r
         domCachingParent->releaseDOM();\r
         if (propagateRelease)\r
             domCachingParent->releaseParentDOM(propagateRelease);\r
@@ -94,23 +92,20 @@ public:
 \r
 void AbstractDOMCachingXMLObject::releaseChildrenDOM(bool propagateRelease)\r
 {\r
-    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM");\r
-    if (log.isDebugEnabled()) {\r
-        log.debug(\r
-            "releasing cached DOM representation for children of %s with propagation set to %s",\r
-            getElementQName().toString().c_str(), propagateRelease ? "true" : "false"\r
-            );\r
-    }\r
-    \r
     vector<XMLObject*> children;\r
-    if (getOrderedChildren(children))\r
+    if (getOrderedChildren(children)) {\r
+        Category::getInstance(XMLTOOLING_LOGCAT".DOM").debug(\r
+            "releasing cached DOM representation for children with propagation set to %s",\r
+            propagateRelease ? "true" : "false"\r
+            );\r
         for_each(children.begin(),children.end(),bind2nd(_release(),propagateRelease));\r
+    }\r
 }\r
 \r
 XMLObject* AbstractDOMCachingXMLObject::prepareForAssignment(const XMLObject* oldValue, XMLObject* newValue) {\r
 \r
     if (newValue && newValue->hasParent())\r
-        throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject");\r
+        throw XMLObjectException("Child XMLObject cannot be added - it is already the child of another XMLObject");\r
 \r
     if (!oldValue) {\r
         if (newValue) {\r
index 8093fe8..dba39e7 100644 (file)
@@ -140,8 +140,8 @@ namespace xmltooling {
          * @param namespaceURI the namespace the element is in\r
          * @param elementLocalName the local name of the XML element this Object represents\r
          */\r
-        AbstractDOMCachingXMLObject(const XMLCh* namespaceURI, const XMLCh* elementLocalName)\r
-            : AbstractXMLObject(namespaceURI,elementLocalName), m_dom(NULL), m_document(NULL) {}\r
+        AbstractDOMCachingXMLObject(const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix)\r
+            : AbstractXMLObject(namespaceURI,elementLocalName, namespacePrefix), m_dom(NULL), m_document(NULL) {}\r
 \r
     private:\r
         DOMElement* m_dom;\r
index a3b5a70..12d8408 100644 (file)
@@ -67,7 +67,9 @@ namespace xmltooling {
          * @see XMLObject::addNamespace()\r
          */\r
         void addNamespace(const Namespace& ns) {\r
-            m_namespaces.insert(ns);\r
+            if (ns.alwaysDeclare() || m_namespaces.find(ns)==m_namespaces.end()) {\r
+                m_namespaces.insert(ns);\r
+            }\r
         }\r
     \r
         /**\r
@@ -126,8 +128,10 @@ namespace xmltooling {
          * @param namespaceURI the namespace the element is in\r
          * @param elementLocalName the local name of the XML element this Object represents\r
          */\r
-        AbstractXMLObject(const XMLCh* namespaceURI, const XMLCh* elementLocalName)\r
-            : m_elementQname(namespaceURI,elementLocalName), m_typeQname(NULL), m_parent(NULL) {}\r
+        AbstractXMLObject(const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix)\r
+            : m_elementQname(namespaceURI,elementLocalName, namespacePrefix), m_typeQname(NULL), m_parent(NULL) {\r
+            addNamespace(Namespace(namespaceURI, namespacePrefix));\r
+        }\r
         \r
     private:\r
         XMLObject* m_parent;\r
index c4bcca7..21bf4b2 100644 (file)
@@ -25,7 +25,7 @@
 \r
 using namespace xmltooling;\r
 \r
-Namespace::Namespace(const XMLCh* uri, const XMLCh* prefix)\r
+Namespace::Namespace(const XMLCh* uri, const XMLCh* prefix, bool alwaysDeclare) : m_pinned(alwaysDeclare)\r
 {\r
 #ifndef HAVE_GOOD_STL\r
     m_uri=m_prefix=NULL;\r
@@ -75,19 +75,21 @@ Namespace::Namespace(const Namespace& src)
 {\r
     m_uri=XMLString::replicate(src.getNamespaceURI());\r
     m_prefix=XMLString::replicate(src.getNamespacePrefix());\r
+    m_pinned=src.getAlwaysDeclare();\r
 }\r
 \r
 Namespace& Namespace::operator=(const Namespace& src)\r
 {\r
     m_uri=XMLString::replicate(src.getNamespaceURI());\r
     m_prefix=XMLString::replicate(src.getNamespacePrefix());\r
+    m_pinned=src.getAlwaysDeclare();\r
     return *this;\r
 }\r
 \r
 bool xmltooling::operator==(const Namespace& op1, const Namespace& op2)\r
 {\r
-    return (!XMLString::compareString(op1.getNamespaceURI(),op2.getNamespaceURI()) &&\r
-            !XMLString::compareString(op1.getNamespacePrefix(),op2.getNamespacePrefix()));\r
+    return (XMLString::equals(op1.getNamespaceURI(),op2.getNamespaceURI()) &&\r
+            XMLString::equals(op1.getNamespacePrefix(),op2.getNamespacePrefix()));\r
 }\r
 #endif\r
 \r
index 984df21..3e9bfc8 100644 (file)
@@ -35,10 +35,11 @@ namespace xmltooling {
     public:\r
         /**\r
          * Constructor\r
-         * @param uri       namespace URI\r
-         * @param prefix    namespace prefix (without the colon)\r
+         * @param uri               namespace URI\r
+         * @param prefix            namespace prefix (without the colon)\r
+         * @param alwaysDeclare     true iff the namespace should always be declared regardless of in-scope declarations\r
          */\r
-        Namespace(const XMLCh* uri=NULL, const XMLCh* prefix=NULL);\r
+        Namespace(const XMLCh* uri=NULL, const XMLCh* prefix=NULL, bool alwaysDeclare=false);\r
         \r
         ~Namespace();\r
 #ifndef HAVE_GOOD_STL\r
@@ -80,6 +81,12 @@ namespace xmltooling {
 #endif\r
 \r
         /**\r
+         * Returns true iff the namespace should always be declared regardless of in-scope declarations\r
+         * @return the alwaysDeclared setting\r
+         */\r
+        const bool alwaysDeclare() const { return m_pinned; } \r
+\r
+        /**\r
          * Sets the namespace prefix\r
          * @param prefix    Null-terminated Unicode string containing the prefix, without the colon\r
          */\r
@@ -90,8 +97,15 @@ namespace xmltooling {
          * @param uri  Null-terminated Unicode string containing the URI\r
          */\r
         void setNamespaceURI(const XMLCh* uri);\r
+\r
+        /**\r
+         * Sets the alwaysDeclared property\r
+         * @param alwaysDeclare     true iff the namespace should always be declared regardless of in-scope declarations\r
+         */\r
+        void setAlwaysDeclare(bool alwaysDeclare) { m_pinned = alwaysDeclare; } \r
         \r
     private:\r
+        bool m_pinned;\r
 #ifdef HAVE_GOOD_STL\r
         xstring m_uri;\r
         xstring m_prefix;\r
index b47588e..2c95801 100644 (file)
@@ -123,14 +123,14 @@ bool xmltooling::operator<(const QName& op1, const QName& op2)
 \r
 string QName::toString() const\r
 {\r
-    if (!getLocalPart())\r
+    if (!hasLocalPart())\r
         return "";\r
     auto_ptr_char local(getLocalPart());\r
-    if (getPrefix()) {\r
+    if (hasPrefix()) {\r
         auto_ptr_char pre(getPrefix());\r
         return string(pre.get()) + ':' + local.get(); \r
     }\r
-    else if (getNamespaceURI()) {\r
+    else if (hasNamespaceURI()) {\r
         auto_ptr_char ns(getNamespaceURI());\r
         return string("{") + ns.get() + '}' + local.get(); \r
     }\r
index 4df23ba..779ce70 100644 (file)
@@ -58,6 +58,24 @@ namespace xmltooling {
         \r
 #ifdef HAVE_GOOD_STL\r
         /**\r
+         * Indicates whether the QName has a prefix.\r
+         * @return  true iff the prefix is non-empty\r
+         */\r
+        bool hasPrefix() const { return !m_prefix.empty(); }\r
+\r
+        /**\r
+         * Indicates whether the QName has a non-empty namespace.\r
+         * @return  true iff the namespace is non-empty\r
+         */\r
+        bool hasNamespaceURI() const { return !m_uri.empty(); }\r
+\r
+        /**\r
+         * Indicates whether the QName has a non-empty local name.\r
+         * @return  true iff the local name is non-empty\r
+         */\r
+        bool hasLocalPart() const { return !m_local.empty(); }\r
+\r
+        /**\r
          * Returns the namespace prefix\r
          * @return  Null-terminated Unicode string containing the prefix, without the colon\r
          */\r
@@ -76,6 +94,24 @@ namespace xmltooling {
         const XMLCh* getLocalPart() const { return m_local.c_str(); }\r
 #else\r
         /**\r
+         * Indicates whether the QName has a prefix.\r
+         * @return  true iff the prefix is non-empty\r
+         */\r
+        bool hasPrefix() const { return m_prefix && *m_prefix; }\r
+\r
+        /**\r
+         * Indicates whether the QName has a non-empty namespace.\r
+         * @return  true iff the namespace is non-empty\r
+         */\r
+        bool hasNamespaceURI() const { return m_uri && *m_uri; }\r
+\r
+        /**\r
+         * Indicates whether the QName has a non-empty local name.\r
+         * @return  true iff the local name is non-empty\r
+         */\r
+        bool hasLocalPart() const { return m_local && *m_local; }\r
+\r
+        /**\r
          * Returns the namespace prefix\r
          * @return  Null-terminated Unicode string containing the prefix, without the colon\r
          */\r
index 03b9c27..24d434d 100644 (file)
@@ -59,7 +59,9 @@ const XMLObjectBuilder* XMLObjectBuilder::getBuilder(const DOMElement* domElemen
         return xmlObjectBuilder;\r
     }\r
 \r
-    log.error("no XMLObjectBuilder registered for element (%s), using default", elementName->toString().c_str());\r
+    if (log.isDebugEnabled()) {\r
+        log.debug("no XMLObjectBuilder registered for element (%s), returning default", elementName->toString().c_str());\r
+    }\r
     return m_default;\r
 }\r
 \r
index 9af4b26..745abe9 100644 (file)
@@ -24,9 +24,9 @@
 #include "exceptions.h"\r
 #include "impl/UnknownElement.h"\r
 #include "util/NDC.h"\r
+#include "util/XMLHelper.h"\r
 \r
 #include <log4cpp/Category.hh>\r
-#include <xercesc/framework/MemBufFormatTarget.hpp>\r
 #include <xercesc/framework/MemBufInputSource.hpp>\r
 #include <xercesc/framework/Wrapper4InputSource.hpp>\r
 #include <xercesc/util/XMLUniDefs.hpp>\r
@@ -66,25 +66,8 @@ XMLObject* UnknownElementImpl::clone() const
 \r
 void UnknownElementImpl::serialize(string& s) const\r
 {\r
-    if (getDOM()) {\r
-        static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull };\r
-        static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDigit_8, chNull };\r
-        DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype);\r
-        DOMWriter* serializer=(static_cast<DOMImplementationLS*>(impl))->createDOMWriter();\r
-        serializer->setEncoding(UTF8);\r
-        try {\r
-            MemBufFormatTarget target;\r
-            if (!serializer->writeNode(&target,*(getDOM())))\r
-                throw XMLObjectException("unable to serialize XML to preserve DOM");\r
-            s.erase();\r
-            s.append(reinterpret_cast<const char*>(target.getRawBuffer()),target.getLen());\r
-            serializer->release();\r
-        }\r
-        catch (...) {\r
-            serializer->release();\r
-            throw;\r
-        }\r
-    }\r
+    if (getDOM())\r
+        XMLHelper::serialize(getDOM(),s);\r
 }\r
 \r
 DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMDocument* document) const\r
@@ -104,7 +87,8 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMDocument
     if (cachedDOM) {\r
         if (!document || document==cachedDOM->getOwnerDocument()) {\r
             log.debug("XMLObject has a usable cached DOM, reusing it");\r
-            setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);\r
+            if (document)\r
+                setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);\r
             unk->releaseParentDOM(true);\r
             return cachedDOM;\r
         }\r
index 764e17d..787cea1 100644 (file)
@@ -47,6 +47,7 @@ namespace xmltooling {
     {\r
     public:\r
         UnknownElementImpl() {}\r
+        virtual ~UnknownElementImpl() {}\r
 \r
         /**\r
          * Overridden to ensure XML content of DOM isn't lost.\r
index c66b770..0b09c3e 100644 (file)
@@ -62,7 +62,8 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMDocum
         if (cachedDOM) {\r
             if (!document || document==cachedDOM->getOwnerDocument()) {\r
                 XT_log.debug("XMLObject has a usable cached DOM, reusing it");\r
-                setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);\r
+                if (document)\r
+                    setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);\r
                 dc->releaseParentDOM(true);\r
                 return cachedDOM;\r
             }\r
@@ -165,11 +166,11 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(XMLObject* xmlObject, DOMEleme
 void AbstractXMLObjectMarshaller::marshallInto(XMLObject* xmlObject, DOMElement* targetElement) const\r
 {\r
     targetElement->setPrefix(xmlObject->getElementQName().getPrefix());\r
+    marshallElementType(xmlObject, targetElement);\r
     marshallNamespaces(xmlObject, targetElement);\r
     marshallAttributes(xmlObject, targetElement);\r
     marshallChildElements(xmlObject, targetElement);\r
     marshallElementContent(xmlObject, targetElement);\r
-    marshallElementType(xmlObject, targetElement);\r
 \r
     /* TODO Signing/Encryption\r
     if (xmlObject instanceof SignableXMLObject) {\r
@@ -221,6 +222,12 @@ public:
     void operator()(DOMElement* domElement, const Namespace& ns) const {\r
         const XMLCh* prefix=ns.getNamespacePrefix();\r
         const XMLCh* uri=ns.getNamespaceURI();\r
+        \r
+        // Check to see if the prefix is already declared properly above this node.\r
+        if (!ns.alwaysDeclare() && domElement->getParentNode() &&\r
+                XMLString::equals(domElement->getParentNode()->lookupNamespaceURI(prefix),uri))\r
+            return;\r
+            \r
         if (prefix && *prefix) {\r
             XMLCh* xmlns=new XMLCh[XMLString::stringLen(XMLConstants::XMLNS_PREFIX) + XMLString::stringLen(prefix) + 2*sizeof(XMLCh)];\r
             *xmlns=chNull;\r
@@ -260,7 +267,7 @@ public:
                 );\r
             throw MarshallingException("Marshaller found unknown child element, but no default marshaller was found.");\r
         }\r
-        element->appendChild(marshaller->marshall(obj, element->getOwnerDocument()));\r
+        element->appendChild(marshaller->marshall(obj, element));\r
     }\r
 };\r
 \r
index e6bdf7e..18b09cd 100644 (file)
@@ -121,18 +121,21 @@ 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
+        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()));\r
+            xmlObject->addNamespace(Namespace(attribute->getValue(), attribute->getLocalName(), true));\r
             continue;\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
             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
index 5d6a82e..2ed9d16 100644 (file)
@@ -58,8 +58,10 @@ const Marshaller* Marshaller::getMarshaller(const XMLObject* xmlObject)
         }\r
         return m;\r
     }\r
-\r
-    log.error("no Marshaller registered for element (%s), returning default", xmlObject->getElementQName().toString().c_str());\r
+    if (log.isDebugEnabled()) {\r
+        string qname=xmlObject->getElementQName().toString().c_str();\r
+        log.debug("no Marshaller registered for element (%s), returning default", qname.empty() ? "unknown" : qname.c_str());\r
+    }\r
     return m_default;\r
 }\r
 \r
index d0bba16..41acae8 100644 (file)
@@ -60,7 +60,9 @@ const Unmarshaller* Unmarshaller::getUnmarshaller(const DOMElement* domElement)
         return m;\r
     }\r
 \r
-    log.error("no Unmarshaller registered for element (%s), using default", elementName->toString().c_str());\r
+    if (log.isDebugEnabled()) {\r
+        log.debug("no Unmarshaller registered for element (%s), returning default", elementName->toString().c_str());\r
+    }\r
     return m_default;\r
 }\r
 \r
index e5962d6..d4cd911 100644 (file)
  */\r
 \r
 #include "internal.h"\r
+#include "exceptions.h"\r
 #include "util/XMLHelper.h"\r
 #include "util/XMLConstants.h"\r
 \r
+#include <xercesc/framework/MemBufFormatTarget.hpp>\r
 #include <xercesc/util/XMLUniDefs.hpp>\r
 \r
 using namespace xmltooling;\r
@@ -114,3 +116,24 @@ DOMElement* XMLHelper::appendChildElement(DOMElement* parentElement, DOMElement*
     parentElement->appendChild(childElement);\r
     return childElement;\r
 }\r
+\r
+void XMLHelper::serialize(const DOMElement* e, std::string& buf)\r
+{\r
+    static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull };\r
+    static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDigit_8, chNull };\r
+    DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype);\r
+    DOMWriter* serializer=(static_cast<DOMImplementationLS*>(impl))->createDOMWriter();\r
+    serializer->setEncoding(UTF8);\r
+    try {\r
+        MemBufFormatTarget target;\r
+        if (!serializer->writeNode(&target,*e))\r
+            throw XMLParserException("unable to serialize XML");\r
+        buf.erase();\r
+        buf.append(reinterpret_cast<const char*>(target.getRawBuffer()),target.getLen());\r
+        serializer->release();\r
+    }\r
+    catch (...) {\r
+        serializer->release();\r
+        throw;\r
+    }\r
+}\r
index 9cf69b9..3642029 100644 (file)
@@ -95,8 +95,17 @@ namespace xmltooling {
          * @return  true iff the element's qualified name matches the other parameters\r
          */\r
         static bool isElementNamed(const DOMElement* e, const XMLCh* ns, const XMLCh* local) {\r
-            return (e && !XMLString::compareString(ns,e->getNamespaceURI()) && !XMLString::compareString(local,e->getLocalName()));\r
+            return (e && XMLString::equals(ns,e->getNamespaceURI()) && XMLString::equals(local,e->getLocalName()));\r
         }\r
+\r
+        /**\r
+         * Serializes the DOM Element provided into a buffer using UTF-8 encoding and\r
+         * the default XML serializer available. No manipulation or formatting is applied.\r
+         * \r
+         * @param e     element to serialize\r
+         * @param buf   buffer to serialize element into\r
+         */\r
+        static void serialize(const DOMElement* e, std::string& buf);\r
     };\r
 \r
 };\r
diff --git a/xmltoolingtest/.gitignore b/xmltoolingtest/.gitignore
new file mode 100644 (file)
index 0000000..f2fdc61
--- /dev/null
@@ -0,0 +1,4 @@
+/Debug
+/*.user
+/*.cpp
+/Release
diff --git a/xmltoolingtest/UnknownTest.h b/xmltoolingtest/UnknownTest.h
new file mode 100644 (file)
index 0000000..46196e5
--- /dev/null
@@ -0,0 +1,85 @@
+/*\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 <xmltooling/io/Marshaller.h>\r
+#include <xmltooling/io/Unmarshaller.h>\r
+\r
+\r
+class UnknownTest : public CxxTest::TestSuite {\r
+public:\r
+\r
+    void testUnknown() {\r
+        ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml");\r
+        DOMDocument* doc=nonvalidatingPool->parse(fs);\r
+        TS_ASSERT(doc!=NULL);\r
+\r
+        string buf1;\r
+        XMLHelper::serialize(doc->getDocumentElement(), buf1);\r
+\r
+        const Unmarshaller* u=Unmarshaller::getUnmarshaller(doc->getDocumentElement());\r
+        TS_ASSERT(u!=NULL);\r
+\r
+        auto_ptr<XMLObject> xmlObject(u->unmarshall(doc->getDocumentElement(),true)); // bind document\r
+        TS_ASSERT(xmlObject.get()!=NULL);\r
+\r
+        auto_ptr<XMLObject> clonedObject(xmlObject->clone());\r
+        TS_ASSERT(clonedObject.get()!=NULL);\r
+\r
+        const Marshaller* m=Marshaller::getMarshaller(clonedObject.get());\r
+        TS_ASSERT(m!=NULL);\r
+\r
+        DOMElement* rootElement=m->marshall(clonedObject.get());\r
+        TS_ASSERT(rootElement!=NULL);\r
+\r
+        rootElement=m->marshall(clonedObject.get());    // should reuse DOM\r
+        TS_ASSERT(rootElement!=NULL);\r
+\r
+        string buf2;\r
+        XMLHelper::serialize(rootElement, buf2);\r
+        TS_ASSERT_EQUALS(buf1,buf2);\r
+    }\r
+\r
+    void testUnknownWithDocChange() {\r
+        ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml");\r
+        DOMDocument* doc=nonvalidatingPool->parse(fs);\r
+        TS_ASSERT(doc!=NULL);\r
+\r
+        string buf1;\r
+        XMLHelper::serialize(doc->getDocumentElement(), buf1);\r
+\r
+        const Unmarshaller* u=Unmarshaller::getUnmarshaller(doc->getDocumentElement());\r
+        TS_ASSERT(u!=NULL);\r
+\r
+        auto_ptr<XMLObject> xmlObject(u->unmarshall(doc->getDocumentElement(),true)); // bind document\r
+        TS_ASSERT(xmlObject.get()!=NULL);\r
+\r
+        const Marshaller* m=Marshaller::getMarshaller(xmlObject.get());\r
+        TS_ASSERT(m!=NULL);\r
+\r
+        DOMDocument* newDoc=nonvalidatingPool->newDocument();\r
+        DOMElement* rootElement=m->marshall(xmlObject.get(), newDoc);\r
+        TS_ASSERT(rootElement!=NULL);\r
+\r
+        string buf2;\r
+        XMLHelper::serialize(rootElement, buf2);\r
+        TS_ASSERT_EQUALS(buf1,buf2);\r
+\r
+        newDoc->release();\r
+    }\r
+};\r
diff --git a/xmltoolingtest/XMLObjectBaseTestCase.h b/xmltoolingtest/XMLObjectBaseTestCase.h
new file mode 100644 (file)
index 0000000..99e878a
--- /dev/null
@@ -0,0 +1,27 @@
+/*\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 <cxxtest/TestSuite.h>\r
+#include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/util/ParserPool.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+extern ParserPool* validatingPool;\r
+extern ParserPool* nonvalidatingPool;\r
+\r
diff --git a/xmltoolingtest/data/SimpleXMLObjectWithChildren.xml b/xmltoolingtest/data/SimpleXMLObjectWithChildren.xml
new file mode 100644 (file)
index 0000000..ce437ed
Binary files /dev/null and b/xmltoolingtest/data/SimpleXMLObjectWithChildren.xml differ
diff --git a/xmltoolingtest/data/catalog.xml b/xmltoolingtest/data/catalog.xml
new file mode 100644 (file)
index 0000000..6094e8d
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+    <uri name="http://www.w3.org/XML/1998/namespace" uri="../schemas/xml.xsd"/>
+    <uri name="http://www.w3.org/2001/04/xmlenc#" uri="../schemas/xenc-schema.xsd"/>
+    <uri name="http://www.w3.org/2000/09/xmldsig#" uri="../schemas/xmldsig-core-schema.xsd"/>
+</catalog>
diff --git a/xmltoolingtest/xmltoolingtest.h b/xmltoolingtest/xmltoolingtest.h
new file mode 100644 (file)
index 0000000..f3fb5af
--- /dev/null
@@ -0,0 +1,67 @@
+/*\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 <cxxtest/TestSuite.h>\r
+#include <cxxtest/GlobalFixture.h>\r
+\r
+#include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/util/ParserPool.h>\r
+\r
+using namespace xmltooling;\r
+\r
+ParserPool* validatingPool=NULL;\r
+ParserPool* nonvalidatingPool=NULL;\r
+\r
+class ToolingFixture : public CxxTest::GlobalFixture\r
+{\r
+public:\r
+    bool setUpWorld() {\r
+        XMLToolingConfig::getConfig().log_config("DEBUG");\r
+        if (!XMLToolingConfig::getConfig().init())\r
+            return false;\r
+        validatingPool = new ParserPool(true,true);\r
+        nonvalidatingPool = new ParserPool();\r
+        return true;\r
+    }\r
+    bool tearDownWorld() {\r
+        delete validatingPool;\r
+        delete nonvalidatingPool;\r
+        XMLToolingConfig::getConfig().term();\r
+#if defined(_MSC_VER ) && defined(XMLTOOLINGTEST_LEAKCHECK)\r
+       _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );\r
+       _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );\r
+       _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );\r
+       _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );\r
+       _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );\r
+       _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );\r
+       _CrtDumpMemoryLeaks();\r
+#endif\r
+        return true;\r
+    }\r
+    //bool setUp() { printf( "</test>" ); return true; }\r
+    //bool tearDown() { printf( "</test>" ); return true; }\r
+};\r
+\r
+static ToolingFixture globalFixture;\r
+\r
+class CatalogTest : public CxxTest::TestSuite\r
+{\r
+public:\r
+    void testCatalog(void) {\r
+        auto_ptr_XMLCh temp("../xmltoolingtest/data/catalog.xml");\r
+        TS_ASSERT(validatingPool->loadCatalog(temp.get()));\r
+    }\r
+};\r
diff --git a/xmltoolingtest/xmltoolingtest.vcproj b/xmltoolingtest/xmltoolingtest.vcproj
new file mode 100644 (file)
index 0000000..a19b4f1
--- /dev/null
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="8.00"\r
+       Name="xmltoolingtest"\r
+       ProjectGUID="{3E34CDCC-FCBA-490D-A165-1CB6F4559799}"\r
+       RootNamespace="xmltoolingtest"\r
+       Keyword="Win32Proj"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories=".."\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="0"\r
+                               BrowseInformation="1"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="4"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="xerces-c_2D.lib"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories=".."\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="xerces-c_2.lib"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Generated Code"\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\UnknownTest.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\xmltoolingtest.cpp"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Unit Tests"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\UnknownTest.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
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCustomBuildTool"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --error-printer --have-eh --have-std --abort-on-fail -o &quot;$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
+                                               Outputs="$(InputName).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 --error-printer --have-eh --have-std --abort-on-fail -o &quot;$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
+                                               Outputs="&quot;$(InputName)&quot;.cpp"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <File\r
+                       RelativePath=".\XMLObjectBaseTestCase.h"\r
+                       >\r
+               </File>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r