Creating SAML objects from an XML source is done through a process known as unmarshalling which operates on DOM Elements. The OpenSAML 2 library contains unmarshalling support for known types and elements within its implementation classes, and the appropriate one is selected based off of either the XML Schema type of the Element to be unmarshalled or the Element's QName (a tuple representing the namespace the element is in and the element's name).
Unmarshalling is part of the core XMLObject interface. As a result, you can unmarshall either against a constructed (but empty) XMLObject, or using XMLObjectBuilder
methods that take DOM elements or DOM documents. The document can be bound during this process as well, to control which XMLObject instance is responsible for freeing the document.
ParserPool::parse()
to construct a DOM representation of the document. Both schema-aware (validating) or non-validating parser pools can be used. The SAMLConfig
class includes methods for accessing both kinds of pools. The pool API improves efficiency by reusing parser instances for you.XMLObjectBuilder::getBuilder(const DOMElement*)
method. The element argument is the root element from which you wish to begin unmarshalling. This is normally the document element if you're unmarshalling data from a file.buildFromElement(DOMElement*)
or buildFromDocument(DOMDocument*)
method on the returned XMLObjectBuilder
. Alternatively, just build an empty object and use its unmarshall() methods directly. Usually the builder methods are easier to use.By default, building from a DOMDocument will bind the document to the root object returned, and document ownership is transferred to the object. You must free the resulting XMLObject, but the document will be freed automatically when the bound object is. Building from an element does not bind the owning document by default, but this can be overridden.
The following example shows the parsing and unmarshalling of a SAML 2 metadata document. Exception handling code has been omitted here for readability, but the example does show how to protect the application from leaks by wrapping the DOMDocument in a janitor class before unmarshalling. If that results in an error, the document will be freed for you. Otherwise, the documentis released from the janitor after unmarshalling succeeds.
// Parse metadata file string inCommonMDFile = "/data/org/opensaml/saml2/metadata/InCommon-metadata.xml"; ifstream in(inCommonMDFile); DOMDocument* inCommonMDDoc = XMLToolingConfig::getConfig()->getParser().parse(in); XercesJanitor<DOMDocument> janitor(inCommonMDDoc); // Get apropriate builder. const XMLObjectBuilder* builder=XMLObjectBuilder::getBuilder(inCommonMDDoc->getDocumentElement()); // Unmarshall using the document, an EntitiesDescriptor in this case. XMLObject* xo=builder->buildFromDocument(inCommonMDDoc); janitor.release(); EntitiesDescriptor* inCommonMD = dynamic_cast<EntitiesDescriptor*>(xo); |
After all that, only inCommonMD
(or xo
) needs to be deleted when you're done with it. If an exception is thrown, nothing will leak.
xsi:type
attribute. If it does, the factory attempts to lookup a builder for that schema type. If the element does not have a specified schema type, or no builder is registered for that schema type, the system uses the element's name.