Distinguish between visibly used and unused namespaces.
authorScott Cantor <cantor.2@osu.edu>
Mon, 18 Jan 2010 21:56:38 +0000 (21:56 +0000)
committerScott Cantor <cantor.2@osu.edu>
Mon, 18 Jan 2010 21:56:38 +0000 (21:56 +0000)
.cproject
xmltooling/AbstractAttributeExtensibleXMLObject.cpp
xmltooling/AbstractXMLObject.cpp
xmltooling/AttributeExtensibleXMLObject.h
xmltooling/Namespace.cpp
xmltooling/Namespace.h
xmltooling/io/AbstractXMLObjectUnmarshaller.cpp
xmltoolingtest/Makefile.am
xmltoolingtest/NonVisibleNamespaceTest.h [new file with mode: 0644]
xmltoolingtest/XMLObjectBaseTestCase.h
xmltoolingtest/data/SimpleXMLObjectWithNonVisible.xml [new file with mode: 0644]

index 23da8f4..ad088ae 100644 (file)
--- a/.cproject
+++ b/.cproject
@@ -57,6 +57,7 @@
 <listOptionValue builtIn="false" value="&quot;C:\xerces-c-3.0.1-x86-windows-vc-9.0\include&quot;"/>\r
 <listOptionValue builtIn="false" value="&quot;C:\xml-security-c-1.5.1\include&quot;"/>\r
 <listOptionValue builtIn="false" value="&quot;C:\Program Files\Microsoft Visual Studio 9.0\VC\include&quot;"/>\r
+<listOptionValue builtIn="false" value="&quot;C:\cxxtest&quot;"/>\r
 </option>\r
 <inputType id="org.eclipse.linuxtools.cdt.autotools.inputType.configure.387715961" superClass="org.eclipse.linuxtools.cdt.autotools.inputType.configure"/>\r
 <inputType id="org.eclipse.linuxtools.cdt.autotools.inputType.configure1.2086982536" superClass="org.eclipse.linuxtools.cdt.autotools.inputType.configure1"/>\r
@@ -83,6 +84,9 @@
 </sourceEntries>\r
 </configuration>\r
 </storageModule>\r
+<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>\r
+<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>\r
+<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>\r
 <storageModule moduleId="scannerConfiguration">\r
 <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>\r
 <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">\r
 <parser enabled="false"/>\r
 </scannerInfoProvider>\r
 </profile>\r
-<scannerConfigBuildInfo instanceId="org.eclipse.linuxtools.cdt.autotools.configuration.build.1769801814;org.eclipse.linuxtools.cdt.autotools.configuration.build.1769801814.">\r
+<scannerConfigBuildInfo instanceId="org.eclipse.linuxtools.cdt.autotools.configuration.build.1769801814;org.eclipse.linuxtools.cdt.autotools.configuration.build.1769801814.;org.eclipse.linuxtools.cdt.autotools.gnu.toolchain.tool.configure.837026680;org.eclipse.linuxtools.cdt.autotools.inputType.configure1.2086982536">\r
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"/>\r
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">\r
+<buildOutputProvider>\r
+<openAction enabled="true" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>\r
+<parser enabled="true"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">\r
+<buildOutputProvider>\r
+<openAction enabled="false" filePath=""/>\r
+<parser enabled="false"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="makefileGenerator">\r
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>\r
+<parser enabled="false"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">\r
+<buildOutputProvider>\r
+<openAction enabled="false" filePath=""/>\r
+<parser enabled="false"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>\r
+<parser enabled="false"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">\r
+<buildOutputProvider>\r
+<openAction enabled="false" filePath=""/>\r
+<parser enabled="false"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>\r
+<parser enabled="false"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">\r
+<buildOutputProvider>\r
+<openAction enabled="false" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>\r
+<parser enabled="false"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">\r
+<buildOutputProvider>\r
+<openAction enabled="false" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>\r
+<parser enabled="false"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">\r
+<buildOutputProvider>\r
+<openAction enabled="false" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>\r
+<parser enabled="false"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">\r
+<buildOutputProvider>\r
+<openAction enabled="false" filePath=""/>\r
+<parser enabled="true"/>\r
+</buildOutputProvider>\r
+<scannerInfoProvider id="specsFile">\r
+<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>\r
+<parser enabled="false"/>\r
+</scannerInfoProvider>\r
+</profile>\r
+</scannerConfigBuildInfo>\r
+<scannerConfigBuildInfo instanceId="org.eclipse.linuxtools.cdt.autotools.configuration.build.1769801814;org.eclipse.linuxtools.cdt.autotools.configuration.build.1769801814.;org.eclipse.linuxtools.cdt.autotools.gnu.toolchain.tool.configure.837026680;org.eclipse.linuxtools.cdt.autotools.inputType.configure.387715961">\r
 <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile"/>\r
 <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">\r
 <buildOutputProvider>\r
 </profile>\r
 </scannerConfigBuildInfo>\r
 </storageModule>\r
-<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>\r
-<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>\r
-<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>\r
 </cconfiguration>\r
 </storageModule>\r
 <storageModule moduleId="cdtBuildSystem" version="4.0.0">\r
index eae509f..44b07bc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2009 Internet2
+ *  Copyright 2001-2010 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
 
 using namespace xmltooling;
 using namespace std;
+using xercesc::chColon;
 
 using xercesc::DOMAttr;
 using xercesc::DOMElement;
@@ -137,9 +138,30 @@ void AbstractAttributeExtensibleXMLObject::setAttribute(const QName& qualifiedNa
         m_attributeMap[qualifiedName]=XMLString::replicate(value);
         if (ID)
             m_idAttribute = m_attributeMap.find(qualifiedName);
+        Namespace newNamespace(qualifiedName.getNamespaceURI(), qualifiedName.getPrefix());
+        addNamespace(newNamespace);
     }
 }
 
+void AttributeExtensibleXMLObject::setAttribute(const QName& qualifiedName, const QName& value)
+{
+    if (!value.hasLocalPart())
+        return;
+
+    if (value.hasPrefix()) {
+        xstring buf(value.getPrefix());
+        buf = buf + chColon + value.getLocalPart();
+        setAttribute(qualifiedName, buf.c_str());
+    }
+    else {
+        setAttribute(qualifiedName, value.getLocalPart());
+    }
+
+    // Attach a non-visibly used namespace.
+    Namespace newNamespace(value.getNamespaceURI(), value.getPrefix(), false, false);
+    addNamespace(newNamespace);
+}
+
 const map<QName,XMLCh*>& AbstractAttributeExtensibleXMLObject::getExtensionAttributes() const
 {
     return m_attributeMap;
index 58efeda..9944a96 100644 (file)
@@ -1,5 +1,5 @@
 /*
-*  Copyright 2001-2009 Internet2
+*  Copyright 2001-2010 Internet2
  *
 * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -60,7 +60,8 @@ AbstractXMLObject::AbstractXMLObject(const XMLCh* nsURI, const XMLCh* localName,
     addNamespace(Namespace(nsURI, prefix));
     if (schemaType) {
         m_typeQname = new QName(*schemaType);
-        addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix()));
+        // Attach a non-visibly used namespace.
+        addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix(), false, false));
     }
 }
 
@@ -133,8 +134,12 @@ void AbstractXMLObject::addNamespace(const Namespace& ns) const
     std::set<Namespace>::iterator i = m_namespaces.find(ns);
     if (i == m_namespaces.end())
         m_namespaces.insert(ns);
-    else if (ns.alwaysDeclare())
-        const_cast<Namespace&>(*i).setAlwaysDeclare(true);
+    else {
+        if (ns.alwaysDeclare())
+            const_cast<Namespace&>(*i).setAlwaysDeclare(true);
+        if (ns.visiblyUsed())
+            const_cast<Namespace&>(*i).setVisiblyUsed(true);
+    }
 }
 
 void AbstractXMLObject::removeNamespace(const Namespace& ns)
@@ -196,8 +201,8 @@ QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* new
     if (!oldValue) {
         if (newValue) {
             releaseThisandParentDOM();
-            Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());
-            addNamespace(newNamespace);
+            // Attach a non-visibly used namespace.
+            addNamespace(Namespace(newValue->getNamespaceURI(), newValue->getPrefix(), false, false));
             return new QName(*newValue);
         }
         return NULL;
@@ -206,8 +211,8 @@ QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* new
     delete oldValue;
     releaseThisandParentDOM();
     if (newValue) {
-        Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());
-        addNamespace(newNamespace);
+        // Attach a non-visibly used namespace.
+        addNamespace(Namespace(newValue->getNamespaceURI(), newValue->getPrefix(), false, false));
         return new QName(*newValue);
     }
     return NULL;
index 08eff0f..c01250f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2009 Internet2
+ *  Copyright 2001-2010 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -61,6 +61,14 @@ namespace xmltooling {
         virtual void setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID=false)=0;
 
         /**
+         * Sets a QName-valued XML attribute of the object.
+         * 
+         * @param qualifiedName qualified name of the attribute   
+         * @param value         value to set
+         */
+        virtual void setAttribute(const QName& qualifiedName, const QName& value);
+
+        /**
          * Gets an immutable map of the extended XML attributes of the object.
          * 
          * This set is not guaranteed to (and generally will not) include
index ebb942f..179579b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2009 Internet2
+ *  Copyright 2001-2010 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,7 +27,8 @@ using namespace xmltooling;
 
 using xercesc::XMLString;
 
-Namespace::Namespace(const XMLCh* uri, const XMLCh* prefix, bool alwaysDeclare) : m_pinned(alwaysDeclare)
+Namespace::Namespace(const XMLCh* uri, const XMLCh* prefix, bool alwaysDeclare, bool visiblyUsed)
+    : m_pinned(alwaysDeclare), m_visiblyUsed(visiblyUsed)
 {
     setNamespaceURI(uri);
     setNamespacePrefix(prefix);
index 16ff035..8ac6382 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2009 Internet2
+ *  Copyright 2001-2010 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -43,8 +43,9 @@ namespace xmltooling {
          * @param uri               namespace URI
          * @param prefix            namespace prefix (without the colon)
          * @param alwaysDeclare     true iff the namespace should always be declared regardless of in-scope declarations
+         * @param visiblyUsed       true iff the namespace is visibly used by an XMLObject its attached to
          */
-        Namespace(const XMLCh* uri=NULL, const XMLCh* prefix=NULL, bool alwaysDeclare=false);
+        Namespace(const XMLCh* uri=NULL, const XMLCh* prefix=NULL, bool alwaysDeclare=false, bool visiblyUsed=true);
         
         ~Namespace();
         
@@ -64,7 +65,13 @@ namespace xmltooling {
          * Returns true iff the namespace should always be declared regardless of in-scope declarations
          * @return the alwaysDeclared setting
          */
-        const bool alwaysDeclare() const { return m_pinned; } 
+        const bool alwaysDeclare() const { return m_pinned; }
+
+        /**
+         * Returns true iff the namespace is visibly used by an XMLObject its attached to
+         * @return the visiblyUsed setting
+         */
+        const bool visiblyUsed() const { return m_visiblyUsed; }
 
         /**
          * Sets the namespace prefix
@@ -84,8 +91,14 @@ namespace xmltooling {
          */
         void setAlwaysDeclare(bool alwaysDeclare) { m_pinned = alwaysDeclare; } 
         
+        /**
+         * Sets the visiblyUsed property
+         * @param visiblyUsed     true iff the namespace is visibly used by an XMLObject its attached to
+         */
+        void setVisiblyUsed(bool visiblyUsed) { m_visiblyUsed = visiblyUsed; }
+
     private:
-        bool m_pinned;
+        bool m_pinned,m_visiblyUsed;
         xstring m_uri;
         xstring m_prefix;
     };
index b200f5b..4d0f8cc 100644 (file)
@@ -1,5 +1,5 @@
 /*
-*  Copyright 2001-2009 Internet2
+*  Copyright 2001-2010 Internet2
  * 
 * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -106,14 +106,14 @@ void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domEl
         if (XMLString::equals(nsuri,XMLNS_NS)) {
             if (XMLString::equals(attribute->getLocalName(),XMLNS_PREFIX)) {
                 m_log.debug("found default namespace declaration, adding it to the list of namespaces on the XMLObject");
-                addNamespace(Namespace(attribute->getValue(), NULL, true));
+                addNamespace(Namespace(attribute->getValue(), NULL, true, false));
             }
             else if (XMLString::equals(attribute->getLocalName(),XML_PREFIX) && XMLString::equals(attribute->getNodeValue(),XML_NS)) {
                 m_log.debug("found standard xml prefix declaration, ignoring as superfluous");
             }
             else {
                 m_log.debug("found namespace declaration, adding it to the list of namespaces on the XMLObject");
-                addNamespace(Namespace(attribute->getValue(), attribute->getLocalName(), true));
+                addNamespace(Namespace(attribute->getValue(), attribute->getLocalName(), true, false));
             }
             continue;
         }
index 5698e75..b1a5502 100644 (file)
@@ -35,6 +35,7 @@ xmltoolingtest_h = \
     ExceptionTest.h \
     KeyInfoTest.h \
     MarshallingTest.h \
+    NonVisibleNamespaceTest.h \
     UnmarshallingTest.h \
     TemplateEngineTest.h \
     xmltoolingtest.h \
diff --git a/xmltoolingtest/NonVisibleNamespaceTest.h b/xmltoolingtest/NonVisibleNamespaceTest.h
new file mode 100644 (file)
index 0000000..a1eeaa7
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ *  Copyright 2001-2010 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "XMLObjectBaseTestCase.h"
+
+#include <fstream>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+class NonVisibleNamespaceTest : public CxxTest::TestSuite {
+public:
+    void setUp() {
+        xmltooling::QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME);
+        xmltooling::QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME);
+        XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder());
+        XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder());
+    }
+
+    void tearDown() {
+        xmltooling::QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME);
+        xmltooling::QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME);
+        XMLObjectBuilder::deregisterBuilder(qname);
+        XMLObjectBuilder::deregisterBuilder(qtype);
+    }
+
+    void testNamespacesAfterBuilding() {
+        xmltooling::QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME,SimpleXMLObject::NAMESPACE_PREFIX);
+        const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(qtype);
+        TS_ASSERT(b!=NULL);
+        auto_ptr<SimpleXMLObject> sxObject(
+            dynamic_cast<SimpleXMLObject*>(b->buildObject(SimpleXMLObject::NAMESPACE, SimpleXMLObject::LOCAL_NAME, NULL, &qtype))
+            );
+        TS_ASSERT(sxObject.get()!=NULL);
+        static_cast<AttributeExtensibleXMLObject*>(sxObject.get())->setAttribute(
+            xmltooling::QName(NULL, "attr1"), xmltooling::QName("http://www.example.org/testObjects/ext", "Value1", "test2")
+            );
+
+        static const XMLCh TEST2_PREFIX[] = { chLatin_t, chLatin_e, chLatin_s, chLatin_t, chDigit_2, chNull };
+
+        const set<Namespace>& namespaces = sxObject->getNamespaces();
+        bool cond1=false, cond2=false, cond3 = false;
+        for (set<Namespace>::const_iterator ns = namespaces.begin(); ns != namespaces.end(); ++ns) {
+            if (XMLString::equals(ns->getNamespacePrefix(), SimpleXMLObject::NAMESPACE_PREFIX)) {
+                TSM_ASSERT("'test' namespace was visibly used", !ns->visiblyUsed());
+                cond1 = true;
+            }
+            else if (XMLString::equals(ns->getNamespacePrefix(), TEST2_PREFIX)) {
+                TSM_ASSERT("'test2' namespace was visibly used", !ns->visiblyUsed());
+                cond2 = true;
+            }
+            else if (XMLString::equals(ns->getNamespacePrefix(), &chNull)) {
+                TSM_ASSERT("Default namespace was not visibly used", ns->visiblyUsed());
+                cond3 = true;
+            }
+        }
+        TSM_ASSERT("'test' namespace was missing.", cond1);
+        TSM_ASSERT("'test2' namespace was missing.", cond2);
+        TSM_ASSERT("Default namespace was missing.", cond3);
+    }
+
+    void testNamespacesAfterUnmarshalling() {
+        string path=data_path + "SimpleXMLObjectWithNonVisible.xml";
+        ifstream fs(path.c_str());
+        DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs);
+        TS_ASSERT(doc!=NULL);
+
+        const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
+        TS_ASSERT(b!=NULL);
+
+        auto_ptr<SimpleXMLObject> sxObject(
+            dynamic_cast<SimpleXMLObject*>(b->buildFromDocument(doc))
+            );
+        TS_ASSERT(sxObject.get()!=NULL);
+
+        const set<Namespace>& namespaces = sxObject->getNamespaces();
+        bool cond1=false, cond2=false, cond3=false;
+        for (set<Namespace>::const_iterator ns = namespaces.begin(); ns != namespaces.end(); ++ns) {
+            if (XMLString::equals(ns->getNamespacePrefix(), SimpleXMLObject::NAMESPACE_PREFIX)) {
+                TSM_ASSERT("'test' namespace was visibly used", !ns->visiblyUsed());
+                cond1 = true;
+            }
+            else if (XMLString::equals(ns->getNamespacePrefix(), &chNull)) {
+                TSM_ASSERT("Default namespace was not visibly used", ns->visiblyUsed());
+                cond2 = true;
+            }
+        }
+        TSM_ASSERT("Default or 'test' namespace missing.", cond1 && cond2);
+        for (set<Namespace>::const_iterator ns = namespaces.begin(); ns != namespaces.end(); ++ns) {
+            static const XMLCh TEST2_PREFIX[] = { chLatin_t, chLatin_e, chLatin_s, chLatin_t, chDigit_2, chNull };
+            TSM_ASSERT("'test2' namespace was noted during unmarshalling", !XMLString::equals(ns->getNamespacePrefix(), TEST2_PREFIX));
+        }
+    }
+};
index 99aa08f..1962683 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2010 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
  */
 
 #include <cxxtest/TestSuite.h>
+#include <xmltooling/AbstractAttributeExtensibleXMLObject.h>
 #include <xmltooling/AbstractComplexElement.h>
 #include <xmltooling/ElementProxy.h>
 #include <xmltooling/exceptions.h>
@@ -46,14 +47,15 @@ extern string data_path;
 #endif
 
 class SimpleXMLObject
-    : public AbstractComplexElement,
+    : public AbstractAttributeExtensibleXMLObject,
+        public AbstractComplexElement,
         public AbstractDOMCachingXMLObject,
         public AbstractXMLObjectMarshaller,
         public AbstractXMLObjectUnmarshaller
 {
 protected:
     SimpleXMLObject(const SimpleXMLObject& src)
-            : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src),
+            : AbstractXMLObject(src), AbstractAttributeExtensibleXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src),
                 m_id(XMLString::replicate(src.m_id)) {
 #ifndef XMLTOOLING_NO_XMLSEC
         m_children.push_back(NULL);
@@ -132,6 +134,7 @@ protected:
             domElement->setIdAttributeNS(NULL, SimpleXMLObject::ID_ATTRIB_NAME);
 #endif
         }
+        marshallExtensionAttributes(domElement);
     }
 
     void processChildElement(XMLObject* childXMLObject, const xercesc::DOMElement* root) {
@@ -153,10 +156,11 @@ protected:
     }
 
     void processAttribute(const xercesc::DOMAttr* attribute) {
-        if (XMLHelper::isNodeNamed(attribute, NULL, SimpleXMLObject::ID_ATTRIB_NAME))
+        if (XMLHelper::isNodeNamed(attribute, NULL, SimpleXMLObject::ID_ATTRIB_NAME)) {
             setId(attribute->getValue());
-        else
-            throw UnmarshallingException("Unknown attribute cannot be processed by parent object.");
+            return;
+        }
+        unmarshallExtensionAttribute(attribute);
     }
 
 private:
diff --git a/xmltoolingtest/data/SimpleXMLObjectWithNonVisible.xml b/xmltoolingtest/data/SimpleXMLObjectWithNonVisible.xml
new file mode 100644 (file)
index 0000000..3eea6ac
Binary files /dev/null and b/xmltoolingtest/data/SimpleXMLObjectWithNonVisible.xml differ