Lendo XML + JDOM

9 respostas
J

Pessoal, to precisando de ajuda

quero ler um xml e acontece que meu XML pode ter varias tags repetidas.

Por exemplo

<mensagem>
<nome>Fulano</nome>
<contato>11111</contato>
</mensagem>
<mensagem>
<nome>Beltrano</nome>
<contato>22222</contato>
</mensagem>

E como eu to usando JDom, meu código ta assim:

System.out.println(elemento..getChildText( "nome"));
System.out.println(elemento..getChildText( "contato"));

como tem dois contatos, se eu colocar no “for” ou “while”, ele fica percorrendo somente o primeiro.
Como resolver isso?

9 Respostas

Lavieri

vc precisa ter um ROOT … um marca raiz, que não se repita, algo assim

<app> <mensagem> <nome>Fulano</nome> <contato>11111</contato> </mensagem> <mensagem> <nome>Beltrano</nome> <contato>22222</contato> </mensagem> <mensagem> <nome>Abacwssda</nome> <contato>12321312</contato> </mensagem> <mensagem> <nome>adsadaDAds</nome> <contato>12313123</contato> </mensagem> <mensagem> <nome>Adsadsa</nome> <contato>435435</contato> </mensagem> </app>

ai da pra recuperar assim

public static void main(String ... args) throws Throwable { URL url = new URL("file:///C:/xml.xml"); SAXReader reader = new SAXReader(); final Document document = reader.read(url); Iterable<Element> iterable = new Iterable<Element>() { @Override @SuppressWarnings("unchecked") public Iterator<Element> iterator() { return document.getRootElement().elementIterator(); } }; for (Element e : iterable) { System.out.println("nome = "+ e.elementText("nome")); System.out.println("contato = "+ e.elementText("nome")); } }

só uma observação, não precisa criar um new Iterable … mais é que não gosto de iterator ^^ uhaauhhua … prefiro colocar direto no for

renzonuccitelli

Ou usa o JColtrane e não se preocupa mais com isso…

Lavieri

eu não sei exatamente c tem que ter o root… sei que meu navegador não le XML sem o raiz… e só sei usar o dom4j quando tem raiz ^^

renzonuccitelli

Fiz um exemplo aqui:

public class LeitorDeContatoNomeEContato {
	@BeforeElement(tag="mensagem", elementDeep = 1)
	@EndElement(tag="nome")
	private void imprimirNome(@Body String nome){
		System.out.println(nome);
	}
	
	
	@BeforeElement(tag="mensagem", elementDeep = 1)
	@EndElement(tag="contato")
	private void imprimirContato(@Body String contato){
		System.out.println(contato);
	}
	
	public static void main(String[] args) { 
        SAXParser parser=null; 

        try { 
              parser= SAXParserFactory.newInstance().newSAXParser(); 
        } catch (ParserConfigurationException e) { 
              e.printStackTrace(); 
        } catch (SAXException e) { 
              e.printStackTrace(); 
        } 

        File file=new File("src\xml\msg.xml"); 
        if(parser!=null){ 
              InputSource input=new InputSource(file.getAbsolutePath()); 
              try { 
                    parser.parse(input,new JColtraneXMLHandler(new LeitorDeContatoNomeEContato())); 
              } catch (SAXException e) { 
                    e.printStackTrace(); 
              } catch (IOException e) { 
                    e.printStackTrace(); 
              } 
        } 
  } 


}

quando fiz o parsing do seu arquivo, deu uma exceção:

Fulano
11111
org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.

Ou seja, ele imprimiu os dois primeiro e deu pau quando viu que não tem root. Aí eu coloquei um root no seu documento e imprimiu tudo certinho:

Fulano
11111
Beltrano
22222

Ou seja, o Lavieri tava certo. Eu tb não sabia que era necessário um root. Vivendo e aprendendo...

Lavieri

pois é renzonuccitelli … ^^ … o mesmo que falei la pro dom4j … que faltava o ROOT … ai coloquei APP de root só como exemplo

J

Mas a duvida ainda persiste…

e se o arquivo não tiver diretamente ligado ao elemento raiz?

por exemplo…

<texto>
      <mensagemGeral>
             <mensagem>   
                    <nome>Fulano</nome>   
                   <contato>11111</contato>   
            </mensagem>   
            <mensagem>   
                   <nome>Beltrano</nome>   
                   <contato>22222</contato>   
           </mensagem>  
     </mensagemGeral>
</texto>

dessa forma eu tambem pego o valor iterando?

renzonuccitelli

Sim, da mesma forma vc vai ter que iterar. Pelo que vi, o root é requerido mesmo, o que já era de se esperar pela Exceção lançada.

Lavieri
javaCBA:
Mas a duvida ainda persiste....

e se o arquivo não tiver diretamente ligado ao elemento raiz?

por exemplo....

<texto>
      <mensagemGeral>
             <mensagem>   
                    <nome>Fulano</nome>   
                   <contato>11111</contato>   
            </mensagem>   
            <mensagem>   
                   <nome>Beltrano</nome>   
                   <contato>22222</contato>   
           </mensagem>  
     </mensagemGeral>
</texto>

dessa forma eu tambem pego o valor iterando?

Pega sim, basta primeiro vc pegar o elemento mensagemGeral, depois é so fazer pegar o iterator dos elementos dele, e usar em um for ou onde achar conviniente...

Conforme o XML que vc enviou, uma das formas de solicionar é assim:
public static void main(String ... args) throws Throwable { 
		URL url = new URL("file:///C:/xml.xml");  
		SAXReader reader = new SAXReader();  
		final Document document = reader.read(url);  
		for (Element e : getIterable(document,"mensagemGeral")) {  
			System.out.println("nome = "+ e.elementText("nome"));  
			System.out.println("contato = "+ e.elementText("nome"));  
		}
	}
	private static Iterable<Element> getIterable(final Document document, final String element) {
		return new Iterable<Element>() {  
			@Override @SuppressWarnings("unchecked")  
			public Iterator<Element> iterator() {  
				return document.getRootElement().element(element).elementIterator();
			}  
		};
	}

Note que ele busca o elemnto "mensagemGeral", e faz um iterator a partir dele.... e coloca dentro de um Iterable, pra vc usar facilmente em um for

veja que quebrei em 2 métodos... criei um método apenas para montar o Iterable....

os parametros do método getIterable, são:
- "document" que é o documento ao qual deve-se buscar os elementos
- "element" que é uma String com o nome do sub elemento que se deseja criar o Iterable, que no seu caso é "mensagemGeral"

EDIT: apenas para facilitar, os imports usados nesse exemplo são
import java.net.URL;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
P
ola, desculpa se estou postando na pagina errada. Mais estou com uma duvida e sou novato em java. Encontrei um codigo para ler um xml de retorno de um outro aplicativo. Quando faço a leitura do xml ele me retorna resultado null segue o codigo:
File f = new File("C:/mural.xml");

                        //Criamos uma classe SAXBuilder que vai processar o XML4
org.jdom.input.SAXBuilder sb = new org.jdom.input.SAXBuilder();

//Este documento agora possui toda a estrutura do arquivo.
                org.jdom.Document d = null;
                try {
                    d = sb.build(f);
                } catch (JDOMException ex) {
                    Logger.getLogger(Assistec.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IOException ex) {
                    Logger.getLogger(Assistec.class.getName()).log(Level.SEVERE, null, ex);
                }

   //Recuperamos o elemento root
   org.jdom.Element mural = d.getRootElement();

   //Recuperamos os elementos filhos (children)
   List elements = mural.getChildren();
   Iterator i = elements.iterator();

   //Iteramos com os elementos filhos, e filhos do dos filhos
   while (i.hasNext()) {
      Element element = (Element) i.next();
      System.out.println("Códido:"+ element.getChildText("cStat"));
   }
segue o xml
<?xml version="1.0" encoding="utf-8"?>
<retAltConfUniNFe>
<cStat>1</cStat>
<xmotivo>Configuracao do UniNFe alterada com sucesso</xmotivo>
</retAltConfUniNFe>
Criado 16 de janeiro de 2009
Ultima resposta 8 de jun. de 2012
Respostas 9
Participantes 4