É, eu ainda estou tentando resolver isso. Mas aparentemente, eu achei uma solução um tanto menos traumática pra mim.
Cá estou eu tentando resolver o incômodo problema da inclusão de namespaces extras no elemento raíz do xml durante o marshalling do JAXB. Aí eu resolvi voltar às origens do meu problema. Peguei todos os meus xsd's (Xml Schema), coloquei numa pasta separada, e gerei as classes java novamente. Não havia reparado na importância disso antes, mas para targetNamespaces diferentes, o xjc gera pastas (pacotes) diferentes.
Dessa vez eu resolvi respeitar este fato, e copiei as pastas para dentro do meu projeto, renomeando-as (é claro), mas mantendo-as separadas. Daí, eu tentei fazer o marshalling novamente, e o problema continuou. Como o meu problema é bem específico, eu resolvi meter a mão na massa de modo também específico.
Primeiramente, fiz o marshalling para um org.w3c.dom.Document:
A partir daqui, removi os namespaces extras no elemento raíz do meu org.w3c.dom.Document:
Com esse trecho de código, eu tentei novamente o marshalling. O namespace extra realmente desapareceu no elemento raíz, mas o prefixo extra (ns2) continuou para os elementos do namespace extra. O mais interessante foi que ele definiu um atributo de nome xmlns (definição de namespace) para cada elemento do novo namespace que possui a anotação @XmlRootElement. Para remover os prefixos extras, eu tentei outra solução além do uso da classe NamespacePrefixMapper:
Dessa vez eu resolvi respeitar este fato, e copiei as pastas para dentro do meu projeto, renomeando-as (é claro), mas mantendo-as separadas. Daí, eu tentei fazer o marshalling novamente, e o problema continuou. Como o meu problema é bem específico, eu resolvi meter a mão na massa de modo também específico.
Primeiramente, fiz o marshalling para um org.w3c.dom.Document:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.newDocument(); marshaller.marshal(object, document);
A partir daqui, removi os namespaces extras no elemento raíz do meu org.w3c.dom.Document:
Element rootElement = document.getDocumentElement(); rootElement.removeAttribute("xmlns:ns2");
Com esse trecho de código, eu tentei novamente o marshalling. O namespace extra realmente desapareceu no elemento raíz, mas o prefixo extra (ns2) continuou para os elementos do namespace extra. O mais interessante foi que ele definiu um atributo de nome xmlns (definição de namespace) para cada elemento do novo namespace que possui a anotação @XmlRootElement. Para remover os prefixos extras, eu tentei outra solução além do uso da classe NamespacePrefixMapper:
NodeList nodeList = document.getElementsByTagNameNS("namespace", "*"); if (nodeList.getLength() != 0) { for (int i = 0; i < nodeList.getLength(); i++) { Element element = (Element) nodeList.item(i); element.setPrefix(""); } }Atentem para a primeira linha do trecho de código acima. Usei o asterisco (*) para pegar todos os elementos do referido namespace. Daí, setei um prefixo vazio ("") e ele de fato removeu o prefixo dos elementos que eu desejava. Para contextualizar a minha situação, isso tudo começou por causa de namespaces extras no elemento raíz, após assinar digitalmente os xml's das notas fiscais eletrônicas... É importante passar o resultado do marshalling por algum validador de xml's. Isso porque, por exemplo, seu xml schema pode não permitir espaços em branco no conteúdo dos elementos, e a depender do tamanho do seu xml schema, checar elemento a elemento pode ser um tanto demorado...