Клонировать XML без пространства имен и префикса

У меня есть XML-файл с пространством имен и префиксом. Я хочу удалить эти пространства имен и префиксы и преобразовать их в обычный XML с помощью Java. Я устал от этого, используя аксиому в последние пару дней. пока что не удачно. Так как аксиома не поддерживает удаление пространства имен (обьявленное пространство имен iterator.remove() не работает), я попытался клонировать и удалить пространство имен. это не работает как обход через итератор.

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

Теперь я хочу создать другой документ, проходя через оригинальный документ. значения должны быть одинаковыми, и единственное ожидаемое различие заключается в удалении пространства имен / префикса и значения атрибута ключа основного элемента concat для каждого элемента.

источник

<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>

ожидаемый результат

<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>

лучше, если я смогу сделать это, используя AXIOM, поскольку это уже утвержденная библиотека. но я в порядке, чтобы сделать это с любой библиотекой. любая помощь будет признательна.

2 ответа

Решение

Удаление объявлений пространства имен не достаточно, потому что OMElement экземпляры в дереве все еще сохраняют свои пространства имен (и во время сериализации Axiom автоматически генерирует необходимые объявления пространств имен, чтобы они имели эти пространства имен в выходном документе). Вам также нужно позвонить setNamespace поменять их:

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

Это мой ответ, с интенсивным использованием XPath и 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");
    }

}

Вывод моего XML

<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>
Другие вопросы по тегам