A couple of elements within the SAML schema are defined with a special, wildcard, type known as an
anyType . These elements can take any valid XML as content which translates to the SAMLObjects representing those element allowing any XMLObject as a child. Specifically these are, in SAML 1.X:
StatusDetail and in SAML 2.0:
StatusResponse, and all the metadata endpoint elements.
Adding Content to
Every SAMLObject representing an XML element of type
org.opensaml.xml.ElementExtensibleXMLObject which defines the method
getUnknownXMLObjects() . XMLObjects representing the content to be added to the SAMLObject should be added to the list returned by this method. These child objects will then be marshalled as any other children object.
Building XMLObjects for use as content works a bit differently than the normal method for building objects, because some child elements are expected to have a specific name (e.g. AttributeValue) but can still contain any valid XML. To build the XMLObject in this case get the builder for the XMLObject as you normally would, but instead of invoking
buildObject() you need to use either
buildObject(String, String, String) or
builidObject(QName) to override the default element name. It's also good practice to explicitly state the schema type of this object as it makes it easier for the receiver of the message to parse it. To do this pass in a
QName that represents the schema type in as an additional, final, argument to the methods just discussed. All the objects in the OpenSAML library, on their interface, define a static
QName called TYPE_NAME that can be used as this argument.
Reading Content of
getUnknownXMLObjects() provides access to the unknown content of SAMLObjects defined with the
any type. Reading information from this list can be problematic if you're not exactly sure what is in the returned list. If, during the unmarshalling process, the library encountered an element whose xsi:type or element name was not recognized (i.e. was not explicitly listed in the OpenSAML configuration files) the library will unmarshall the element into the
org.opensaml.xml.ElementProxy XMLObject. No information is lost, but if you were expecting to cast the object to a specific SAMLObject interface you'll receive a class cast exception when you try. If the library understands the element or element type, though, it is safe to cast it to the respecting interface.
Probably the most commonly encountered example of this is the
AttributeValue element. There is an AttributeValue interface but nothing implements it, which means you can't cast classes to it. It exists simply to hold name constants which may be used when building other XMLObjects via the
XMLObjectBuilder#buildObject(String, String, String) or
Here's an example of an
AttributeValue that carries string content. The
AttributeValue element will express an
Here's an example of an
AttributeValue that carries element content. An
XSAny object is used to represent the
AttributeValue, in order to allow the addition of element children. The
Role child element in the example is also represented by an
XSAny. Another and more correct approach would be to implement XML object provider support for the
When marshalled and serialized, this produces the following XML: