XML Parser usando DOM - Problema com tag de 3º nível

4 respostas
renanXR3

Olá pessoal, estou com um problema, e gostaria que me ajudassem.

Tenho que ler um arquivo XML, e “popular” uma classe com suas informações.

Exemplo do XML (simplificado é claro):

<Xml>
  <Veiculo>
    <Dados>
      <Marca>GM</Marca
      <Modelo>Celta</Modelo>
    </Dados>
    <Placa>
      <Licenciamento>
        <Mes>1</Mes>
        <Final>0</Final>
      </Licenciamento>
    </Placa>
  </Veiculo>
</Xml>

Eu tenho uma classe para cada nó. (Veiculo, Dados, Placa, Licenciamento) E as tags que possuem os valores são os atributos das minhas classes.
Exemplo:

public class Veiculo extends ClasseXML {
  private Dados dados = new Dados();
  private Placa placa = new Placa();

  ... // Getters, Setters, e outros métodos
}

public class Dados extends ClasseXML {
  private String Marca = "";
  private String Modelo = "";

  ... // Getters, Setters, e outros métodos
}

OBS: Todas herdam da classe “ClasseXML”, pois nela eu tenho alguns métodos úteis. Mas não interfere no meu problema.

Bom, eu faço o seguinte para “popular” (realizar o Parse) do XML:

try {
      // Parse via DOM 
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse(xmlPathFile);

      // Nó (Document)
      Element noDoc = doc.getDocumentElement();

      // Leitura da tag "Veiculo"
      // Nós (Veiculo)
      NodeList nosVeiculo = noDoc.getElementsByTagName("Veiculo");

      // Nó (Veiculo)
      Element noVeiculo = (Element) nosVeiculo.item(0);
      Veiculo veiculo = new Veiculo();
      
      // tag Dados
      NodeList nosDados = noVeiculo.getElementsByTagName("Dados");
      Element noDados = (Element) nosDados.item(0);
      dados.Parse(noDados);

      // tag Placa
      NodeList nosPlaca = noVeiculo.getElementsByTagName("Placa");
      Element noPlaca = (Element) nosPlaca.item(0);
      placa.Parse(noPlaca);

      // Métodos para imprimir o dados do objeto "Veiculo"

    } catch (Exception e) {
      e.printStackTrace();
    }
// na Classe Dados
public boolean Parse(Element noDados) {
    try {
      // métodos para pegar os dados do XML
    } catch (Exception e) {
      // ...
    }
  }

// na Classe Placa
public boolean Parse(Element noPlaca) {
    try {
       // nó Licenciamento
      NodeList nosLicenciamento = noPlaca.getElementsByTagName("Licenciamento");
      Element noLicenciamento = (Element) nosLicenciamento.item(0);
      licenciamento.Parse(noLicenciamento);

    } catch (Exception e) {
      // ...
    }
  }

// na Classe Licenciamento
public boolean Parse(Element noDados) {
    try {
      // métodos para pegar os dados do XML
    } catch (Exception e) {
      // ...
    }
  }

Bom, eu omiti várias coisas, porque eu acho que não fazem diferença mostrar ou não. Caso seja necessário eu posto aqui.

O PROBLEMA: Quando eu mando fazer o Parse da tag “Dados”, ele faz direitinho, jogando os valores dos atributos tranquilamente. Quando eu mando fazer o Parse da tag “Placa”, ele NÃO acha o nó “Licenciamento”, trazendo sempre como nulo. Ou seja, eu acho que ele não consegue trazer os nós do 3º nível do XML!

Eu fiz um teste aqui, e ao invés disso:

NodeList nosLicenciamento = [color=red]noPlaca[/color].getElementsByTagName(“Licenciamento”);

eu mandei ele fazer isso:

NodeList nosLicenciamento = [color=red]noVeiculo[/color].getElementsByTagName(“Licenciamento”);

E ele achou o nó Licenciamento!

Para mim isso tá muito estranho. O nó “Licenciamento” não deveria estar dentro do nó “Placa”? Porque ele achou dentro de “Veiculo”? É uma limitação da API DOM (limitada até o 2º nível do XML?)? Falta setar ou configurar alguma propriedade?

Por favor me ajudem!!!

Agradeço desde já, a todos que me ajudarem!

4 Respostas

T

Hum… você não quer usar XPath? Ele ajuda bastante, já que você tem as coisas no DOM.

Pegar algo pela posição (item (0)), não pelo nome, é uma coisa que considero proibida, já que você pode ter problemas com elementos inesperados (como espaços em branco, comentários etc.).

Não pegue coisas pela posição.

Usar getElementsByTagName também não é muito legal, porque ele pega coisas demais.

renanXR3

Esse XPath posso usar com o DOM mesmo ou é outra API e preciso alterar meu código todo?

Tem alguma idéia melhor para usar ao invés de “getElementsByTagName”?

renanXR3

Já achei uma solução. Vou responder minhas perguntas acima:

É outra API. Tive que alterar todo o código, mas XPath é mil vezes mais simples (pelo menos pro meu caso) e não deu muito trabalho.

Caso use o DOM: não tenho solução melhor
Caso use o XPath: Sim, pois vc busca todas as informações pelo nome, e mesmo que este nome não seja encontrado, ela retorna vazio.

Bom, é isso.
Valeu.

T

Vou fazer um manifesto “Aprenda XPath já!” (não tão ambicioso quanto o “Dia do Orgulho Nerd” mas mais útil.)

Criado 22 de maio de 2009
Ultima resposta 26 de mai. de 2009
Respostas 4
Participantes 2