Ajuda com JDom - getChild() Retorna Null [RESOLVIDO]

Pessoal meu primeiro post no forum para pedir uma ajuda. Já acompanho o forum a um bom tempo somente lendo os posts.

Bom já li varios tutoriais sobre o JDOM e as apis de XML para java como:

Utilizando JDOM para ler e gerar XML
Manipulando Arquivo XML ? Parte II: JDOM
Reading an XML document using JDOM

Porem esbarro em um problema que esta me deixando de cabelo branco. Estou tentando importar de um arquivo xml de NF-e algumas informações como:

CNPJ Emitente
CNPJ Destinatario
Valor total da Nota.

Porem só estou consigo chegar até o cnpj do emitente e isso usando o get(int index) e passando o index na unha. Quando tento usar o getChild(“string”) sempre retorna null.

Vejam um código de teste que fiz:

public class TesteJDom2 {

    public static void main(String[] args) {
        Document document = null;
        SAXBuilder builder = new org.jdom2.input.SAXBuilder();

        try {
            document = builder.build("D:\\XML\\NFe42130305063146000108550010001580261000225602-nfe-proc.xml");
        } catch (JDOMException ex) {
            Logger.getLogger(TesteJDOM.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(TesteJDOM.class.getName()).log(Level.SEVERE, null, ex);
        }

        Element root = document.getRootElement();

        System.out.println("Nome da root: " + root.getName());

        List<Element> elements = root.getChildren();

        System.out.println("Tamanho da lista: " + elements.size());

        //imprime o nome dos elements
        for (Element e : elements) {
            System.out.println("Nome do Element: " + e.getName());
        }
        
        //tenta pegar a child NFe
        Element nfeElement = root.getChild("NFe");
        
        //imprimi o nome do element dever ser NFe
        System.out.println("Nome do nfeElement: " + nfeElement.getName());

    }
}

A saida é a seguinte:

Nome da root: nfeProc
Tamanho da lista: 2
Nome do Element: NFe
Nome do Element: protNFe
Exception in thread "main" java.lang.NullPointerException
	at Teste.TesteJDom2.main(TesteJDom2.java:51)
Java Result: 1

Percebam que a lista tem dois Elements e que um deles se chama “NFe”.
Porem quanto tento pega-lo pelo root.getChild(“NFe”) e passo pro nfeElement, ao acessar qualquer propriedade dele recebo um NullPointerException.

Sei que estou fazendo algo de errado só não consegui descobrir o que ainda.

Se alguém puder me ajudar fico grato.

[ ]'s

Teria como você postar o XML? Fica mais fácil.

Mas acredito que NFe não é um child direto de root, por isso rola o nullpointer. Talvez ele esteja dentro do objeto elements. Por isso, se postar o XML fica mais fácil visualizar.

Segue o XML.

Não consegui postar como código ficou todo bagunçado, apaguei os dados de CNPJ, CPF e e-mail deliberadamente.

[ ]'s


Link Imagem

[quote=romarcio]Teria como você postar o XML? Fica mais fácil.

Mas acredito que NFe não é um child direto de root, por isso rola o nullpointer. Talvez ele esteja dentro do objeto elements. Por isso, se postar o XML fica mais fácil visualizar.[/quote]

romarcio, seguindo está sua ideia, se o “NFe” não for uma child direto de root, por que ele aparece no array quando eu do um getChildren(), teoricamente, se está no get é porque ele é um node filho. Ou estou enganado?

Obrigado pela ajuda.

Olhando para o XML, parece estar certo mesmo o que você fez.
Caso você tentasse recuperar o <infNFe> dai sim se enquadraria no que eu tinha falado antes, porque essa tag não é filha direta de root, mas sim de <NFe>

Sendo assim, deveria estar funcionando.
Você tentou debugar para acompanhar os valores de cada objeto?

Pois é por isso não consegui descobrir qual o erro ainda.

Vou debugar com mais calma isso hoje, pra ver se consigo descobrir o que esta acontecendo. Em teoria eu pensei que seria da seguinte forma:

Element nfeElement = root.getChild("NFe");

Elemente infNFe = nfeElement.getChild("infNFe");

Element emit = infNfw.getChild("emit");

depois o getAttribute do emit.

Por tudo que li e vi seria assim, pior que estou a dois dias em cima disso e não consigo descobrir qual o erro e pra ajudar é pra empresa do meu pai ou seja todo hora que me vê:

" Já ta pronto? Vai ficar pronto hoje?" hauhauhau :lol:

O velho não me da descanso.

Muito obrigado pela ajuda romarcio.

Copiei o seu código fonte da classe TesteJDom2 e montei o XML que você postou na imagem.
Executei o código e não ocorreu erro algum.
E tudo foi impresso no console sem problemas.

[quote=romarcio]Copiei o seu código fonte da classe TesteJDom2 e montei o XML que você postou na imagem.
Executei o código e não ocorreu erro algum.
E tudo foi impresso no console sem problemas.[/quote]

:?

romarcio, mais uma vez obrigado, pela ajuda.

Você consegui pegar o child NFe sem erros ?

Me tire algumas duvidas qual a versão da JDK e do JDOM você esta usando?

Existe alguma outra dependência do JDOM além do seu próprio .jar :?:

[ ]'s

Sim, executou sem erro.

A versão do JDom que eu usei é a 1.1.1.

Não existe outra dependência, apenas o JDom mesmo.

Dê um conferida se você não importou alguma classe errada. Existem classes com o mesmo nome no JDK. Veja as que usei:

import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder;

Aparentemente meus imports estão corretos a não se pelo fato de eu estar usando JDOM 2.04.

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

Vou testar com 1.1.1 pra ver se da certo.

Fico lhe devendo uma. Depois posto se deu certo.

[ ]'s

Tentei com a 1.1.1 e 1.1.3 mesmo coisa nullpointerException. Ta muito estrando isso.

Alterei o codigo do for dai consegui pegar o child NFe com um if. :?

[code]
for (Element e : elements) {
System.out.println("Nome do Element: " + e.getName());

        //tenta pegar a child NFe
        if(e.getName().equals(new String("NFe"))){
            nfeElement = e;
        }
    }
    
    //imprimi o nome do element dever ser NFe
    System.out.println("Nome do Parent: " + nfeElement.getParentElement().getName());
    System.out.println("Nome do nfeElement: " + nfeElement.getName());

}[/code]

Saida:

Nome da root: nfeProc
Tamanho da lista: 2
Nome do Element: NFe
Nome do Element: protNFe
Nome do Parent: nfeProc
Nome do nfeElement: NFe

Mais ficou muito POG isso pra mim e sou meio teimosão. Acho que nao vou conseguir dormir hoje se não der um jeito nisso. :lol:

Sei que o código esta tosco mas é só pra teste mesmo:

Consigo chegar em todos os níveis de Document com for.

Porem não consigo acessar nenhum valor com pelos métodos getAttribute(String attName) ou getChild(String cname) sempre retornam null.

Modifiquei mais um pouco o for pra ver se consigo chegar em todos os childs, e consigo, é isto que ainda não entendi se eles, os childs, estão lá e os atributos também por que os métodos do JDOM não os acha.

Chequei a pilha debugando e os elements estão lá em Arrays chamdados content do tipo ContentList vejam:

[code]import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

/**
*

  • @author Cleber
    */
    public class TesteJDom2 {

    public static void main(String[] args) {
    Document document = null;
    SAXBuilder builder = new org.jdom2.input.SAXBuilder();

     try {
         document = builder.build("D:\\XML\\42130389735070000363550010001507501173058302-nfe.xml");
     } catch (JDOMException ex) {
         Logger.getLogger(TesteJDOM.class.getName()).log(Level.SEVERE, null, ex);
     } catch (IOException ex) {
         Logger.getLogger(TesteJDOM.class.getName()).log(Level.SEVERE, null, ex);
     }
    
    
     Element root = document.getRootElement();
     Element nfeElement = null;
    
     System.out.println("Nome da root: " + root.getName());
    
     List<Element> elements = root.getChildren();
    
     System.out.println("Tamanho da lista: " + elements.size());
    
     //imprime o nome dos elements da root
     for (Element e : elements) {
         System.out.println("Filho de root nome:" + e.getName());
    
         
         for (Element e1 : e.getChildren()) {
    
             System.out.println("    +Filho de " + e1.getParent().getParent() + " nome: " + e1.getName());
    
             for (Element e2 : e1.getChildren()) {
                 System.out.println("        -Filho de : " + e2.getParent() + " nome: " + e2.getName());
    
                 if (e2.getName().equals(new String("emit"))) {
                     System.out.println("            ### Imprimindo Child CNPJ ###");
    
                     for (Element emit : e2.getChildren()) {
    
                         if (emit.getName().equals(new String("CNPJ"))) {
                             System.out.println("            Numero CNPJ: " + emit.getText());
                         }
                     }
                 }
             }
    
         }
    

// //tenta pegar a child NFe
// if(e.getName().equals(new String(“NFe”))){
// nfeElement = e;
// }
}

// nfeElement = root.getChild(“NFe”);
//
// //imprimi o nome do element dever ser NFe
// System.out.println("Nome do Parent: " + nfeElement.getParentElement().getName());
// System.out.println("Nome do nfeElement: " + nfeElement.getName());

}

}[/code]

Saida: Percebam que usei um emit.getText() porque se eu usar o emit.getAttributeValue(“CNPJ”) retornoa null

Nome da root: nfeProc
Tamanho da lista: 2
Filho de root nome:NFe
    +Filho de [Element: <nfeProc [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: infNFe
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: ide
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: emit
            ### Imprimindo Child CNPJ ###
            Numero CNPJ: 89735070000363
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: dest
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: det
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: det
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: det
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: total
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: transp
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: cobr
        -Filho de : [Element: <infNFe [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: infAdic
    +Filho de [Element: <nfeProc [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: Signature
        -Filho de : [Element: <Signature [Namespace: http://www.w3.org/2000/09/xmldsig#]/>] nome: SignedInfo
        -Filho de : [Element: <Signature [Namespace: http://www.w3.org/2000/09/xmldsig#]/>] nome: SignatureValue
        -Filho de : [Element: <Signature [Namespace: http://www.w3.org/2000/09/xmldsig#]/>] nome: KeyInfo
Filho de root nome:protNFe
    +Filho de [Element: <nfeProc [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: infProt
        -Filho de : [Element: <infProt [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: tpAmb
        -Filho de : [Element: <infProt [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: verAplic
        -Filho de : [Element: <infProt [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: chNFe
        -Filho de : [Element: <infProt [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: dhRecbto
        -Filho de : [Element: <infProt [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: nProt
        -Filho de : [Element: <infProt [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: digVal
        -Filho de : [Element: <infProt [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: cStat
        -Filho de : [Element: <infProt [Namespace: http://www.portalfiscal.inf.br/nfe]/>] nome: xMotivo

[ ]'s

Só pra deixar de referencia pro pessoal a solução.

Eu já tinha resolvido de forma mais verbosa com if da seguinte forma:


for(Element e : root.getChildren()){

  if(e.getName.equals("NFe")){

    nfeElement = e;
  }

}

E esta funcionando mas como ficou muito verboso pois tenho que pegar vários childs, continuei fuçando e descobri que qdo o XML tem namespace declarado o getChild(String cName) sem namespace não funciona. É preciso usar o método getChild(String Cname, NameSpace ns).

Em resumo o código funcional fica assim:

Namespace ns = Namespace.getNamespace("http://www.portalfiscal.inf.br/nfe");
        for (Element e : root.getChildren()) {
            
            Element e1 = e.getChild("infNFe",root.getNamespace());
            if(e1 != null){
                System.out.println(e1.getName());
            }
        }

Fica a dica.

[ ]'s