[java-opensaml] 01/02: OSJ-154: Marshalling an assertion into a new document does not preserve its IDness

Brent Putman putmanb at georgetown.edu
Thu May 28 03:50:34 UTC 2020


This is an automated email from the git hooks/post-receive script.

putmanb pushed a commit to branch master
in repository java-opensaml.

View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=c1423fcff610e75510386bc995a062f46aa0a5cf

commit c1423fcff610e75510386bc995a062f46aa0a5cf
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Fri May 15 04:21:17 2020 -0400

    OSJ-154: Marshalling an assertion into a new document does not preserve its IDness
---
 .../xml/AbstractExtensibleXMLObjectMarshaller.java | 32 ++++++---------
 .../core/xml/io/AbstractXMLObjectMarshaller.java   | 28 +++++++++++++
 .../core/xml/schema/impl/XSAnyMarshaller.java      | 23 +++--------
 .../opensaml/core/xml/util/XMLObjectSupport.java   | 46 +++++++++++++++++++++-
 .../core/xml/XMLObjectProviderBaseTestCase.java    | 37 +++++++++++++++++
 .../saml/saml1/core/impl/AssertionMarshaller.java  | 14 +++++--
 .../saml1/core/impl/AssertionUnmarshaller.java     |  3 +-
 .../core/impl/RequestAbstractTypeMarshaller.java   | 14 +++++--
 .../core/impl/RequestAbstractTypeUnmarshaller.java |  3 +-
 .../core/impl/ResponseAbstractTypeMarshaller.java  | 13 ++++--
 .../impl/ResponseAbstractTypeUnmarshaller.java     |  3 +-
 .../saml/saml2/core/impl/AssertionMarshaller.java  | 10 ++++-
 .../core/impl/RequestAbstractTypeMarshaller.java   |  9 ++++-
 .../core/impl/StatusResponseTypeMarshaller.java    | 10 ++++-
 .../impl/AffiliationDescriptorMarshaller.java      | 13 +++++-
 .../impl/EntitiesDescriptorMarshaller.java         | 14 ++++++-
 .../metadata/impl/EntityDescriptorMarshaller.java  | 17 +++++++-
 .../metadata/impl/RoleDescriptorMarshaller.java    | 12 +++++-
 .../saml/saml1/core/impl/AssertionTest.java        | 25 ++++++++++--
 .../opensaml/saml/saml1/core/impl/RequestTest.java | 27 ++++++++++---
 .../saml/saml1/core/impl/ResponseTest.java         | 25 ++++++++++--
 .../saml/saml2/core/impl/ArtifactResolveTest.java  | 25 ++++++++++--
 .../saml/saml2/core/impl/ArtifactResponseTest.java | 23 ++++++++++-
 .../saml2/core/impl/AssertionIDRequestTest.java    | 24 +++++++++--
 .../saml/saml2/core/impl/AssertionTest.java        | 29 ++++++++++----
 .../saml/saml2/core/impl/AttributeQueryTest.java   | 24 +++++++++--
 .../saml/saml2/core/impl/AuthnQueryTest.java       | 25 ++++++++++--
 .../saml/saml2/core/impl/AuthnRequestTest.java     | 28 ++++++++++---
 .../saml2/core/impl/AuthzDecisionQueryTest.java    | 24 +++++++++--
 .../saml/saml2/core/impl/LogoutRequestTest.java    | 26 ++++++++++--
 .../saml/saml2/core/impl/LogoutResponseTest.java   | 23 ++++++++++-
 .../saml2/core/impl/ManageNameIDRequestTest.java   | 25 ++++++++++--
 .../saml2/core/impl/ManageNameIDResponseTest.java  | 23 ++++++++++-
 .../saml2/core/impl/NameIDMappingRequestTest.java  | 25 ++++++++++--
 .../saml2/core/impl/NameIDMappingResponseTest.java | 25 ++++++++++--
 .../saml/saml2/core/impl/ResponseTest.java         | 28 ++++++++++---
 .../metadata/impl/AffiliationDescriptorTest.java   | 22 ++++++++++-
 .../metadata/impl/EntitiesDescriptorTest.java      | 29 +++++++++++---
 .../saml2/metadata/impl/EntityDescriptorTest.java  | 22 ++++++++++-
 .../opensaml/soap/soap11/impl/BodyMarshaller.java  | 20 +---------
 .../soap/soap11/impl/DetailMarshaller.java         | 20 +---------
 .../soap/soap11/impl/EnvelopeMarshaller.java       | 20 +---------
 .../soap/soap11/impl/HeaderMarshaller.java         | 20 +---------
 .../soap/wspolicy/impl/PolicyMarshaller.java       |  7 ++++
 .../impl/AttributedDateTimeMarshaller.java         |  7 ++++
 .../impl/AttributedStringMarshaller.java           |  7 ++++
 .../wssecurity/impl/EncryptedHeaderMarshaller.java |  7 ++++
 .../impl/SecurityTokenReferenceMarshaller.java     |  7 ++++
 .../impl/SignatureConfirmationMarshaller.java      |  7 ++++
 .../soap/wssecurity/impl/TimestampMarshaller.java  |  7 ++++
 .../wssecurity/impl/UsernameTokenMarshaller.java   |  7 ++++
 .../encryption/impl/EncryptedTypeMarshaller.java   |  9 ++++-
 .../impl/EncryptionPropertiesMarshaller.java       |  9 ++++-
 .../impl/EncryptionPropertyMarshaller.java         | 32 ++++++---------
 .../impl/DEREncodedKeyValueMarshaller.java         |  9 ++++-
 .../signature/impl/ECKeyValueMarshaller.java       | 11 +++++-
 .../xmlsec/signature/impl/KeyInfoMarshaller.java   |  9 ++++-
 .../signature/impl/KeyInfoReferenceMarshaller.java | 10 ++++-
 .../xmlsec/encryption/impl/EncryptedDataTest.java  | 25 ++++++++++--
 .../xmlsec/encryption/impl/EncryptedKeyTest.java   | 25 ++++++++++--
 .../encryption/impl/EncryptionPropertiesTest.java  | 26 ++++++++++--
 .../encryption/impl/EncryptionPropertyTest.java    | 25 ++++++++++--
 .../signature/impl/DEREncodedKeyValueTest.java     | 19 +++++++++
 .../xmlsec/signature/impl/ECKeyValueTest.java      | 19 +++++++++
 .../signature/impl/KeyInfoReferenceTest.java       | 20 ++++++++++
 .../xmlsec/signature/impl/KeyInfoTest.java         | 25 ++++++++++--
 66 files changed, 990 insertions(+), 247 deletions(-)

diff --git a/opensaml-core/src/main/java/org/opensaml/core/xml/AbstractExtensibleXMLObjectMarshaller.java b/opensaml-core/src/main/java/org/opensaml/core/xml/AbstractExtensibleXMLObjectMarshaller.java
index 2b99ec328..f58bdb233 100644
--- a/opensaml-core/src/main/java/org/opensaml/core/xml/AbstractExtensibleXMLObjectMarshaller.java
+++ b/opensaml-core/src/main/java/org/opensaml/core/xml/AbstractExtensibleXMLObjectMarshaller.java
@@ -17,17 +17,10 @@
 
 package org.opensaml.core.xml;
 
-import java.util.Map.Entry;
-
 import javax.annotation.Nonnull;
-import javax.xml.namespace.QName;
-
-import net.shibboleth.utilities.java.support.xml.AttributeSupport;
 
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
 import org.opensaml.core.xml.io.MarshallingException;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.w3c.dom.Element;
 
 /**
@@ -49,18 +42,19 @@ public abstract class AbstractExtensibleXMLObjectMarshaller extends AbstractElem
     @Override
     protected void marshallAttributes(@Nonnull final XMLObject xmlObject, @Nonnull final Element domElement)
             throws MarshallingException {
+
+        final AttributeExtensibleXMLObject anyAttribute = (AttributeExtensibleXMLObject) xmlObject;
+
+        XMLObjectSupport.marshallAttributeMap(anyAttribute.getUnknownAttributes(), domElement);
+    }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
         final AttributeExtensibleXMLObject anyAttribute = (AttributeExtensibleXMLObject) xmlObject;
-        Attr attribute;
-        final Document document = domElement.getOwnerDocument();
-        for (final Entry<QName, String> entry : anyAttribute.getUnknownAttributes().entrySet()) {
-            attribute = AttributeSupport.constructAttribute(document, entry.getKey());
-            attribute.setValue(entry.getValue());
-            domElement.setAttributeNodeNS(attribute);
-            if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey())
-                    || anyAttribute.getUnknownAttributes().isIDAttribute(entry.getKey())) {
-                attribute.getOwnerElement().setIdAttributeNode(attribute, true);
-            }
-        }
+
+        XMLObjectSupport.marshallAttributeMapIDness(anyAttribute.getUnknownAttributes(), domElement);
     }
 
 }
\ No newline at end of file
diff --git a/opensaml-core/src/main/java/org/opensaml/core/xml/io/AbstractXMLObjectMarshaller.java b/opensaml-core/src/main/java/org/opensaml/core/xml/io/AbstractXMLObjectMarshaller.java
index fc8a87ebf..15516b455 100644
--- a/opensaml-core/src/main/java/org/opensaml/core/xml/io/AbstractXMLObjectMarshaller.java
+++ b/opensaml-core/src/main/java/org/opensaml/core/xml/io/AbstractXMLObjectMarshaller.java
@@ -35,6 +35,7 @@ import org.opensaml.core.xml.AttributeExtensibleXMLObject;
 import org.opensaml.core.xml.Namespace;
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.util.AttributeMap;
 import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -103,6 +104,8 @@ public abstract class AbstractXMLObjectMarshaller implements Marshaller {
             log.trace("Setting DOM of XMLObject as document element of given Document");
             setDocumentElement(document, domElement);
 
+            marshallAttributeIDness(xmlObject, domElement);
+
             return domElement;
         }
 
@@ -147,6 +150,8 @@ public abstract class AbstractXMLObjectMarshaller implements Marshaller {
                     QNameSupport.getNodeQName(parentElement));
             ElementSupport.appendChildElement(parentElement, domElement);
 
+            marshallAttributeIDness(xmlObject, domElement);
+
             return domElement;
         }
 
@@ -209,6 +214,8 @@ public abstract class AbstractXMLObjectMarshaller implements Marshaller {
 
         marshallAttributes(xmlObject, targetElement);
 
+        marshallAttributeIDness(xmlObject, targetElement);
+
         marshallChildElements(xmlObject, targetElement);
 
         marshallElementContent(xmlObject, targetElement);
@@ -389,6 +396,27 @@ public abstract class AbstractXMLObjectMarshaller implements Marshaller {
         
     }
 
+    /**
+     * Marshalls the IDness of the ID attribute present on the element, if any.
+     *
+     * The default implementation here handles the wildcard attributes in the {@link AttributeMap} if the XMLObject
+     * is an instance of {@link AttributeExtensibleXMLObject}, via {@link XMLObjectSupport.marshallAttributeMapIDness}.
+     *
+     * @param xmlObject the XMLObject to marshall
+     * @param domElement the W3C DOM element
+     *
+     * @throws MarshallingException thrown if there is a problem marshalling the element
+     */
+    protected void marshallAttributeIDness(@Nonnull final XMLObject xmlObject, @Nonnull final Element domElement)
+            throws MarshallingException {
+
+        if (AttributeExtensibleXMLObject.class.isInstance(xmlObject)) {
+            XMLObjectSupport.marshallAttributeMapIDness(
+                    AttributeExtensibleXMLObject.class.cast(xmlObject).getUnknownAttributes(), domElement);
+        }
+
+    }
+
     /**
      * Marshalls data from the XMLObject into content of the DOM Element.
      * 
diff --git a/opensaml-core/src/main/java/org/opensaml/core/xml/schema/impl/XSAnyMarshaller.java b/opensaml-core/src/main/java/org/opensaml/core/xml/schema/impl/XSAnyMarshaller.java
index 908485030..7edbb3e65 100644
--- a/opensaml-core/src/main/java/org/opensaml/core/xml/schema/impl/XSAnyMarshaller.java
+++ b/opensaml-core/src/main/java/org/opensaml/core/xml/schema/impl/XSAnyMarshaller.java
@@ -17,22 +17,17 @@
 
 package org.opensaml.core.xml.schema.impl;
 
-import java.util.Map.Entry;
-
 import javax.annotation.Nonnull;
-import javax.xml.namespace.QName;
-
-import net.shibboleth.utilities.java.support.xml.AttributeSupport;
-import net.shibboleth.utilities.java.support.xml.ElementSupport;
 
 import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
 import org.opensaml.core.xml.io.AbstractXMLObjectMarshaller;
 import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.schema.XSAny;
-import org.w3c.dom.Attr;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.w3c.dom.Element;
 
+import net.shibboleth.utilities.java.support.xml.ElementSupport;
+
 /**
  * Thread-safe marshaller of {@link XSAny} objects.
  */
@@ -42,18 +37,10 @@ public class XSAnyMarshaller extends AbstractXMLObjectMarshaller {
     @Override
     protected void marshallAttributes(@Nonnull final XMLObject xmlObject, @Nonnull final Element domElement)
             throws MarshallingException {
+
         final XSAny xsAny = (XSAny) xmlObject;
 
-        Attr attribute;
-        for (final Entry<QName, String> entry : xsAny.getUnknownAttributes().entrySet()) {
-            attribute = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey());
-            attribute.setValue(entry.getValue());
-            domElement.setAttributeNodeNS(attribute);
-            if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey())
-                    || xsAny.getUnknownAttributes().isIDAttribute(entry.getKey())) {
-                attribute.getOwnerElement().setIdAttributeNode(attribute, true);
-            }
-        }
+        XMLObjectSupport.marshallAttributeMap(xsAny.getUnknownAttributes(), domElement);
     }
 
     /** {@inheritDoc} */
diff --git a/opensaml-core/src/main/java/org/opensaml/core/xml/util/XMLObjectSupport.java b/opensaml-core/src/main/java/org/opensaml/core/xml/util/XMLObjectSupport.java
index 3dafe628a..4b53d8b2a 100644
--- a/opensaml-core/src/main/java/org/opensaml/core/xml/util/XMLObjectSupport.java
+++ b/opensaml-core/src/main/java/org/opensaml/core/xml/util/XMLObjectSupport.java
@@ -417,6 +417,50 @@ public final class XMLObjectSupport {
         }
     }
 
+    /**
+     * Marshall the ID-ness of attributes represented by the indicated AttributeMap into the indicated DOM Element.
+     *
+     * @param attributeMap the AttributeMap
+     * @param domElement the target Element
+     */
+    public static void marshallAttributeMapIDness(final AttributeMap attributeMap, final Element domElement) {
+        for (final QName qname : attributeMap.keySet()) {
+            if (XMLObjectProviderRegistrySupport.isIDAttribute(qname) || attributeMap.isIDAttribute(qname)) {
+                marshallAttributeIDness(qname, domElement, true);
+            }
+        }
+    }
+
+    /**
+     * Marshall the ID-ness of an attribute into the indicated DOM Element.
+     *
+     * @param attributeName the attribute QName
+     * @param domElement the target Element
+     * @param isIDAttribute true if attribute is an ID attribute, false if not
+     */
+    public static void marshallAttributeIDness(final QName attributeName, final Element domElement,
+            final boolean isIDAttribute) {
+
+        marshallAttributeIDness(attributeName.getNamespaceURI(), attributeName.getLocalPart(), domElement,
+                isIDAttribute);
+    }
+
+    /**
+     * Marshall the ID-ness of an attribute into the indicated DOM Element.
+     *
+     * @param namespaceURI the attribute name's namespace URI
+     * @param localPart the attribute name's local part
+     * @param domElement the target Element
+     * @param isIDAttribute true if attribute is an ID attribute, false if not
+     */
+    public static void marshallAttributeIDness(final String namespaceURI, final String localPart,
+            final Element domElement, final boolean isIDAttribute) {
+
+        if (domElement.hasAttributeNS(namespaceURI, localPart)) {
+            domElement.setIdAttributeNS(namespaceURI, localPart, isIDAttribute);
+        }
+    }
+
     /**
      * Unmarshall a DOM Attr to an AttributeMap.
      * 
@@ -431,7 +475,7 @@ public final class XMLObjectSupport {
             attributeMap.registerID(attribQName);
         }
     }
-    
+
     /**
      * Build an XMLObject based on the element name.
      * 
diff --git a/opensaml-core/src/test/java/org/opensaml/core/xml/XMLObjectProviderBaseTestCase.java b/opensaml-core/src/test/java/org/opensaml/core/xml/XMLObjectProviderBaseTestCase.java
index 944b4a338..4fa240599 100644
--- a/opensaml-core/src/test/java/org/opensaml/core/xml/XMLObjectProviderBaseTestCase.java
+++ b/opensaml-core/src/test/java/org/opensaml/core/xml/XMLObjectProviderBaseTestCase.java
@@ -17,10 +17,17 @@
 
 package org.opensaml.core.xml;
 
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import net.shibboleth.utilities.java.support.xml.ElementSupport;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  * Base test case for {@link org.opensaml.core.xml.XMLObject}s in XMLTooling for which we need a full set
@@ -146,5 +153,35 @@ public abstract class XMLObjectProviderBaseTestCase extends XMLObjectBaseTestCas
 	public void testChildElementsMarshall() {
         Assert.assertNull(expectedChildElementsDOM, "No testSingleElementChildElementsMarshall");
     }
+
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    public void testAttributeIDnessMarshall(final XMLObject target, final String idValue) throws MarshallingException, XMLParserException {
+        // Test marshall of newly constructed object
+        Element origDOM = XMLObjectSupport.getMarshaller(target).marshall(target);
+        Element resolvedDOM = origDOM.getOwnerDocument().getElementById(idValue);
+        Assert.assertNotNull(resolvedDOM);
+        Assert.assertTrue(origDOM.isSameNode(resolvedDOM));
+
+        // Remarshall existing DOM into new Document
+        Document newDocument = XMLObjectProviderRegistrySupport.getParserPool().newDocument();
+        origDOM = XMLObjectSupport.getMarshaller(target).marshall(target, newDocument);
+        resolvedDOM = newDocument.getElementById(idValue);
+        Assert.assertNotNull(resolvedDOM);
+        Assert.assertTrue(origDOM.isSameNode(resolvedDOM));
+
+        // Remarshall existing DOM as child of new parent Element in new Document
+        newDocument = XMLObjectProviderRegistrySupport.getParserPool().newDocument();
+        Element parent = ElementSupport.constructElement(newDocument, "urn:test:foo", "Foo", "foo");
+        ElementSupport.setDocumentElement(newDocument, parent);
+        origDOM = XMLObjectSupport.getMarshaller(target).marshall(target, parent);
+        resolvedDOM = newDocument.getElementById(idValue);
+        Assert.assertNotNull(resolvedDOM);
+        Assert.assertTrue(origDOM.isSameNode(resolvedDOM));
+    }
     
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/AssertionMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/AssertionMarshaller.java
index 39426398d..6b200eee6 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/AssertionMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/AssertionMarshaller.java
@@ -19,6 +19,7 @@ package org.opensaml.saml.saml1.core.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.saml1.core.Assertion;
 import org.w3c.dom.Element;
@@ -38,9 +39,6 @@ public class AssertionMarshaller extends AbstractSAMLObjectMarshaller {
 
         if (assertion.getID() != null) {
             domElement.setAttributeNS(null, Assertion.ID_ATTRIB_NAME, assertion.getID());
-            if (assertion.getMinorVersion() != 0) {
-                domElement.setIdAttributeNS(null, Assertion.ID_ATTRIB_NAME, true);
-            }
         }
 
         if (assertion.getIssuer() != null) {
@@ -59,4 +57,14 @@ public class AssertionMarshaller extends AbstractSAMLObjectMarshaller {
             domElement.setAttributeNS(null, Assertion.MINORVERSION_ATTRIB_NAME, "1");
         }
     }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        if (((Assertion)xmlObject).getMinorVersion() != 0) {
+            XMLObjectSupport.marshallAttributeIDness(null, Assertion.ID_ATTRIB_NAME, domElement, true);
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/AssertionUnmarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/AssertionUnmarshaller.java
index a86343281..9d5dafe18 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/AssertionUnmarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/AssertionUnmarshaller.java
@@ -19,6 +19,7 @@ package org.opensaml.saml.saml1.core.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
 import org.opensaml.saml.common.SAMLVersion;
 import org.opensaml.saml.saml1.core.Advice;
@@ -43,7 +44,7 @@ public class AssertionUnmarshaller extends AbstractSAMLObjectUnmarshaller {
         // After regular unmarshalling, check the minor version and set ID-ness if not SAML 1.0
         final Assertion assertion = (Assertion) super.unmarshall(domElement);
         if (assertion.getMinorVersion() != 0 && !Strings.isNullOrEmpty(assertion.getID())) {
-            domElement.setIdAttributeNS(null, Assertion.ID_ATTRIB_NAME, true);
+            XMLObjectSupport.marshallAttributeIDness(null, Assertion.ID_ATTRIB_NAME, domElement, true);
         }
         return assertion;
     }
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/RequestAbstractTypeMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/RequestAbstractTypeMarshaller.java
index 4bf61305a..0bf1bd244 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/RequestAbstractTypeMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/RequestAbstractTypeMarshaller.java
@@ -23,6 +23,7 @@ package org.opensaml.saml.saml1.core.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.common.SAMLVersion;
 import org.opensaml.saml.saml1.core.RequestAbstractType;
@@ -42,9 +43,6 @@ public class RequestAbstractTypeMarshaller extends AbstractSAMLObjectMarshaller
 
         if (request.getID() != null) {
             domElement.setAttributeNS(null, RequestAbstractType.ID_ATTRIB_NAME, request.getID());
-            if (request.getVersion() != SAMLVersion.VERSION_10) {
-                domElement.setIdAttributeNS(null, RequestAbstractType.ID_ATTRIB_NAME, true);
-            }
         }
 
         if (request.getIssueInstant() != null) {
@@ -57,4 +55,14 @@ public class RequestAbstractTypeMarshaller extends AbstractSAMLObjectMarshaller
         domElement.setAttributeNS(null, RequestAbstractType.MINORVERSION_ATTRIB_NAME,
                 Integer.toString(request.getVersion().getMinorVersion()));
     }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        if (((RequestAbstractType)xmlObject).getVersion() != SAMLVersion.VERSION_10) {
+            XMLObjectSupport.marshallAttributeIDness(null, RequestAbstractType.ID_ATTRIB_NAME, domElement, true);
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/RequestAbstractTypeUnmarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/RequestAbstractTypeUnmarshaller.java
index 2a9b2511a..641eec2f0 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/RequestAbstractTypeUnmarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/RequestAbstractTypeUnmarshaller.java
@@ -25,6 +25,7 @@ import javax.annotation.Nonnull;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
 import org.opensaml.saml.common.SAMLVersion;
 import org.opensaml.saml.saml1.core.RequestAbstractType;
@@ -52,7 +53,7 @@ public abstract class RequestAbstractTypeUnmarshaller extends AbstractSAMLObject
         // After regular unmarshalling, check the minor version and set ID-ness if not SAML 1.0
         final RequestAbstractType request = (RequestAbstractType) super.unmarshall(domElement);
         if (request.getVersion() != SAMLVersion.VERSION_10 && !Strings.isNullOrEmpty(request.getID())) {
-            domElement.setIdAttributeNS(null, RequestAbstractType.ID_ATTRIB_NAME, true);
+            XMLObjectSupport.marshallAttributeIDness(null, RequestAbstractType.ID_ATTRIB_NAME, domElement, true);
         }
         return request;
     }
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/ResponseAbstractTypeMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/ResponseAbstractTypeMarshaller.java
index b4f680c79..df56869e2 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/ResponseAbstractTypeMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/ResponseAbstractTypeMarshaller.java
@@ -23,6 +23,7 @@ package org.opensaml.saml.saml1.core.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.common.SAMLVersion;
 import org.opensaml.saml.saml1.core.ResponseAbstractType;
@@ -42,9 +43,6 @@ public abstract class ResponseAbstractTypeMarshaller extends AbstractSAMLObjectM
 
         if (response.getID() != null) {
             domElement.setAttributeNS(null, ResponseAbstractType.ID_ATTRIB_NAME, response.getID());
-            if (response.getVersion() != SAMLVersion.VERSION_10) {
-                domElement.setIdAttributeNS(null, ResponseAbstractType.ID_ATTRIB_NAME, true);
-            }
         }
 
         if (response.getInResponseTo() != null) {
@@ -66,4 +64,13 @@ public abstract class ResponseAbstractTypeMarshaller extends AbstractSAMLObjectM
         }
     }
 
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        if (((ResponseAbstractType)xmlObject).getVersion() != SAMLVersion.VERSION_10) {
+            XMLObjectSupport.marshallAttributeIDness(null, ResponseAbstractType.ID_ATTRIB_NAME, domElement, true);
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/ResponseAbstractTypeUnmarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/ResponseAbstractTypeUnmarshaller.java
index 0ee6d6b20..c71bd6917 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/ResponseAbstractTypeUnmarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml1/core/impl/ResponseAbstractTypeUnmarshaller.java
@@ -25,6 +25,7 @@ import javax.annotation.Nonnull;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
 import org.opensaml.saml.common.SAMLVersion;
 import org.opensaml.saml.saml1.core.ResponseAbstractType;
@@ -52,7 +53,7 @@ public abstract class ResponseAbstractTypeUnmarshaller extends AbstractSAMLObjec
         // After regular unmarshalling, check the minor version and set ID-ness if not SAML 1.0
         final ResponseAbstractType response = (ResponseAbstractType) super.unmarshall(domElement);
         if (response.getVersion() != SAMLVersion.VERSION_10 && !Strings.isNullOrEmpty(response.getID())) {
-            domElement.setIdAttributeNS(null, ResponseAbstractType.ID_ATTRIB_NAME, true);
+            XMLObjectSupport.marshallAttributeIDness(null, ResponseAbstractType.ID_ATTRIB_NAME, domElement, true);
         }
         return response;
     }
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/AssertionMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/AssertionMarshaller.java
index 39843fd13..2395cee99 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/AssertionMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/AssertionMarshaller.java
@@ -23,6 +23,7 @@ package org.opensaml.saml.saml2.core.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.saml2.core.Assertion;
 import org.w3c.dom.Element;
@@ -50,7 +51,14 @@ public class AssertionMarshaller extends AbstractSAMLObjectMarshaller {
 
         if (assertion.getID() != null) {
             domElement.setAttributeNS(null, Assertion.ID_ATTRIB_NAME, assertion.getID());
-            domElement.setIdAttributeNS(null, Assertion.ID_ATTRIB_NAME, true);
         }
     }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, Assertion.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/RequestAbstractTypeMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/RequestAbstractTypeMarshaller.java
index 78e6b1022..39274e0bd 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/RequestAbstractTypeMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/RequestAbstractTypeMarshaller.java
@@ -23,6 +23,7 @@ package org.opensaml.saml.saml2.core.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.saml2.core.RequestAbstractType;
 import org.w3c.dom.Element;
@@ -45,7 +46,6 @@ public abstract class RequestAbstractTypeMarshaller extends AbstractSAMLObjectMa
 
         if (req.getID() != null) {
             domElement.setAttributeNS(null, RequestAbstractType.ID_ATTRIB_NAME, req.getID());
-            domElement.setIdAttributeNS(null, RequestAbstractType.ID_ATTRIB_NAME, true);
         }
 
         if (req.getVersion() != null) {
@@ -66,4 +66,11 @@ public abstract class RequestAbstractTypeMarshaller extends AbstractSAMLObjectMa
         }
     }
     
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, RequestAbstractType.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/StatusResponseTypeMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/StatusResponseTypeMarshaller.java
index 155de5287..a2e5f0581 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/StatusResponseTypeMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/core/impl/StatusResponseTypeMarshaller.java
@@ -23,6 +23,7 @@ package org.opensaml.saml.saml2.core.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.saml2.core.StatusResponseType;
 import org.w3c.dom.Element;
@@ -45,7 +46,6 @@ public abstract class StatusResponseTypeMarshaller extends AbstractSAMLObjectMar
 
         if (sr.getID() != null) {
             domElement.setAttributeNS(null, StatusResponseType.ID_ATTRIB_NAME, sr.getID());
-            domElement.setIdAttributeNS(null, StatusResponseType.ID_ATTRIB_NAME, true);
         }
 
         if (sr.getInResponseTo() != null) {
@@ -69,4 +69,12 @@ public abstract class StatusResponseTypeMarshaller extends AbstractSAMLObjectMar
             domElement.setAttributeNS(null, StatusResponseType.CONSENT_ATTRIB_NAME, sr.getConsent());
         }
     }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, StatusResponseType.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/AffiliationDescriptorMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/AffiliationDescriptorMarshaller.java
index abd8a4fb9..586dcddfe 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/AffiliationDescriptorMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/AffiliationDescriptorMarshaller.java
@@ -23,6 +23,7 @@ package org.opensaml.saml.saml2.metadata.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.saml2.common.CacheableSAMLObject;
 import org.opensaml.saml.saml2.common.TimeBoundSAMLObject;
@@ -49,7 +50,6 @@ public class AffiliationDescriptorMarshaller extends AbstractSAMLObjectMarshalle
         // Set ID
         if (descriptor.getID() != null) {
             domElement.setAttributeNS(null, AffiliationDescriptor.ID_ATTRIB_NAME, descriptor.getID());
-            domElement.setIdAttributeNS(null, AffiliationDescriptor.ID_ATTRIB_NAME, true);
         }
 
         // Set the validUntil attribute
@@ -66,5 +66,14 @@ public class AffiliationDescriptorMarshaller extends AbstractSAMLObjectMarshalle
 
         marshallUnknownAttributes(descriptor, domElement);
     }
-    
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+        
+        XMLObjectSupport.marshallAttributeIDness(null, AffiliationDescriptor.ID_ATTRIB_NAME, domElement, true);
+
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntitiesDescriptorMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntitiesDescriptorMarshaller.java
index 386eb2615..4855bbe12 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntitiesDescriptorMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntitiesDescriptorMarshaller.java
@@ -18,6 +18,8 @@
 package org.opensaml.saml.saml2.metadata.impl;
 
 import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.saml2.common.CacheableSAMLObject;
 import org.opensaml.saml.saml2.common.TimeBoundSAMLObject;
@@ -32,14 +34,14 @@ import net.shibboleth.utilities.java.support.xml.AttributeSupport;
 public class EntitiesDescriptorMarshaller extends AbstractSAMLObjectMarshaller {
 
     /** {@inheritDoc} */
-    protected void marshallAttributes(final XMLObject samlElement, final Element domElement) {
+    protected void marshallAttributes(final XMLObject samlElement, final Element domElement)
+            throws MarshallingException {
 
         final EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) samlElement;
 
         // Set the ID attribute
         if (entitiesDescriptor.getID() != null) {
             domElement.setAttributeNS(null, EntitiesDescriptor.ID_ATTRIB_NAME, entitiesDescriptor.getID());
-            domElement.setIdAttributeNS(null, EntitiesDescriptor.ID_ATTRIB_NAME, true);
         }
 
         // Set the validUntil attribute
@@ -59,4 +61,12 @@ public class EntitiesDescriptorMarshaller extends AbstractSAMLObjectMarshaller {
             domElement.setAttributeNS(null, EntitiesDescriptor.NAME_ATTRIB_NAME, entitiesDescriptor.getName());
         }
     }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, EntitiesDescriptor.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorMarshaller.java
index 2c26149db..085397721 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorMarshaller.java
@@ -18,6 +18,8 @@
 package org.opensaml.saml.saml2.metadata.impl;
 
 import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.saml2.common.CacheableSAMLObject;
 import org.opensaml.saml.saml2.common.TimeBoundSAMLObject;
@@ -32,7 +34,9 @@ import net.shibboleth.utilities.java.support.xml.AttributeSupport;
 public class EntityDescriptorMarshaller extends AbstractSAMLObjectMarshaller {
 
     /** {@inheritDoc} */
-    protected void marshallAttributes(final XMLObject samlElement, final Element domElement) {
+    protected void marshallAttributes(final XMLObject samlElement, final Element domElement)
+            throws MarshallingException {
+
         final EntityDescriptor entityDescriptor = (EntityDescriptor) samlElement;
 
         // Set the entityID attribute
@@ -43,7 +47,6 @@ public class EntityDescriptorMarshaller extends AbstractSAMLObjectMarshaller {
         // Set the ID attribute
         if (entityDescriptor.getID() != null) {
             domElement.setAttributeNS(null, EntityDescriptor.ID_ATTRIB_NAME, entityDescriptor.getID());
-            domElement.setIdAttributeNS(null, EntityDescriptor.ID_ATTRIB_NAME, true);
         }
 
         // Set the validUntil attribute
@@ -60,4 +63,14 @@ public class EntityDescriptorMarshaller extends AbstractSAMLObjectMarshaller {
 
         marshallUnknownAttributes(entityDescriptor, domElement);
     }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, EntityDescriptor.ID_ATTRIB_NAME, domElement, true);
+        
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/RoleDescriptorMarshaller.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/RoleDescriptorMarshaller.java
index 34a4b9baf..df7cac366 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/RoleDescriptorMarshaller.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/metadata/impl/RoleDescriptorMarshaller.java
@@ -21,6 +21,7 @@ import java.util.List;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
 import org.opensaml.saml.saml2.common.CacheableSAMLObject;
 import org.opensaml.saml.saml2.common.TimeBoundSAMLObject;
@@ -42,7 +43,6 @@ public abstract class RoleDescriptorMarshaller extends AbstractSAMLObjectMarshal
         // Set the ID attribute
         if (roleDescriptor.getID() != null) {
             domElement.setAttributeNS(null, RoleDescriptor.ID_ATTRIB_NAME, roleDescriptor.getID());
-            domElement.setIdAttributeNS(null, RoleDescriptor.ID_ATTRIB_NAME, true);
         }
 
         // Set the validUntil attribute
@@ -77,4 +77,14 @@ public abstract class RoleDescriptorMarshaller extends AbstractSAMLObjectMarshal
 
         marshallUnknownAttributes(roleDescriptor, domElement);
     }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, RoleDescriptor.ID_ATTRIB_NAME, domElement, true);
+
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/AssertionTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/AssertionTest.java
index aa4bbcabe..3d487436d 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/AssertionTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/AssertionTest.java
@@ -21,15 +21,13 @@
 
 package org.opensaml.saml.saml1.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.Assert;
-
 import java.time.Instant;
 
 import javax.xml.namespace.QName;
 
-import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.saml1.core.Advice;
 import org.opensaml.saml.saml1.core.Assertion;
 import org.opensaml.saml.saml1.core.AttributeStatement;
@@ -37,9 +35,13 @@ import org.opensaml.saml.saml1.core.AuthenticationStatement;
 import org.opensaml.saml.saml1.core.AuthorizationDecisionStatement;
 import org.opensaml.saml.saml1.core.Conditions;
 import org.opensaml.saml.saml1.core.Statement;
+import org.testng.Assert;
+import org.testng.annotations.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
 /**
  * Test for {@link org.opensaml.saml.saml1.core.Assertion}
  */
@@ -145,6 +147,21 @@ public class AssertionTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, buildXMLObject(qname));
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(qname);
+
+        ((Assertion)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/RequestTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/RequestTest.java
index 8d8f351e7..ed3de5339 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/RequestTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/RequestTest.java
@@ -20,24 +20,24 @@
  */
 package org.opensaml.saml.saml1.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.Assert;
-
 import java.time.Instant;
 
 import javax.xml.namespace.QName;
 
-import net.shibboleth.utilities.java.support.xml.XMLParserException;
-
-import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.saml1.core.AssertionArtifact;
 import org.opensaml.saml.saml1.core.AssertionIDReference;
 import org.opensaml.saml.saml1.core.AttributeQuery;
 import org.opensaml.saml.saml1.core.Request;
+import org.testng.Assert;
+import org.testng.annotations.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
 /**
  * Test in and around the {@link org.opensaml.saml.saml1.core.Request} interface
  */
@@ -121,6 +121,21 @@ public class RequestTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, buildXMLObject(qname));
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(Request.DEFAULT_ELEMENT_NAME);
+
+        ((Request)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/ResponseTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/ResponseTest.java
index 69b4668c1..3ff3de5dc 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/ResponseTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml1/core/impl/ResponseTest.java
@@ -21,21 +21,23 @@
 
 package org.opensaml.saml.saml1.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.Assert;
-
 import java.time.Instant;
 
 import javax.xml.namespace.QName;
 
-import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.saml1.core.Assertion;
 import org.opensaml.saml.saml1.core.Response;
 import org.opensaml.saml.saml1.core.Status;
+import org.testng.Assert;
+import org.testng.annotations.Test;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
 /**
  * Test class for org.opensaml.saml.saml1.core.Response
  */
@@ -132,6 +134,21 @@ public class ResponseTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, buildXMLObject(qname));
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(Response.DEFAULT_ELEMENT_NAME);
+
+        ((Response)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ArtifactResolveTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ArtifactResolveTest.java
index b7fdb6138..a73c38d60 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ArtifactResolveTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ArtifactResolveTest.java
@@ -20,14 +20,18 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.Artifact;
 import org.opensaml.saml.saml2.core.ArtifactResolve;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -60,6 +64,21 @@ public class ArtifactResolveTest extends RequestTestBase {
         assertXMLEquals(expectedDOM, ar);
     }
     
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(ArtifactResolve.DEFAULT_ELEMENT_NAME);
+
+        ((ArtifactResolve)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+    
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ArtifactResponseTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ArtifactResponseTest.java
index 00722f7e4..f39ac00b9 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ArtifactResponseTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ArtifactResponseTest.java
@@ -20,12 +20,16 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.ArtifactResponse;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -59,6 +63,21 @@ public class ArtifactResponseTest extends StatusResponseTestBase {
         assertXMLEquals(expectedDOM, ar);
     }
     
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(ArtifactResponse.DEFAULT_ELEMENT_NAME);
+
+        ((ArtifactResponse)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+    
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AssertionIDRequestTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AssertionIDRequestTest.java
index 06235e8dc..a1087a6fc 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AssertionIDRequestTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AssertionIDRequestTest.java
@@ -20,14 +20,18 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.AssertionIDRef;
 import org.opensaml.saml.saml2.core.AssertionIDRequest;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -66,6 +70,20 @@ public class AssertionIDRequestTest extends RequestTestBase {
         assertXMLEquals(expectedDOM, req);
     }
     
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(AssertionIDRequest.DEFAULT_ELEMENT_NAME);
+
+        ((AssertionIDRequest)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
 
     /** {@inheritDoc} */
     @Test
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AssertionTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AssertionTest.java
index 79d338455..568143fb5 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AssertionTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AssertionTest.java
@@ -17,18 +17,13 @@
 
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-
-import net.shibboleth.utilities.java.support.xml.XMLParserException;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
-
 import java.time.Instant;
 
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.io.UnmarshallingException;
 import org.opensaml.saml.common.SAMLVersion;
 import org.opensaml.saml.common.xml.SAMLConstants;
@@ -40,6 +35,11 @@ import org.opensaml.saml.saml2.core.AuthzDecisionStatement;
 import org.opensaml.saml.saml2.core.Conditions;
 import org.opensaml.saml.saml2.core.Issuer;
 import org.opensaml.saml.saml2.core.Subject;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  * Test case for creating, marshalling, and unmarshalling {@link org.opensaml.saml.saml2.core.impl.AssertionImpl}.
@@ -118,6 +118,21 @@ public class AssertionTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, assertion);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(Assertion.DEFAULT_ELEMENT_NAME);
+
+        ((Assertion)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AttributeQueryTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AttributeQueryTest.java
index cdf40dee9..8bce901b8 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AttributeQueryTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AttributeQueryTest.java
@@ -20,14 +20,18 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.Attribute;
 import org.opensaml.saml.saml2.core.AttributeQuery;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -65,6 +69,20 @@ public class AttributeQueryTest extends SubjectQueryTestBase {
         assertXMLEquals(expectedDOM, query);
     }
     
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(AttributeQuery.DEFAULT_ELEMENT_NAME);
+
+        ((AttributeQuery)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
     
 
     /** {@inheritDoc} */
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthnQueryTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthnQueryTest.java
index bdbf5ca44..f6ba2e684 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthnQueryTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthnQueryTest.java
@@ -20,14 +20,18 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.AuthnQuery;
 import org.opensaml.saml.saml2.core.RequestedAuthnContext;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -67,6 +71,21 @@ public class AuthnQueryTest extends SubjectQueryTestBase {
         assertXMLEquals(expectedDOM, query);
     }
     
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(AuthnQuery.DEFAULT_ELEMENT_NAME);
+
+        ((AuthnQuery)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+    
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthnRequestTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthnRequestTest.java
index c4a671acb..7ae8eb5b7 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthnRequestTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthnRequestTest.java
@@ -20,14 +20,10 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-
-import net.shibboleth.utilities.java.support.xml.XMLParserException;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.io.UnmarshallingException;
 import org.opensaml.core.xml.schema.XSBooleanValue;
 import org.opensaml.saml.common.xml.SAMLConstants;
@@ -37,6 +33,11 @@ import org.opensaml.saml.saml2.core.NameIDPolicy;
 import org.opensaml.saml.saml2.core.RequestedAuthnContext;
 import org.opensaml.saml.saml2.core.Scoping;
 import org.opensaml.saml.saml2.core.Subject;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  * Unit test for {@link AuthnRequest}.
@@ -102,6 +103,21 @@ public class AuthnRequestTest extends RequestTestBase {
 
     }
     
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(AuthnRequest.DEFAULT_ELEMENT_NAME);
+
+        ((AuthnRequest)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+    
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthzDecisionQueryTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthzDecisionQueryTest.java
index 99577ae07..c1846de83 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthzDecisionQueryTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/AuthzDecisionQueryTest.java
@@ -20,15 +20,19 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.Action;
 import org.opensaml.saml.saml2.core.AuthzDecisionQuery;
 import org.opensaml.saml.saml2.core.Evidence;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -72,6 +76,20 @@ public class AuthzDecisionQueryTest extends SubjectQueryTestBase {
         assertXMLEquals(expectedDOM, query);
     }
     
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(AuthzDecisionQuery.DEFAULT_ELEMENT_NAME);
+
+        ((AuthzDecisionQuery)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
     
     
     /** {@inheritDoc} */
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/LogoutRequestTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/LogoutRequestTest.java
index c9578588d..c23cfa26f 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/LogoutRequestTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/LogoutRequestTest.java
@@ -20,18 +20,21 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
-
 import java.time.Instant;
 
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.LogoutRequest;
 import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.SessionIndex;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -76,6 +79,21 @@ public class LogoutRequestTest extends RequestTestBase {
         
         assertXMLEquals(expectedDOM, req);
     }
+    
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(LogoutRequest.DEFAULT_ELEMENT_NAME);
+
+        ((LogoutRequest)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
 
     /** {@inheritDoc} */
     @Test
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/LogoutResponseTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/LogoutResponseTest.java
index 78915f0df..f3bcfd9f1 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/LogoutResponseTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/LogoutResponseTest.java
@@ -20,12 +20,16 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.LogoutResponse;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -58,6 +62,21 @@ public class LogoutResponseTest extends StatusResponseTestBase {
         
         assertXMLEquals(expectedDOM, resp);
     }
+    
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(LogoutResponse.DEFAULT_ELEMENT_NAME);
+
+        ((LogoutResponse)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
 
     /** {@inheritDoc} */
     @Test
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ManageNameIDRequestTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ManageNameIDRequestTest.java
index 407fbc024..bdeb23eb0 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ManageNameIDRequestTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ManageNameIDRequestTest.java
@@ -20,15 +20,19 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.ManageNameIDRequest;
 import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.NewID;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -62,6 +66,21 @@ public class ManageNameIDRequestTest extends RequestTestBase {
         assertXMLEquals(expectedDOM, req);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(ManageNameIDRequest.DEFAULT_ELEMENT_NAME);
+
+        ((ManageNameIDRequest)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+    
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ManageNameIDResponseTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ManageNameIDResponseTest.java
index 1c76e3531..a10778814 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ManageNameIDResponseTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ManageNameIDResponseTest.java
@@ -20,12 +20,16 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.ManageNameIDResponse;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -59,6 +63,21 @@ public class ManageNameIDResponseTest extends StatusResponseTestBase {
         assertXMLEquals(expectedDOM, resp);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(ManageNameIDResponse.DEFAULT_ELEMENT_NAME);
+
+        ((ManageNameIDResponse)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+    
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/NameIDMappingRequestTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/NameIDMappingRequestTest.java
index 4232c7602..1123fd0e0 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/NameIDMappingRequestTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/NameIDMappingRequestTest.java
@@ -20,15 +20,19 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.NameIDMappingRequest;
 import org.opensaml.saml.saml2.core.NameIDPolicy;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -63,6 +67,21 @@ public class NameIDMappingRequestTest extends RequestTestBase {
         assertXMLEquals(expectedDOM, req);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(NameIDMappingRequest.DEFAULT_ELEMENT_NAME);
+
+        ((NameIDMappingRequest)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+    
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/NameIDMappingResponseTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/NameIDMappingResponseTest.java
index d1e870cf4..14099bd5b 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/NameIDMappingResponseTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/NameIDMappingResponseTest.java
@@ -20,14 +20,18 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.NameIDMappingResponse;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -62,6 +66,21 @@ public class NameIDMappingResponseTest extends StatusResponseTestBase {
         
         assertXMLEquals(expectedDOM, resp);
     }
+    
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(NameIDMappingResponse.DEFAULT_ELEMENT_NAME);
+
+        ((NameIDMappingResponse)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
 
     /** {@inheritDoc} */
     @Test
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ResponseTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ResponseTest.java
index 23880c628..8d304041e 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ResponseTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/core/impl/ResponseTest.java
@@ -20,19 +20,20 @@
  */
 package org.opensaml.saml.saml2.core.impl;
 
-import org.testng.annotations.Test;
-
-import net.shibboleth.utilities.java.support.xml.XMLParserException;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.io.UnmarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.Assertion;
 import org.opensaml.saml.saml2.core.EncryptedAssertion;
 import org.opensaml.saml.saml2.core.Response;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  * Test case for creating, marshalling, and unmarshalling
@@ -76,6 +77,21 @@ public class ResponseTest extends StatusResponseTestBase {
         
         assertXMLEquals(expectedDOM, resp);
     }
+    
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(Response.DEFAULT_ELEMENT_NAME);
+
+        ((Response)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
 
     /** {@inheritDoc} */
     @Test
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/AffiliationDescriptorTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/AffiliationDescriptorTest.java
index 98a36e649..b6bc0bffa 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/AffiliationDescriptorTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/AffiliationDescriptorTest.java
@@ -22,18 +22,22 @@ import java.time.Instant;
 
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.util.AttributeMap;
 import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml2.metadata.Extensions;
 import org.opensaml.saml.saml2.metadata.AffiliateMember;
 import org.opensaml.saml.saml2.metadata.AffiliationDescriptor;
+import org.opensaml.saml.saml2.metadata.Extensions;
 import org.opensaml.xmlsec.signature.Signature;
 import org.opensaml.xmlsec.signature.support.SignatureConstants;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
 /**
  * Test case for creating, marshalling, and unmarshalling
  * {@link org.opensaml.saml.saml2.metadata.impl.AffiliationDescriptorImpl}.
@@ -149,6 +153,22 @@ public class AffiliationDescriptorTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, descriptor);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(AffiliationDescriptor.DEFAULT_ELEMENT_NAME);
+
+        ((AffiliationDescriptor)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/EntitiesDescriptorTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/EntitiesDescriptorTest.java
index 3c51302d4..c5896d084 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/EntitiesDescriptorTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/EntitiesDescriptorTest.java
@@ -17,22 +17,25 @@
 
 package org.opensaml.saml.saml2.metadata.impl;
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
-
 import java.time.Duration;
 import java.time.Instant;
 
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml2.metadata.Extensions;
 import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.Extensions;
 import org.opensaml.xmlsec.signature.Signature;
 import org.opensaml.xmlsec.signature.support.SignatureConstants;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  * Test case for creating, marshalling, and unmarshalling
@@ -137,6 +140,22 @@ public class EntitiesDescriptorTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, entitiesDescriptor);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(EntitiesDescriptor.DEFAULT_ELEMENT_NAME);
+
+        ((EntitiesDescriptor)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorTest.java
index c9c4fed3a..bcd8551f0 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/metadata/impl/EntityDescriptorTest.java
@@ -22,16 +22,18 @@ import java.time.Instant;
 
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.util.AttributeMap;
 import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml2.metadata.Extensions;
 import org.opensaml.saml.saml2.metadata.AdditionalMetadataLocation;
 import org.opensaml.saml.saml2.metadata.AffiliationDescriptor;
 import org.opensaml.saml.saml2.metadata.AttributeAuthorityDescriptor;
 import org.opensaml.saml.saml2.metadata.AuthnAuthorityDescriptor;
 import org.opensaml.saml.saml2.metadata.ContactPerson;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.Extensions;
 import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
 import org.opensaml.saml.saml2.metadata.Organization;
 import org.opensaml.saml.saml2.metadata.PDPDescriptor;
@@ -43,6 +45,8 @@ import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
 /**
  * Test case for creating, marshalling, and unmarshalling
  * {@link org.opensaml.saml.saml2.metadata.impl.EntityDescriptorImpl}.
@@ -208,6 +212,22 @@ public class EntityDescriptorTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, descriptor);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(EntityDescriptor.DEFAULT_ELEMENT_NAME);
+
+        ((EntityDescriptor)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
+
     @Test public void testSingleElementUnknownAttributesMarshall() {
         EntityDescriptor descriptor = (new EntityDescriptorBuilder()).buildObject();
 
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/BodyMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/BodyMarshaller.java
index d9a25e162..d1cfacb05 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/BodyMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/BodyMarshaller.java
@@ -17,18 +17,11 @@
 
 package org.opensaml.soap.soap11.impl;
 
-import java.util.Map.Entry;
-
-import javax.xml.namespace.QName;
-
-import net.shibboleth.utilities.java.support.xml.AttributeSupport;
-
 import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
 import org.opensaml.core.xml.io.AbstractXMLObjectMarshaller;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.soap.soap11.Body;
-import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 
 /**
@@ -40,16 +33,7 @@ public class BodyMarshaller extends AbstractXMLObjectMarshaller {
     protected void marshallAttributes(final XMLObject xmlObject, final Element domElement) throws MarshallingException {
         final Body body = (Body) xmlObject;
 
-        Attr attribute;
-        for (final Entry<QName, String> entry : body.getUnknownAttributes().entrySet()) {
-            attribute = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey());
-            attribute.setValue(entry.getValue());
-            domElement.setAttributeNodeNS(attribute);
-            if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey()) 
-                    || body.getUnknownAttributes().isIDAttribute(entry.getKey())) {
-                attribute.getOwnerElement().setIdAttributeNode(attribute, true);
-            }
-        }
+        XMLObjectSupport.marshallAttributeMap(body.getUnknownAttributes(), domElement);
     }
 
     /** {@inheritDoc} */
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/DetailMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/DetailMarshaller.java
index 41a0f3d92..1b5c374bf 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/DetailMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/DetailMarshaller.java
@@ -17,18 +17,11 @@
 
 package org.opensaml.soap.soap11.impl;
 
-import java.util.Map.Entry;
-
-import javax.xml.namespace.QName;
-
-import net.shibboleth.utilities.java.support.xml.AttributeSupport;
-
 import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
 import org.opensaml.core.xml.io.AbstractXMLObjectMarshaller;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.soap.soap11.Detail;
-import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 
 /**
@@ -40,16 +33,7 @@ public class DetailMarshaller extends AbstractXMLObjectMarshaller {
     protected void marshallAttributes(final XMLObject xmlObject, final Element domElement) throws MarshallingException {
         final Detail detail = (Detail) xmlObject;
 
-        Attr attribute;
-        for (final Entry<QName, String> entry : detail.getUnknownAttributes().entrySet()) {
-            attribute = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey());
-            attribute.setValue(entry.getValue());
-            domElement.setAttributeNodeNS(attribute);
-            if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey()) 
-                    || detail.getUnknownAttributes().isIDAttribute(entry.getKey())) {
-                attribute.getOwnerElement().setIdAttributeNode(attribute, true);
-            }
-        }
+        XMLObjectSupport.marshallAttributeMap(detail.getUnknownAttributes(), domElement);
     }
 
     /** {@inheritDoc} */
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/EnvelopeMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/EnvelopeMarshaller.java
index f4c8aa726..10ada8ccc 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/EnvelopeMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/EnvelopeMarshaller.java
@@ -21,18 +21,11 @@
 
 package org.opensaml.soap.soap11.impl;
 
-import java.util.Map.Entry;
-
-import javax.xml.namespace.QName;
-
-import net.shibboleth.utilities.java.support.xml.AttributeSupport;
-
 import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
 import org.opensaml.core.xml.io.AbstractXMLObjectMarshaller;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.soap.soap11.Envelope;
-import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 
 /**
@@ -44,16 +37,7 @@ public class EnvelopeMarshaller extends AbstractXMLObjectMarshaller {
     protected void marshallAttributes(final XMLObject xmlObject, final Element domElement) throws MarshallingException {
         final Envelope envelope = (Envelope) xmlObject;
 
-        Attr attribute;
-        for (final Entry<QName, String> entry : envelope.getUnknownAttributes().entrySet()) {
-            attribute = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey());
-            attribute.setValue(entry.getValue());
-            domElement.setAttributeNodeNS(attribute);
-            if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey()) 
-                    || envelope.getUnknownAttributes().isIDAttribute(entry.getKey())) {
-                attribute.getOwnerElement().setIdAttributeNode(attribute, true);
-            }
-        }
+        XMLObjectSupport.marshallAttributeMap(envelope.getUnknownAttributes(), domElement);
     }
 
     /** {@inheritDoc} */
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/HeaderMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/HeaderMarshaller.java
index b614fdb66..976aa5214 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/HeaderMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/soap11/impl/HeaderMarshaller.java
@@ -17,18 +17,11 @@
 
 package org.opensaml.soap.soap11.impl;
 
-import java.util.Map.Entry;
-
-import javax.xml.namespace.QName;
-
-import net.shibboleth.utilities.java.support.xml.AttributeSupport;
-
 import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
 import org.opensaml.core.xml.io.AbstractXMLObjectMarshaller;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.soap.soap11.Header;
-import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 
 /**
@@ -40,16 +33,7 @@ public class HeaderMarshaller extends AbstractXMLObjectMarshaller {
     protected void marshallAttributes(final XMLObject xmlObject, final Element domElement) throws MarshallingException {
         final Header header = (Header) xmlObject;
 
-        Attr attribute;
-        for (final Entry<QName, String> entry : header.getUnknownAttributes().entrySet()) {
-            attribute = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey());
-            attribute.setValue(entry.getValue());
-            domElement.setAttributeNodeNS(attribute);
-            if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey()) 
-                    || header.getUnknownAttributes().isIDAttribute(entry.getKey())) {
-                attribute.getOwnerElement().setIdAttributeNode(attribute, true);
-            }
-        }
+        XMLObjectSupport.marshallAttributeMap(header.getUnknownAttributes(), domElement);
     }
 
     /** {@inheritDoc} */
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wspolicy/impl/PolicyMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wspolicy/impl/PolicyMarshaller.java
index a4499e135..0ebde540c 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wspolicy/impl/PolicyMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wspolicy/impl/PolicyMarshaller.java
@@ -45,5 +45,12 @@ public class PolicyMarshaller extends OperatorContentTypeMarshaller {
         
         XMLObjectSupport.marshallAttributeMap(policy.getUnknownAttributes(), domElement);
     }
+    
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(XMLObject xmlObject, Element domElement) throws MarshallingException {
+        XMLObjectSupport.marshallAttributeIDness(IdBearing.WSU_ID_ATTR_NAME, domElement, true);
+        
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
 
 }
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/AttributedDateTimeMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/AttributedDateTimeMarshaller.java
index 40f813c03..d79aec47e 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/AttributedDateTimeMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/AttributedDateTimeMarshaller.java
@@ -46,6 +46,13 @@ public class AttributedDateTimeMarshaller extends AbstractWSSecurityObjectMarsha
         
     }
 
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(XMLObject xmlObject, Element domElement) throws MarshallingException {
+        XMLObjectSupport.marshallAttributeIDness(AttributedDateTime.WSU_ID_ATTR_NAME, domElement, true);
+        
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
+
     /** {@inheritDoc} */
     protected void marshallElementContent(final XMLObject xmlObject, final Element domElement)
             throws MarshallingException {
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/AttributedStringMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/AttributedStringMarshaller.java
index 5e0a10839..8b261269e 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/AttributedStringMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/AttributedStringMarshaller.java
@@ -44,6 +44,13 @@ public class AttributedStringMarshaller extends AbstractWSSecurityObjectMarshall
         XMLObjectSupport.marshallAttributeMap(attributedString.getUnknownAttributes(), domElement);
         
     }
+    
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(XMLObject xmlObject, Element domElement) throws MarshallingException {
+        XMLObjectSupport.marshallAttributeIDness(AttributedString.WSU_ID_ATTR_NAME, domElement, true);
+        
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
 
     /** {@inheritDoc} */
     protected void marshallElementContent(final XMLObject xmlObject, final Element domElement)
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/EncryptedHeaderMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/EncryptedHeaderMarshaller.java
index fcdea5493..416c91b43 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/EncryptedHeaderMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/EncryptedHeaderMarshaller.java
@@ -59,5 +59,12 @@ public class EncryptedHeaderMarshaller extends AbstractWSSecurityObjectMarshalle
         
         super.marshallAttributes(xmlObject, domElement);
     }
+    
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(XMLObject xmlObject, Element domElement) throws MarshallingException {
+        XMLObjectSupport.marshallAttributeIDness(EncryptedHeader.WSU_ID_ATTR_NAME, domElement, true);
+        
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
 
 }
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/SecurityTokenReferenceMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/SecurityTokenReferenceMarshaller.java
index 6a9ec738a..81d7be770 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/SecurityTokenReferenceMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/SecurityTokenReferenceMarshaller.java
@@ -49,5 +49,12 @@ public class SecurityTokenReferenceMarshaller extends AbstractWSSecurityObjectMa
         
         XMLObjectSupport.marshallAttributeMap(str.getUnknownAttributes(), domElement);
     }
+    
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(XMLObject xmlObject, Element domElement) throws MarshallingException {
+        XMLObjectSupport.marshallAttributeIDness(SecurityTokenReference.WSU_ID_ATTR_NAME, domElement, true);
+        
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
 
 }
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/SignatureConfirmationMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/SignatureConfirmationMarshaller.java
index 1b818d016..d4079c9f3 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/SignatureConfirmationMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/SignatureConfirmationMarshaller.java
@@ -41,5 +41,12 @@ public class SignatureConfirmationMarshaller extends AbstractWSSecurityObjectMar
             domElement.setAttributeNS(null, SignatureConfirmation.VALUE_ATTRIB_NAME, sc.getValue());
         }
     }
+    
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(XMLObject xmlObject, Element domElement) throws MarshallingException {
+        XMLObjectSupport.marshallAttributeIDness(SignatureConfirmation.WSU_ID_ATTR_NAME, domElement, true);
+        
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
 
 }
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/TimestampMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/TimestampMarshaller.java
index 63d388b85..af2ede57f 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/TimestampMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/TimestampMarshaller.java
@@ -41,5 +41,12 @@ public class TimestampMarshaller extends AbstractWSSecurityObjectMarshaller {
         
         XMLObjectSupport.marshallAttributeMap(timestamp.getUnknownAttributes(), domElement);
     }
+    
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(XMLObject xmlObject, Element domElement) throws MarshallingException {
+        XMLObjectSupport.marshallAttributeIDness(Timestamp.WSU_ID_ATTR_NAME, domElement, true);
+        
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
 
 }
diff --git a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/UsernameTokenMarshaller.java b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/UsernameTokenMarshaller.java
index 8d3101e14..876a91c69 100644
--- a/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/UsernameTokenMarshaller.java
+++ b/opensaml-soap-impl/src/main/java/org/opensaml/soap/wssecurity/impl/UsernameTokenMarshaller.java
@@ -42,5 +42,12 @@ public class UsernameTokenMarshaller extends AbstractWSSecurityObjectMarshaller
         XMLObjectSupport.marshallAttributeMap(usernameToken.getUnknownAttributes(), domElement);
         
     }
+    
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(XMLObject xmlObject, Element domElement) throws MarshallingException {
+        XMLObjectSupport.marshallAttributeIDness(UsernameToken.WSU_ID_ATTR_NAME, domElement, true);
+        
+        super.marshallAttributeIDness(xmlObject, domElement);
+    }
 
 }
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptedTypeMarshaller.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptedTypeMarshaller.java
index 0c2dc6e1b..8dc529fea 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptedTypeMarshaller.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptedTypeMarshaller.java
@@ -19,6 +19,7 @@ package org.opensaml.xmlsec.encryption.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.xmlsec.encryption.EncryptedType;
 import org.w3c.dom.Element;
 
@@ -33,7 +34,6 @@ public abstract class EncryptedTypeMarshaller extends AbstractXMLEncryptionMarsh
 
         if (et.getID() != null) {
             domElement.setAttributeNS(null, EncryptedType.ID_ATTRIB_NAME, et.getID());
-            domElement.setIdAttributeNS(null, EncryptedType.ID_ATTRIB_NAME, true);
         }
 
         if (et.getType() != null) {
@@ -50,4 +50,11 @@ public abstract class EncryptedTypeMarshaller extends AbstractXMLEncryptionMarsh
 
     }
 
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, EncryptedType.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertiesMarshaller.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertiesMarshaller.java
index 97d562953..69668913e 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertiesMarshaller.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertiesMarshaller.java
@@ -19,6 +19,7 @@ package org.opensaml.xmlsec.encryption.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.xmlsec.encryption.EncryptionProperties;
 import org.w3c.dom.Element;
 
@@ -33,9 +34,15 @@ public class EncryptionPropertiesMarshaller extends AbstractXMLEncryptionMarshal
 
         if (ep.getID() != null) {
             domElement.setAttributeNS(null, EncryptionProperties.ID_ATTRIB_NAME, ep.getID());
-            domElement.setIdAttributeNS(null, EncryptionProperties.ID_ATTRIB_NAME, true);
         }
 
     }
 
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, EncryptionProperties.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertyMarshaller.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertyMarshaller.java
index fbd1aeb51..b15d4aa66 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertyMarshaller.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertyMarshaller.java
@@ -17,17 +17,10 @@
 
 package org.opensaml.xmlsec.encryption.impl;
 
-import java.util.Map.Entry;
-
-import javax.xml.namespace.QName;
-
-import net.shibboleth.utilities.java.support.xml.AttributeSupport;
-
 import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.xmlsec.encryption.EncryptionProperty;
-import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 
 /**
@@ -41,22 +34,23 @@ public class EncryptionPropertyMarshaller extends AbstractXMLEncryptionMarshalle
 
         if (ep.getID() != null) {
             domElement.setAttributeNS(null, EncryptionProperty.ID_ATTRIB_NAME, ep.getID());
-            domElement.setIdAttributeNS(null, EncryptionProperty.ID_ATTRIB_NAME, true);
         }
         if (ep.getTarget() != null) {
             domElement.setAttributeNS(null, EncryptionProperty.TARGET_ATTRIB_NAME, ep.getTarget());
         }
 
-        Attr attribute;
-        for (final Entry<QName, String> entry : ep.getUnknownAttributes().entrySet()) {
-            attribute = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey());
-            attribute.setValue(entry.getValue());
-            domElement.setAttributeNodeNS(attribute);
-            if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey())
-                    || ep.getUnknownAttributes().isIDAttribute(entry.getKey())) {
-                attribute.getOwnerElement().setIdAttributeNode(attribute, true);
-            }
-        }
+        XMLObjectSupport.marshallAttributeMap(ep.getUnknownAttributes(), domElement);
+    }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        final EncryptionProperty ep = (EncryptionProperty) xmlObject;
+
+        XMLObjectSupport.marshallAttributeIDness(null, EncryptionProperty.ID_ATTRIB_NAME, domElement, true);
+
+        super.marshallAttributeIDness(xmlObject, domElement);
     }
 
 }
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/DEREncodedKeyValueMarshaller.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/DEREncodedKeyValueMarshaller.java
index d8a3cf94a..5436254bb 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/DEREncodedKeyValueMarshaller.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/DEREncodedKeyValueMarshaller.java
@@ -20,6 +20,7 @@ package org.opensaml.xmlsec.signature.impl;
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.schema.impl.XSBase64BinaryMarshaller;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.xmlsec.signature.DEREncodedKeyValue;
 import org.w3c.dom.Element;
 
@@ -34,8 +35,14 @@ public class DEREncodedKeyValueMarshaller extends XSBase64BinaryMarshaller {
 
         if (der.getID() != null) {
             domElement.setAttributeNS(null, DEREncodedKeyValue.ID_ATTRIB_NAME, der.getID());
-            domElement.setIdAttributeNS(null, DEREncodedKeyValue.ID_ATTRIB_NAME, true);
         }
     }
 
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, DEREncodedKeyValue.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/ECKeyValueMarshaller.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/ECKeyValueMarshaller.java
index 977c7f62a..1313732b6 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/ECKeyValueMarshaller.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/ECKeyValueMarshaller.java
@@ -19,6 +19,7 @@ package org.opensaml.xmlsec.signature.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.xmlsec.signature.ECKeyValue;
 import org.w3c.dom.Element;
 
@@ -33,8 +34,14 @@ public class ECKeyValueMarshaller extends AbstractXMLSignatureMarshaller {
 
         if (ec.getID() != null) {
             domElement.setAttributeNS(null, ECKeyValue.ID_ATTRIB_NAME, ec.getID());
-            domElement.setIdAttributeNS(null, ECKeyValue.ID_ATTRIB_NAME, true);
         }
     }
-    
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, ECKeyValue.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/KeyInfoMarshaller.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/KeyInfoMarshaller.java
index dd3cd9199..ea3863fe3 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/KeyInfoMarshaller.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/KeyInfoMarshaller.java
@@ -19,6 +19,7 @@ package org.opensaml.xmlsec.signature.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.xmlsec.signature.KeyInfo;
 import org.w3c.dom.Element;
 
@@ -33,8 +34,14 @@ public class KeyInfoMarshaller extends AbstractXMLSignatureMarshaller {
 
         if (keyInfo.getID() != null) {
             domElement.setAttributeNS(null, KeyInfo.ID_ATTRIB_NAME, keyInfo.getID());
-            domElement.setIdAttributeNS(null, KeyInfo.ID_ATTRIB_NAME, true);
         }
     }
 
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, KeyInfo.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/KeyInfoReferenceMarshaller.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/KeyInfoReferenceMarshaller.java
index 2ba84c43e..c9a3f37ba 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/KeyInfoReferenceMarshaller.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/signature/impl/KeyInfoReferenceMarshaller.java
@@ -19,6 +19,7 @@ package org.opensaml.xmlsec.signature.impl;
 
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.xmlsec.signature.KeyInfoReference;
 import org.w3c.dom.Element;
 
@@ -33,11 +34,18 @@ public class KeyInfoReferenceMarshaller extends AbstractXMLSignatureMarshaller {
 
         if (ref.getID() != null) {
             domElement.setAttributeNS(null, KeyInfoReference.ID_ATTRIB_NAME, ref.getID());
-            domElement.setIdAttributeNS(null, KeyInfoReference.ID_ATTRIB_NAME, true);
         }
 
         if (ref.getURI() != null) {
             domElement.setAttributeNS(null, KeyInfoReference.URI_ATTRIB_NAME, ref.getURI());
         }
     }
+
+    /** {@inheritDoc} */
+    protected void marshallAttributeIDness(final XMLObject xmlObject, final Element domElement)
+            throws MarshallingException {
+
+        XMLObjectSupport.marshallAttributeIDness(null, KeyInfoReference.ID_ATTRIB_NAME, domElement, true);
+    }
+
 }
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptedDataTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptedDataTest.java
index 03508639e..1b1b0d8a6 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptedDataTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptedDataTest.java
@@ -18,15 +18,19 @@
 package org.opensaml.xmlsec.encryption.impl;
 
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.xmlsec.encryption.CipherData;
 import org.opensaml.xmlsec.encryption.EncryptedData;
 import org.opensaml.xmlsec.encryption.EncryptionMethod;
 import org.opensaml.xmlsec.encryption.EncryptionProperties;
 import org.opensaml.xmlsec.signature.KeyInfo;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -105,6 +109,21 @@ public class EncryptedDataTest extends XMLObjectProviderBaseTestCase {
         
         assertXMLEquals(expectedDOM, ed);
     }
+    
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(EncryptedData.DEFAULT_ELEMENT_NAME);
+
+        ((EncryptedData)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
 
     /** {@inheritDoc} */
     @Test
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptedKeyTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptedKeyTest.java
index 9a66d6fc9..07391f559 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptedKeyTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptedKeyTest.java
@@ -18,10 +18,9 @@
 package org.opensaml.xmlsec.encryption.impl;
 
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.xmlsec.encryption.CarriedKeyName;
 import org.opensaml.xmlsec.encryption.CipherData;
 import org.opensaml.xmlsec.encryption.EncryptedKey;
@@ -29,6 +28,11 @@ import org.opensaml.xmlsec.encryption.EncryptionMethod;
 import org.opensaml.xmlsec.encryption.EncryptionProperties;
 import org.opensaml.xmlsec.encryption.ReferenceList;
 import org.opensaml.xmlsec.signature.KeyInfo;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -114,6 +118,21 @@ public class EncryptedKeyTest extends XMLObjectProviderBaseTestCase {
         
         assertXMLEquals(expectedDOM, ek);
     }
+    
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(EncryptedKey.DEFAULT_ELEMENT_NAME);
+
+        ((EncryptedKey)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
 
     /** {@inheritDoc} */
     @Test
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertiesTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertiesTest.java
index 4accba5c2..6067ff354 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertiesTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertiesTest.java
@@ -18,12 +18,16 @@
 package org.opensaml.xmlsec.encryption.impl;
 
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.xmlsec.encryption.EncryptionProperties;
 import org.opensaml.xmlsec.encryption.EncryptionProperty;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -90,6 +94,22 @@ public class EncryptionPropertiesTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, ep);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(EncryptionProperties.DEFAULT_ELEMENT_NAME);
+
+        ((EncryptionProperties)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertyTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertyTest.java
index 9af221ebb..37b57454f 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertyTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/impl/EncryptionPropertyTest.java
@@ -18,14 +18,18 @@
 package org.opensaml.xmlsec.encryption.impl;
 
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
 import javax.xml.namespace.QName;
 
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.mock.SimpleXMLObject;
 import org.opensaml.xmlsec.encryption.EncryptionProperty;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -113,6 +117,21 @@ public class EncryptionPropertyTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, ep);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(EncryptionProperty.DEFAULT_ELEMENT_NAME);
+
+        ((EncryptionProperty)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/DEREncodedKeyValueTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/DEREncodedKeyValueTest.java
index 632198f15..f4b0000c3 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/DEREncodedKeyValueTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/DEREncodedKeyValueTest.java
@@ -18,12 +18,16 @@
 package org.opensaml.xmlsec.signature.impl;
 
 
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.xmlsec.signature.DEREncodedKeyValue;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
 /**
  *
  */
@@ -77,6 +81,21 @@ public class DEREncodedKeyValueTest extends XMLObjectProviderBaseTestCase {
         
         assertXMLEquals(expectedDOM, der);
     }
+
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(DEREncodedKeyValue.DEFAULT_ELEMENT_NAME);
+
+        ((DEREncodedKeyValue)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
     
     /** {@inheritDoc} */
     @Test
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/ECKeyValueTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/ECKeyValueTest.java
index 182e4f28c..3023896bf 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/ECKeyValueTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/ECKeyValueTest.java
@@ -18,7 +18,9 @@
 package org.opensaml.xmlsec.signature.impl;
 
 
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.xmlsec.signature.ECKeyValue;
 import org.opensaml.xmlsec.signature.NamedCurve;
 import org.opensaml.xmlsec.signature.PublicKey;
@@ -26,6 +28,8 @@ import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
 /**
  *
  */
@@ -88,6 +92,21 @@ public class ECKeyValueTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, keyValue);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(ECKeyValue.DEFAULT_ELEMENT_NAME);
+
+        ((ECKeyValue)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/KeyInfoReferenceTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/KeyInfoReferenceTest.java
index 6aea49a00..0d1c07603 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/KeyInfoReferenceTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/KeyInfoReferenceTest.java
@@ -18,10 +18,15 @@
 package org.opensaml.xmlsec.signature.impl;
 
 
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.xmlsec.signature.KeyInfoReference;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -72,6 +77,21 @@ public class KeyInfoReferenceTest extends XMLObjectProviderBaseTestCase {
         
         assertXMLEquals(expectedDOM, ref);
     }
+
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(KeyInfoReference.DEFAULT_ELEMENT_NAME);
+
+        ((KeyInfoReference)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
     
     /** {@inheritDoc} */
     public void testSingleElementOptionalAttributesMarshall() {
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/KeyInfoTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/KeyInfoTest.java
index 0b8c260e1..20297bcf0 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/KeyInfoTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/impl/KeyInfoTest.java
@@ -18,10 +18,9 @@
 package org.opensaml.xmlsec.signature.impl;
 
 
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.Assert;
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.XMLObjectProviderBaseTestCase;
+import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.mock.SimpleXMLObject;
 import org.opensaml.xmlsec.signature.KeyInfo;
 import org.opensaml.xmlsec.signature.KeyName;
@@ -31,6 +30,11 @@ import org.opensaml.xmlsec.signature.PGPData;
 import org.opensaml.xmlsec.signature.RetrievalMethod;
 import org.opensaml.xmlsec.signature.SPKIData;
 import org.opensaml.xmlsec.signature.X509Data;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
 
 /**
  *
@@ -101,6 +105,21 @@ public class KeyInfoTest extends XMLObjectProviderBaseTestCase {
         assertXMLEquals(expectedDOM, keyInfo);
     }
 
+    /**
+     * Test marshalling of attribute IDness.
+     *
+     * @throws MarshallingException
+     * @throws XMLParserException
+     * */
+    @Test
+    public void testAttributeIDnessMarshall() throws MarshallingException, XMLParserException {
+        XMLObject target = buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);
+
+        ((KeyInfo)target).setID("id123");
+
+        testAttributeIDnessMarshall(target, "id123");
+    }
+
     /** {@inheritDoc} */
     @Test
     public void testSingleElementOptionalAttributesMarshall() {

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list