Example usage for org.w3c.dom Element getElementsByTagNameNS

List of usage examples for org.w3c.dom Element getElementsByTagNameNS

Introduction

In this page you can find the example usage for org.w3c.dom Element getElementsByTagNameNS.

Prototype

public NodeList getElementsByTagNameNS(String namespaceURI, String localName) throws DOMException;

Source Link

Document

Returns a NodeList of all the descendant Elements with a given local name and namespace URI in document order.

Usage

From source file:org.apache.ws.security.message.UsernameTokenTest.java

/**
 * A test for sending a nonce with a bad encoding type in the UsernameToken
 *///from   w w w .  j  a  v  a 2  s . co m
@org.junit.Test
public void testNonceBadEncodingType() throws Exception {
    WSSecUsernameToken builder = new WSSecUsernameToken();
    builder.setPasswordType(WSConstants.PASSWORD_DIGEST);
    builder.setUserInfo("wernerd", "verySecret");

    Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
    WSSecHeader secHeader = new WSSecHeader();
    secHeader.insertSecurityHeader(doc);
    Document utDoc = builder.build(doc, secHeader);

    //
    // Manually find the Nonce node and duplicate it
    //
    org.w3c.dom.Element elem = builder.getUsernameTokenElement();
    org.w3c.dom.NodeList list = elem.getElementsByTagNameNS(WSConstants.WSSE_NS, "Nonce");
    org.w3c.dom.Node nonceNode = list.item(0);
    ((org.w3c.dom.Element) nonceNode).setAttributeNS(null, "EncodingType", "http://bad_encoding_type");

    if (LOG.isDebugEnabled()) {
        String outputString = org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(utDoc);
        LOG.debug(outputString);
    }

    WSSecurityEngine newEngine = new WSSecurityEngine();
    try {
        newEngine.processSecurityHeader(doc, null, callbackHandler, null);
        fail("Expected failure as it is not BSP compliant");
    } catch (WSSecurityException ex) {
        // expected
    }
    WSSConfig config = WSSConfig.getNewInstance();
    config.setWsiBSPCompliant(false);
    newEngine.setWssConfig(config);
    newEngine.processSecurityHeader(doc, null, callbackHandler, null);
}

From source file:org.apache.ws.security.saml.SamlNegativeTest.java

/**
 * Test that creates, sends and processes a signed SAML 2 sender-vouches
 * authentication assertion. The assertion is altered and so the signature validation
 * should fail./*  ww  w  . j a  va 2  s .c o  m*/
 */
@org.junit.Test
public void testSAML2AuthnAssertionModified() throws Exception {
    SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
    callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
    callbackHandler.setConfirmationMethod(SAML2Constants.CONF_SENDER_VOUCHES);
    callbackHandler.setIssuer("www.example.com");

    SAMLParms samlParms = new SAMLParms();
    samlParms.setCallbackHandler(callbackHandler);
    AssertionWrapper assertion = new AssertionWrapper(samlParms);

    WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
    wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);

    Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
    WSSecHeader secHeader = new WSSecHeader();
    secHeader.insertSecurityHeader(doc);

    Document signedDoc = wsSign.build(doc, null, assertion, userCrypto, "wss40", "security", secHeader);

    //
    // Modify the assertion
    //
    Element envelope = signedDoc.getDocumentElement();
    NodeList list = envelope.getElementsByTagNameNS(WSConstants.SAML2_NS, "Assertion");
    Element assertionElement = (org.w3c.dom.Element) list.item(0);
    assertionElement.setAttributeNS(null, "MinorVersion", "5");

    if (LOG.isDebugEnabled()) {
        LOG.debug("SAML 2 Authn Assertion (sender vouches):");
        String outputString = org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
        LOG.debug(outputString);
    }

    try {
        verify(signedDoc, trustCrypto);
        fail("Failure expected on a modified SAML Assertion");
    } catch (Exception ex) {
        // expected
    }
}

From source file:org.apache.ws.security.saml.SamlNegativeTest.java

/**
 * Test that creates a signed SAML 1.1 Assertion using HOK, but then modifies the signature
 * object by replacing the enveloped transform with the exclusive c14n transform. 
 * The signature validation should then fail - the enveloped transform is mandatory for
 * a signed assertion.//  w  w w  .ja  v a2s .  c om
 */
@org.junit.Test
public void testSAML1SignedKeyHolderSigModified() throws Exception {
    SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
    callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
    callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
    callbackHandler.setIssuer("www.example.com");

    SAMLParms samlParms = new SAMLParms();
    samlParms.setCallbackHandler(callbackHandler);
    AssertionWrapper assertion = new AssertionWrapper(samlParms);
    assertion.signAssertion("wss40_server", "security", issuerCrypto, false);

    WSSecSAMLToken wsSign = new WSSecSAMLToken();

    Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
    WSSecHeader secHeader = new WSSecHeader();
    secHeader.insertSecurityHeader(doc);

    Document signedDoc = wsSign.build(doc, assertion, secHeader);

    //
    // Modify the assertion
    //
    Element envelope = signedDoc.getDocumentElement();
    NodeList list = envelope.getElementsByTagNameNS(WSConstants.SAML_NS, "Assertion");
    Element assertionElement = (org.w3c.dom.Element) list.item(0);
    list = assertionElement.getElementsByTagNameNS(WSConstants.SIG_NS, "Signature");
    Element sigElement = (org.w3c.dom.Element) list.item(0);
    list = sigElement.getElementsByTagNameNS(WSConstants.SIG_NS, "Transform");
    Element transformElement = (org.w3c.dom.Element) list.item(0);
    transformElement.setAttributeNS(null, "Algorithm", WSConstants.C14N_EXCL_OMIT_COMMENTS);

    if (LOG.isDebugEnabled()) {
        LOG.debug("Signed (modified) SAML message (key holder):");
        String outputString = org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
        LOG.debug(outputString);
    }

    try {
        verify(signedDoc, trustCrypto);
        fail("Expected failure on a modified signature");
    } catch (WSSecurityException ex) {
        // expected
    }
}

From source file:org.apache.ws.security.saml.SamlNegativeTest.java

/**
 * Test that creates a signed SAML 2 Assertion using HOK, but then modifies the assertion.
 * The signature verification should then fail.
 *//*from www. j a v  a  2s  .com*/
@org.junit.Test
public void testSAML2SignedKeyHolderKeyModified() throws Exception {
    SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
    callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
    callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
    callbackHandler.setIssuer("www.example.com");

    SAMLParms samlParms = new SAMLParms();
    samlParms.setCallbackHandler(callbackHandler);
    AssertionWrapper assertion = new AssertionWrapper(samlParms);
    assertion.signAssertion("wss40_server", "security", issuerCrypto, false);

    WSSecSAMLToken wsSign = new WSSecSAMLToken();

    Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
    WSSecHeader secHeader = new WSSecHeader();
    secHeader.insertSecurityHeader(doc);

    Document signedDoc = wsSign.build(doc, assertion, secHeader);
    //
    // Modify the assertion
    //
    Element envelope = signedDoc.getDocumentElement();
    NodeList list = envelope.getElementsByTagNameNS(WSConstants.SAML2_NS, "Assertion");
    Element assertionElement = (org.w3c.dom.Element) list.item(0);
    assertionElement.setAttributeNS(null, "MinorVersion", "5");

    if (LOG.isDebugEnabled()) {
        LOG.debug("Signed (modified) SAML message (key holder):");
        String outputString = org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
        LOG.debug(outputString);
    }

    try {
        verify(signedDoc, trustCrypto);
        fail("Expected failure on a modified signature");
    } catch (WSSecurityException ex) {
        // expected
    }
}

From source file:org.apache.ws.security.saml.SamlReferenceTest.java

/**
 * WS-Security Test Case for WSS-178 - "signature verification failure of signed saml token
 * due to "The Reference for URI (bst-saml-uri) has no XMLSignatureInput".
 * //from w w  w.  j a  v a 2s  .  c o m
 * The problem is that the signature is referring to a SecurityTokenReference via the 
 * STRTransform, which in turn is referring to the SAML Assertion. The request is putting 
 * the SAML Assertion below the SecurityTokenReference, and this is causing 
 * SecurityTokenReference.getTokenElement to fail.
 */
@org.junit.Test
public void testAssertionBelowSTR() throws Exception {
    Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
    WSSecHeader secHeader = new WSSecHeader();
    secHeader.insertSecurityHeader(doc);

    SAMLIssuer saml = SAMLIssuerFactory.getInstance("saml_sv.properties");
    AssertionWrapper assertion = saml.newAssertion();
    Crypto crypto = CryptoFactory.getInstance("crypto.properties");
    WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
    wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
    Document samlDoc = wsSign.build(doc, null, assertion, crypto, "16c73ab6-b892-458f-abf5-2f875f74882e",
            "security", secHeader);

    WSSecEncrypt builder = new WSSecEncrypt();
    builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
    builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
    Document encryptedDoc = builder.build(samlDoc, crypto, secHeader);

    //
    // Remove the assertion its place in the security header and then append it
    //
    org.w3c.dom.Element secHeaderElement = secHeader.getSecurityHeader();
    org.w3c.dom.Node assertionNode = secHeaderElement.getElementsByTagNameNS(WSConstants.SAML_NS, "Assertion")
            .item(0);
    secHeaderElement.removeChild(assertionNode);
    secHeaderElement.appendChild(assertionNode);

    String outputString = org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
    if (LOG.isDebugEnabled()) {
        LOG.debug("Encrypted message:");
        LOG.debug(outputString);
    }
    assertTrue(outputString.contains(WSConstants.WSS_SAML_KI_VALUE_TYPE));
    assertTrue(outputString.contains(WSConstants.WSS_SAML_TOKEN_TYPE));

    verify(encryptedDoc, crypto, crypto);
}

From source file:org.apache.ws.security.saml.SAMLUtil.java

/**
 * Extract certificates or the key available in the SAMLAssertion
 * @param elem//from w w  w. ja  va 2  s  .  c o  m
 * @return the SAML Key Info
 * @throws WSSecurityException
 */
public static SAMLKeyInfo getSAMLKeyInfo(Element elem, Crypto crypto, CallbackHandler cb)
        throws WSSecurityException {
    SAMLAssertion assertion;
    try {
        // Check for duplicate saml:Assertion
        NodeList list = elem.getElementsByTagNameNS(WSConstants.SAML_NS, "Assertion");
        if (list != null && list.getLength() > 0) {
            throw new WSSecurityException("invalidSAMLSecurity");
        }
        assertion = new SAMLAssertion(elem);
        return getSAMLKeyInfo(assertion, crypto, cb);
    } catch (SAMLException e) {
        throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLToken",
                new Object[] { "for Signature (cannot parse)" }, e);
    }

}

From source file:org.apache.ws.security.util.WSSecurityUtil.java

/**
 * Returns the first WS-Security header element for a given actor. Only one
 * WS-Security header is allowed for an actor.
 * //  w ww . j  a  v a 2 s. c  o m
 * @param doc
 * @param actor
 * @return the <code>wsse:Security</code> element or <code>null</code>
 *         if not such element found
 */
public static Element getSecurityHeader(Document doc, String actor, SOAPConstants sc) {
    Element soapHeaderElement = (Element) getDirectChild(doc.getDocumentElement(),
            sc.getHeaderQName().getLocalPart(), sc.getEnvelopeURI());
    if (soapHeaderElement == null) { // no SOAP header at all
        return null;
    }

    // get all wsse:Security nodes
    NodeList list = soapHeaderElement.getElementsByTagNameNS(WSConstants.WSSE_NS, WSConstants.WSSE_LN);
    if (list == null) {
        return null;
    }
    for (int i = 0; i < list.getLength(); i++) {
        Element elem = (Element) list.item(i);
        Attr attr = elem.getAttributeNodeNS(sc.getEnvelopeURI(), sc.getRoleAttributeQName().getLocalPart());
        String hActor = (attr != null) ? attr.getValue() : null;
        if (WSSecurityUtil.isActorEqual(actor, hActor)) {
            return elem;
        }
    }
    return null;
}

From source file:org.apache.xml.security.encryption.XMLCipher.java

/**
 * /*ww  w.j av  a2 s  . c o  m*/
 * @param element
 * @return the <code>Node</code> as a result of the decrypt operation.
 * @throws XMLEncryptionException
 */
private Document decryptElementContent(Element element) throws XMLEncryptionException {
    Element e = (Element) element.getElementsByTagNameNS(EncryptionConstants.EncryptionSpecNS,
            EncryptionConstants._TAG_ENCRYPTEDDATA).item(0);

    if (null == e) {
        throw new XMLEncryptionException("No EncryptedData child element.");
    }

    return decryptElement(e);
}

From source file:org.chiba.tools.schemabuilder.AbstractSchemaFormBuilder.java

/**
 * builds a form from a XML schema./*  ww w. jav a2 s. c  o  m*/
 *
 * @param inputURI the URI of the Schema to be used
 * @return __UNDOCUMENTED__
 * @throws FormBuilderException __UNDOCUMENTED__
 */
public Document buildForm(String inputURI) throws FormBuilderException {
    try {
        this.loadSchema(inputURI);
        buildTypeTree(schema);

        //refCounter = 0;
        counter = new HashMap();

        Document xForm = createFormTemplate(_rootTagName, _rootTagName + " Form",
                getProperty(CSS_STYLE_PROP, DEFAULT_CSS_STYLE_PROP));

        //this.buildInheritenceTree(schema);
        Element envelopeElement = xForm.getDocumentElement();

        //Element formSection = (Element) envelopeElement.getElementsByTagNameNS(CHIBA_NS, "form").item(0);
        //Element formSection =(Element) envelopeElement.getElementsByTagName("body").item(0);
        //find form element: last element created
        NodeList children = xForm.getDocumentElement().getChildNodes();
        int nb = children.getLength();
        Element formSection = (Element) children.item(nb - 1);

        Element modelSection = (Element) envelopeElement.getElementsByTagNameNS(XFORMS_NS, "model").item(0);

        //add XMLSchema if we use schema types
        if (_useSchemaTypes && modelSection != null) {
            modelSection.setAttributeNS(XFORMS_NS, this.getXFormsNSPrefix() + "schema", inputURI);
        }

        //change stylesheet
        String stylesheet = this.getStylesheet();

        if ((stylesheet != null) && !stylesheet.equals("")) {
            envelopeElement.setAttributeNS(CHIBA_NS, this.getChibaNSPrefix() + "stylesheet", stylesheet);
        }

        // TODO: Commented out because comments aren't output properly by the Transformer.
        //String comment = "This XForm was automatically generated by " + this.getClass().getName() + " on " + (new Date()) + System.getProperty("line.separator") + "    from the '" + rootElementName + "' element from the '" + schema.getSchemaTargetNS() + "' XML Schema.";
        //xForm.insertBefore(xForm.createComment(comment),envelopeElement);
        //xxx XSDNode node = findXSDNodeByName(rootElementTagName,schemaNode.getElementSet());

        //check if target namespace
        //no way to do this with XS API ? load DOM document ?
        //TODO: find a better way to find the targetNamespace
        try {
            Document domDoc = DOMUtil.parseXmlFile(inputURI, true, false);
            if (domDoc != null) {
                Element root = domDoc.getDocumentElement();
                targetNamespace = root.getAttribute("targetNamespace");
                if (targetNamespace != null && targetNamespace.equals(""))
                    targetNamespace = null;
            }
        } catch (Exception ex) {
            LOGGER.error("Schema not loaded as DOM document: " + ex.getMessage());
        }

        //if target namespace & we use the schema types: add it to form ns declarations
        if (_useSchemaTypes && targetNamespace != null && !targetNamespace.equals("")) {
            envelopeElement.setAttributeNS(XMLNS_NAMESPACE_URI, "xmlns:schema", targetNamespace);
        }

        //TODO: WARNING: in Xerces 2.6.1, parameters are switched !!! (name, namespace)
        //XSElementDeclaration rootElementDecl =schema.getElementDeclaration(targetNamespace, _rootTagName);
        XSElementDeclaration rootElementDecl = schema.getElementDeclaration(_rootTagName, targetNamespace);

        if (rootElementDecl == null) {
            //DEBUG
            rootElementDecl = schema.getElementDeclaration(_rootTagName, targetNamespace);
            if (rootElementDecl != null && LOGGER.isDebugEnabled())
                LOGGER.debug("getElementDeclaration: inversed parameters OK !!!");

            throw new FormBuilderException("Invalid root element tag name [" + _rootTagName
                    + ", targetNamespace=" + targetNamespace + "]");
        }

        Element instanceElement = (Element) modelSection
                .appendChild(xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "instance"));
        this.setXFormsId(instanceElement);

        Element rootElement;

        if (_instanceMode == AbstractSchemaFormBuilder.INSTANCE_MODE_NONE) {
            rootElement = (Element) instanceElement.appendChild(
                    xForm.createElementNS(targetNamespace, getElementName(rootElementDecl, xForm)));

            String prefix = xmlSchemaInstancePrefix.substring(0, xmlSchemaInstancePrefix.length() - 1);
            rootElement.setAttributeNS(XMLNS_NAMESPACE_URI, "xmlns:" + prefix,
                    XMLSCHEMA_INSTANCE_NAMESPACE_URI);

        } else if (_instanceMode == AbstractSchemaFormBuilder.INSTANCE_MODE_INCLUDED)
        //get the instance element
        {
            boolean ok = true;

            try {
                /*DOMResult result = new DOMResult();
                TransformerFactory trFactory =
                TransformerFactory.newInstance();
                Transformer tr = trFactory.newTransformer();
                tr.transform(_instanceSource, result);
                Document instanceDoc = (Document) result.getNode();*/
                DocumentBuilderFactory docFact = DocumentBuilderFactory.newInstance();
                docFact.setNamespaceAware(true);
                docFact.setValidating(false);
                DocumentBuilder parser = docFact.newDocumentBuilder();
                Document instanceDoc = parser.parse(new InputSource(_instanceSource.getSystemId()));

                //possibility abandonned for the moment:
                //modify the instance to add the correct "xsi:type" attributes wherever needed
                //Document instanceDoc=this.setXMLSchemaAndPSVILoad(inputURI, _instanceSource, targetNamespace);

                if (instanceDoc != null) {
                    Element instanceInOtherDoc = instanceDoc.getDocumentElement();

                    if (instanceInOtherDoc.getNodeName().equals(_rootTagName)) {
                        rootElement = (Element) xForm.importNode(instanceInOtherDoc, true);
                        instanceElement.appendChild(rootElement);

                        //add XMLSchema instance NS
                        String prefix = xmlSchemaInstancePrefix.substring(0,
                                xmlSchemaInstancePrefix.length() - 1);
                        if (!rootElement.hasAttributeNS(XMLNS_NAMESPACE_URI, prefix))
                            rootElement.setAttributeNS(XMLNS_NAMESPACE_URI, "xmlns:" + prefix,
                                    XMLSCHEMA_INSTANCE_NAMESPACE_URI);

                        //possibility abandonned for the moment:
                        //modify the instance to add the correct "xsi:type" attributes wherever needed
                        //this.addXSITypeAttributes(rootElement);
                    } else {
                        ok = false;
                    }
                } else {
                    ok = false;
                }
            } catch (Exception ex) {
                ex.printStackTrace();

                //if there is an exception we put the empty root element
                ok = false;
            }

            //if there was a problem
            if (!ok) {
                rootElement = (Element) instanceElement.appendChild(xForm.createElement(_rootTagName));
            }
        } else if (_instanceMode == AbstractSchemaFormBuilder.INSTANCE_MODE_HREF)
        //add the xlink:href attribute
        {
            instanceElement.setAttributeNS(SchemaFormBuilder.XLINK_NS, this.getXLinkNSPrefix() + "href",
                    _instanceHref);
        }

        Element formContentWrapper = _wrapper.createGroupContentWrapper(formSection);
        addElement(xForm, modelSection, formContentWrapper, rootElementDecl,
                rootElementDecl.getTypeDefinition(), "/" + getElementName(rootElementDecl, xForm));

        Element submitInfoElement = (Element) modelSection
                .appendChild(xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "submission"));

        //submitInfoElement.setAttributeNS(XFORMS_NS,getXFormsNSPrefix()+"id","save");
        String submissionId = this.setXFormsId(submitInfoElement);

        //action
        if (_action == null) {
            submitInfoElement.setAttributeNS(XFORMS_NS, getXFormsNSPrefix() + "action", "");
        } else {
            submitInfoElement.setAttributeNS(XFORMS_NS, getXFormsNSPrefix() + "action", _action);
        }

        //method
        if ((_submitMethod != null) && !_submitMethod.equals("")) {
            submitInfoElement.setAttributeNS(XFORMS_NS, getXFormsNSPrefix() + "method", _submitMethod);
        } else { //default is "post"
            submitInfoElement.setAttributeNS(XFORMS_NS, getXFormsNSPrefix() + "method",
                    AbstractSchemaFormBuilder.SUBMIT_METHOD_POST);
        }

        //Element submitButton = (Element) formSection.appendChild(xForm.createElementNS(XFORMS_NS,getXFormsNSPrefix()+"submit"));
        Element submitButton = xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "submit");
        Element submitControlWrapper = _wrapper.createControlsWrapper(submitButton);
        formContentWrapper.appendChild(submitControlWrapper);
        submitButton.setAttributeNS(XFORMS_NS, getXFormsNSPrefix() + "submission", submissionId);
        this.setXFormsId(submitButton);

        Element submitButtonCaption = (Element) submitButton
                .appendChild(xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "label"));
        submitButtonCaption.appendChild(xForm.createTextNode("Submit"));
        this.setXFormsId(submitButtonCaption);

        return xForm;
    } catch (ParserConfigurationException x) {
        throw new FormBuilderException(x);
    } catch (java.lang.ClassNotFoundException x) {
        throw new FormBuilderException(x);
    } catch (java.lang.InstantiationException x) {
        throw new FormBuilderException(x);
    } catch (java.lang.IllegalAccessException x) {
        throw new FormBuilderException(x);
    }
}

From source file:org.chiba.tools.schemabuilder.AbstractSchemaFormBuilder.java

/**
 * __UNDOCUMENTED__/* w w  w .j ava2s  . co m*/
 *
 * @param xForm      __UNDOCUMENTED__
 * @param annotation __UNDOCUMENTED__
 * @return __UNDOCUMENTED__
 */
protected Element addHintFromDocumentation(Document xForm, XSAnnotation annotation) {
    if (annotation != null) {
        Element hintElement = xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "hint");
        this.setXFormsId(hintElement);

        Text hintText = (Text) hintElement.appendChild(xForm.createTextNode(""));

        //write annotation to empty doc
        Document doc = DOMUtil.newDocument(true, false);
        annotation.writeAnnotation(doc, XSAnnotation.W3C_DOM_DOCUMENT);

        //get "annotation" element
        NodeList annots = doc.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "annotation");
        if (annots.getLength() > 0) {
            Element annotEl = (Element) annots.item(0);

            //documentation
            NodeList docos = annotEl.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema",
                    "documentation");
            int nbDocos = docos.getLength();
            for (int j = 0; j < nbDocos; j++) {
                Element doco = (Element) docos.item(j);

                //get text value
                String text = DOMUtil.getTextNodeAsString(doco);
                hintText.appendData(text);

                if (j < nbDocos - 1) {
                    hintText.appendData(" ");
                }
            }
            return hintElement;
        }
        return null;
    }

    return null;
}