2

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.

Derek Noble
  • 289
  • 1
  • 3
  • 13

2 Answers2

2

This is my answer, with heavy use of XPath and VTD-XML...

import com.ximpleware.*;
import java.io.*;
public class removeNameSpaces {
    public static void main(String[] args) throws VTDException,IOException {
        // TODO Auto-generated method stub
        VTDGen vg = new VTDGen();
        AutoPilot ap = new AutoPilot(),
                ap3=new AutoPilot(),
                ap4=new AutoPilot(),
                ap5= new AutoPilot();
        ap.selectXPath("/root/a");
        ap3.selectXPath("@key");
        ap4.selectXPath("descendant::*");
        ap5.selectXPath("//@*");
        if (!vg.parseFile("d:\\xml\\oo.xml", false))
            return;
        VTDNav vn = vg.getNav();
        ap.bind(vn);ap3.bind(vn);
        ap4.bind(vn);ap5.bind(vn);
        XMLModifier xm = new XMLModifier(vn);
        // remove all attribute from xml file
        int i=0,j=0;
        while((i=ap5.evalXPath())!=-1){
            xm.remove();
        }
        String keyName;String elementName;
        // update names of all the element nodes under /root/a
        while((i=ap.evalXPath())!=-1){  
            keyName= ap3.evalXPathToString();
            vn.push();
            while((j=ap4.evalXPath())!=-1){
                elementName = vn.toRawString(j);
                int offset = elementName.indexOf(':');
                String newElementName = keyName+"_"+((offset==-1)?elementName: elementName.substring(offset+1)) ;
                xm.updateElementName(newElementName);
            }
            ap4.resetXPath();
            vn.pop();
        }   
        xm.output("d:\\xml\\ooo.xml");
    }

}

The output of my XML is

<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>
</root>
vtd-xml-author
  • 3,319
  • 4
  • 22
  • 30
1

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();
        }
    }
}
Andreas Veithen
  • 8,868
  • 3
  • 25
  • 28
  • Interesting... I tired same code like this before. but what I missed is ` element.setNamespace(null, false); ` when i add that it almost remove all namespaces. but still I do see some issue when something like this if source as ` 1234567890 ` its translate as (Ill add new comment a no enough space) – Derek Noble May 16 '16 at 14:53
  • continue comment: its translate as `
    1234567890
    ` looks like parent namespace continues. I saw this in some other places as well. it taking parent namespace based on prefix. any idea?
    – Derek Noble May 16 '16 at 14:56
  • That's because there are attributes with namespaces. Simply iterate over those attributes and use setNamespace to remove the namespaces. – Andreas Veithen May 16 '16 at 15:41