Reimplement namespace visibility as a three-way setting.
[shibboleth/cpp-xmltooling.git] / xmltooling / io / AbstractXMLObjectMarshaller.cpp
index 87e0087..39b515c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-*  Copyright 2001-2007 Internet2
+*  Copyright 2001-2009 Internet2
  * 
 * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #endif
 using namespace xmlconstants;
 using namespace xmltooling;
+using namespace xercesc;
 using namespace std;
 
+AbstractXMLObjectMarshaller::AbstractXMLObjectMarshaller()
+{
+}
+
+AbstractXMLObjectMarshaller::~AbstractXMLObjectMarshaller()
+{
+}
+
+void AbstractXMLObjectMarshaller::setDocumentElement(DOMDocument* document, DOMElement* element) const
+{
+    DOMElement* documentRoot = document->getDocumentElement();
+    if (documentRoot)
+        document->replaceChild(element, documentRoot);
+    else
+        document->appendChild(element);
+}
+
 DOMElement* AbstractXMLObjectMarshaller::marshall(
     DOMDocument* document
 #ifndef XMLTOOLING_NO_XMLSEC
@@ -192,6 +210,27 @@ void AbstractXMLObjectMarshaller::marshallInto(
                 targetElement->setAttributeNS(XSI_NS,noNamespaceSchemaLocation,m_noNamespaceSchemaLocation); 
         }
     }
+    
+    static const XMLCh _nil[] = { chLatin_x, chLatin_s, chLatin_i, chColon, chLatin_n, chLatin_i, chLatin_l, chNull };
+    
+    if (m_nil != xmlconstants::XML_BOOL_NULL) {
+        switch (m_nil) {
+            case xmlconstants::XML_BOOL_TRUE:
+               targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_TRUE);
+                break;
+            case xmlconstants::XML_BOOL_ONE:
+               targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_ONE);
+                break;
+            case xmlconstants::XML_BOOL_FALSE:
+               targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_FALSE);
+                break;
+            case xmlconstants::XML_BOOL_ZERO:
+               targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_ZERO);
+                break;
+        }
+        m_log.debug("adding XSI namespace to list of namespaces visibly used by XMLObject");
+        addNamespace(Namespace(XSI_NS, XSI_PREFIX, false, Namespace::VisiblyUsed));
+    }
 
     marshallElementType(targetElement);
     marshallNamespaces(targetElement);
@@ -200,7 +239,7 @@ void AbstractXMLObjectMarshaller::marshallInto(
 #ifndef XMLTOOLING_NO_XMLSEC
     marshallContent(targetElement,credential);
     if (sigs) {
-        for_each(sigs->begin(),sigs->end(),bind2nd(mem_fun1<void,Signature,const Credential*>(&Signature::sign),credential));
+        for_each(sigs->begin(),sigs->end(),bind2nd(mem_fun1_t<void,Signature,const Credential*>(&Signature::sign),credential));
     }
 #else
     marshallContent(targetElement);
@@ -236,8 +275,8 @@ void AbstractXMLObjectMarshaller::marshallElementType(DOMElement* domElement) co
         if (xsivalue != typeLocalName)
             XMLString::release(&xsivalue);
 
-        m_log.debug("adding XSI namespace to list of namespaces used by XMLObject");
-        addNamespace(Namespace(XSI_NS, XSI_PREFIX));
+        m_log.debug("adding XSI namespace to list of namespaces visibly used by XMLObject");
+        addNamespace(Namespace(XSI_NS, XSI_PREFIX, false, Namespace::VisiblyUsed));
     }
 }
 
@@ -247,6 +286,10 @@ public:
         const XMLCh* prefix=ns.getNamespacePrefix();
         const XMLCh* uri=ns.getNamespaceURI();
         
+        // Check for xmlns:xml.
+        if (XMLString::equals(prefix, XML_PREFIX) && XMLString::equals(uri, XML_NS))
+            return;
+
         // Check to see if the prefix is already declared properly above this node.
         if (!ns.alwaysDeclare()) {
             const XMLCh* declared=lookupNamespaceURI(domElement->getParentNode(),prefix);
@@ -262,7 +305,7 @@ public:
             XMLString::catString(xmlns,colon);
             XMLString::catString(xmlns,prefix);
             domElement->setAttributeNS(XMLNS_NS, xmlns, uri);
-            XMLString::release(&xmlns);
+            delete[] xmlns;
         }
         else {
             domElement->setAttributeNS(XMLNS_NS, XMLNS_PREFIX, uri);
@@ -316,22 +359,26 @@ void AbstractXMLObjectMarshaller::marshallContent(
 {
     m_log.debug("marshalling text and child elements for XMLObject");
     
-    const XMLCh* val;
     unsigned int pos=0;
+    const XMLCh* val = getTextContent(pos);
+    if (val && *val)
+        domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val));
+    
     const list<XMLObject*>& children=getOrderedChildren();
-    for (list<XMLObject*>::const_iterator i=children.begin(); i!=children.end(); ++i, ++pos) {
-        val = getTextContent(pos);
-        if (val && *val)
-            domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val));
+    for (list<XMLObject*>::const_iterator i=children.begin(); i!=children.end(); ++i) {
         if (*i) {
 #ifndef XMLTOOLING_NO_XMLSEC
             (*i)->marshall(domElement,NULL,credential);
 #else
             (*i)->marshall(domElement);
 #endif
+            val = getTextContent(++pos);
+            if (val && *val)
+                domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val));
         }
     }
-    val = getTextContent(pos);
-    if (val && *val)
-        domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val));
+}
+
+void AbstractXMLObjectMarshaller::marshallAttributes(DOMElement* domElement) const
+{
 }