xmlbeans and dom3

Fri, Apr 14, 2006

Why do I need DOM3 support? Well, I’m handling SAML and WS-Security using XMLBeans and I want to sign a SAML Assertion which is in a WSS Security SOAP header. The problem is that the SAML1.1 Assertion has a non standard ID attributed, “AssertionID”, so when I try to sign the element, XMLSignature throws an exception:

org.apache.xml.security.signature.XMLSignatureException: Cannot resolve element with ID _c7055387-af61-4fce-8b98-e2927324b306

i.e. <Assertion AssertionID="_c7055387-af61-4fce-8b98-e2927324b306" … />

isn’t recognised as having an ID attribute, AssertionID. So, I need to make it one but I can only do that with DOM3 and it seems that XMLBeans doesn’t support DOM3.

This will throw java.lang.RuntimeException: DOM Level 3 Not implemented

AssertionDocument assertionDoc = AssertionDocument.Factory.parse(new File(“xml/assertion.xml”), loadOptions); AssertionType assertion = assertionDoc.getAssertion(); Element e = (Element)assertionDoc.getDomNode().getFirstChild(); e.setIdAttribute(“AssertionID”, true);

Even loading an instance document using:

XmlOptions loadOptions = new XmlOptions(); XMLReader xerces = XMLReaderFactory.createXMLReader(“org.apache.xerces.parsers.SAXParser”); loadOptions.setLoadUseXMLReader(xerces); AssertionDocument assertionDoc = AssertionDocument.Factory.parse(new File(“xml/assertion.xml”), loadOptions);

does nothing for DOM3. So the workaround I cobbled together was to switch out to org.w3c land, do the DOM3 stuff and switch back to bean land.

// Set up the parser we’ll use for DOM3 support DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // This is crucial. If it’s not namespace aware we can’t get back to bean land factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder();

// Load up the SAML Response containing the Assertion AssertionDocument assertionDoc = AssertionDocument.Factory.parse(new File(“xml/assertion.xml”), loadOptions);

// Switch to org.w3c land Document doc = builder.parse(new InputSource(new StringReader(assertionDoc.toString()))); // Set up the required ID attribute using DOM3 support doc.getDocumentElement().setIdAttribute(“AssertionID”, true); // … do XMLSignature stuff with doc … // Switch back to bean land assertionDoc = AssertionDocument.Factory.parse(doc.getDocumentElement());

Hey presto a digitally signed XMLBean!

comments powered by Disqus