01 março 2011

[JAXB] Namespaces indesejados no marshalling

É, 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:

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

Creative Commons License
Esta obra está licenciada sob uma Licença Creative Commons.
Comentários
0 Comentários

0 comments:

Postar um comentário

Regras são chatas, mas...

- Seu comentário precisa ter relação com o assunto do post;
- Em hipótese alguma faça propaganda de outros blogs ou sites;
- Não inclua links desnecessários no conteúdo do seu comentário;
- Se quiser deixar sua URL, comente usando a opção OpenID;
- CAIXA ALTA, miguxês ou erros de ortografia não serão tolerados;
- Ofensas pessoais, ameaças e xingamentos não são permitidos;