Phoenix
Phoenix

Reputation: 8923

Dom4j xmlns attribute

I want to add xmlns attribute to the root node only, however when i add a namespace to the root element, all subsequent child elements also get the same xmlns attribute. How do I add xmlns attribute to a single node but not any of its children ? CODE:

public String toXml() {

        Document document = DocumentHelper.createDocument();
        Element documentRoot = document.addElement("ResponseMessage");
        documentRoot.addNamespace("",getXmlNamespace())
                .addAttribute("xmlns:xsi", getXmlNamespaceSchemaInstance())
                .addAttribute("xsi:schemaLocation", getXmlSchemaLocation())
                .addAttribute("id", super.getId());

        Element header = documentRoot.addElement("Header");
        buildHeader(header);

        Element body = documentRoot.addElement("Body");
        buildProperties(body);

        body.addElement("StatusMessage").addText(this.getStatusMessage().getMessage());

        return document.asXML();


    }

Upvotes: 4

Views: 8244

Answers (2)

Jeshurun
Jeshurun

Reputation: 23186

Heres how. Its a bit of a hack, but it does what you want:

public static String toXml() {

Document d = DocumentHelper.createDocument();
Namespace rootNs = new Namespace("", DEFAULT_NAMESPACE); // root namespace uri
Namespace xsiNs = new Namespace("xsi", XSI_NAMESPACE); // xsi namespace uri
QName rootQName = QName.get(rootElement, rootNs); // your root element's name

Element root = d.addElement(rootElement);
root.setQName(rootQName);
root.add(xsiNs);
root.addAttribute("xsi:schemaLocation", SCHEMA_LOC)
.addAttribute("id", super.getId());

Element header = documentRoot.addElement("Header");

Element body = documentRoot.addElement("Body", getXmlNamespace());
// buildProperties(body);

body.addElement("StatusMessage", getXmlNamespace()).addText("status");

return document.asXML();

}

Upvotes: 2

forty-two
forty-two

Reputation: 12817

OK, new answer.

If you want your elements to belong to a certain namespace, be sure to create them in that namespace. Use the methods that have Qname as one of its arguments. If you create an element with no namespace, DOM4J will have to add namespace declarations to accommodate to your (unwillingly) specification.

Your example slightly edited. I didn't use QName, but gave each element a namespace uri:

public static String toXml() {

    Document document = DocumentHelper.createDocument();
    Element documentRoot = document.addElement("ResponseMessage",
            getXmlNamespace());
    documentRoot.addAttribute(QName.get("schemaLocation", "xsi", "xsi-ns"),
            "schema.xsd").addAttribute("id", "4711");

    Element header = documentRoot.addElement("Header");

    Element body = documentRoot.addElement("Body", getXmlNamespace());
    // buildProperties(body);

    body.addElement("StatusMessage", getXmlNamespace()).addText("status");

    return document.asXML();

}

private static String getXmlNamespace() {
    return "xyzzy";
}

public static void main(String[] args) throws Exception {

    System.out.println(toXml());
}

produces as output:

<?xml version="1.0" encoding="UTF-8"?>
<ResponseMessage xmlns="xyzzy" xmlns:xsi="xsi-ns" xsi:schemaLocation="schema.xsd" id="4711">
<Header/><Body><StatusMessage>status</StatusMessage></Body>
</ResponseMessage>

UPDATE 2:

Note also, that I changed the way how the schemaLocation attribute is declared. You really never have to manually manage the namespace declarations--this will be taken care of by the library.

However, there is one case where it might be useful to add a namespace delaration: If you have a document with predominantly namespace X elements, and some child elements with namspace Y spread out in the document, declaring a namesapce binding for Y at the root element, may save a lot of repeating name space declarations in the child elements.

Upvotes: 6

Related Questions