Search code examples
javaxmlnamespacesaxiom

Clone XML without Namespace and prefix


I have xml file with namespace and prefix. i want to remove those namespace and prefix and convert that in to plain xml using java. I have tired to this using axiom in last couple of days. so far is not successful. since axiom not supporting to remove namespace (declaredNamespace iterator.remove() did not worked) I tried to clone and remove namespace. that is not working as traverse through iterator.

 OMElement oe = fac.createOMElement(new QName(omElement.getQName().getLocalPart()));
                Iterator internalIt = omElement.getChildren();
                if (internalIt.hasNext()) {
                    while (internalIt.hasNext()) {
                        OMNode onode = (OMNode) ((OMNode) internalIt.next()).clone(new OMCloneOptions());
                        oe.addChild((OMNode) onode);
                        omElement.getParent().addChild(oe);
                    }
                } else {
                    omElement.getParent().addChild(oe);
                }

now i want to create other document while traverse through original document. values should be same and only expected difference is remove namespace/prefix and concat main element key attribute value to each element.

source

<root>
<a key="A">
    <c:b xmlns:c="http://schemas.xmlsoap.org/soap/envelope/">
        <c>
            <c:x xmlns:c="http://schemas.xmlsoap.org/soap/envelope/">111</c:x>
            <c:y xmlns:c="http://abc">2222</c:y>
            <z>33333</z>
        </c>
        <c:d xmlns:c="http://schemas.xmlsoap.org/soap/envelope/">sss</c:d>
    </c:b>
    <e>
        <K></K>
        <L></L>
    </e>
</a>
<a key="B">
    <c:b xmlns:c="http://schemas.xmlsoap.org/soap/envelope/">
        <c>
            <c:x xmlns:c="http://schemas.xmlsoap.org/soap/envelope/">3333</c:x>
            <c:y xmlns:c="http://abc">6666</c:y>
            <z>aaaaa</z>
        </c>
        <c:d xmlns:c="http://schemas.xmlsoap.org/soap/envelope/"></c:d>
    </c:b>
    <e>
        <K>54</K>
        <L>fff</L>
    </e>
</a>

expected output

<root>
<a>
    <A_b>
        <A_c>
            <A_x>111</A_x>
            <A_y>2222</A_y>
            <A_z>33333</A_z>
        </A_c>
        <A_d>sss</A_d>
    </A_b>
    <A_e>
        <A_K></A_K>
        <A_L></A_L>
    </A_e>
</a>
<a>
    <B_b>
        <B_c>
            <B_x>3333</B_x>
            <B_y>6666</B_y>
            <B_z>aaaaa</B_z>
        </B_c>
        <B_d></B_d>
    </B_b>
    <B_e>
        <B_K>54</B_K>
        <B_L>fff</B_L>
    </B_e>
</a>

it is better if I can do this using AXIOM as that is already approved library. but I am OK to get this done with any library. any help would appreciate.


Solution

  • Removing the namespace declarations isn't enough because the OMElement instances in the tree still retain their namespaces (and during serialization, Axiom automatically generates the necessary namespace declarations so that they have those namespaces in the output document). You also need to call setNamespace to change them:

    OMDocument document = ...
    for (Iterator it = document.getDescendants(false); it.hasNext(); ) {
        OMNode node = (OMNode)it.next();
        if (node instanceof OMElement) {
            OMElement element = (OMElement)node;
            element.setNamespace(null, false);  // <-- this actually changes the namespace of the element
            for (Iterator it2 = element.getAllDeclaredNamespaces(); it2.hasNext(); ) {
                it2.next();
                it2.remove();
            }
        }
    }