Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dom4j xmlns attribute

Tags:

java

dom4j

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();


    }
like image 684
Phoenix Avatar asked Feb 23 '23 16:02

Phoenix


2 Answers

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.

like image 163
forty-two Avatar answered Mar 07 '23 20:03

forty-two


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();

}
like image 37
Jeshurun Avatar answered Mar 07 '23 20:03

Jeshurun