Clique e receba as novidades quentinhas no Telegram

xml_51

Olá pessoal, tudo bom?

Uma dúvida recorrente dos DEVs Windows Phone é sobre a “leitura” de dados a partir de documentos XML e em especial aqueles que são oriundos de webservices ou chamadas REST, apesar de isso ser basicamente a mesma coisa quando os arquivos XML são locais à APP.

Para exemplificar esse post vou utilizar o retorno XML do webservice https://wcf-concursos.azurewebsites.net/Consulta.svc/xml/professor-etec, que devolve a seguinte estrutura de dados:



 
   Adamantina
   2015-01-27T00:00:00
   https://cpssitevm.cloudapp.net/dgps/selecoespublicas/ProcessoSeletivo/055/055/01/2015/055-01-2015-ps-27-01-2015.pdf
   Escola Técnica Estadual Professor Eudécio Luiz Vicente
   055/01/2015
   55
 
 
   Assis
   2015-02-11T00:00:00
   https://cpssitevm.cloudapp.net/dgps/selecoespublicas/ProcessoSeletivo/095/095/02/2015/095-02-2015-ps.pdf
   Escola Técnica Estadual Pedro D'Arcádia Neto
   095/02/2015
   95
 
......

De posse da estrutura do XML, uma das primeiras coisas a observar é se o documento possui o atributo xmlns. Caso possua, será necessário utilizarmos a classe XNamespace para referenciar seus elementos filhos, situação que nesse exemplo iremos observar.

Declarando uma classe para representar os dados que se deseja obter do documento XML

Para facilitar o trabalho de recuperação dos dados do documento XML, indico a criação de uma classe para representação das informações desejadas. No exemplo, a classe (Escola.cs) será utilizada como base para montar uma lista com todos os nomes de escolas e cidades representadas na estrutura do XML.

namespace LeituraXML
{
  public class Escola
  {
     private string _cidade;
     public string Cidade
     {
       get { return _cidade; }
       set { _cidade = value; }
     }

     private string _nomeEscola;
     public string NomeEscola
     {
       get { return _nomeEscola; }
       set { _nomeEscola = value; }
     }
  }
}

Montando o layout da aplicação XAML

Abaixo demonstro o trecho de código do documento XAML responsável por montar a interface da aplicação. Em especial observe o elemento ListBox e seu respectivo DataTemplate. Reparem que os mesmos coincidem com a estrutura da classe Escola.cs demonstrada acima.

exemplo-xml

...
...

  
  
  

  
    
      
        
          
          
        
      
    
  

...
...

Obtendo o documento XML e recuperando seus dados a partir de uma consulta LINQ

Como o documento XML que iremos tratar nesse exemplo é oriundo de uma URL, utilizaremos a classe WebClient para realizar o download do mesmo. Para mais detalhes sobre o uso do WebClient, acesse o post Classe WebClient para download de conteúdo da web no formato de dados binários ou strings.

...
namespace LeituraXML
{
  public partial class MainPage : PhoneApplicationPage
  {
    //Declaração de um WebClient para download do arquivo XML resultante da chamada REST
    WebClient wc = new WebClient();

    // Construtor
    public MainPage()
    {
      InitializeComponent();

      //Toda vez que o WebClient atualiza seu status de download o método DownloadProgressChanged será executado
      wc.DownloadProgressChanged += wc_DownloadProgressChanged;
      //Ao terminar o download do conteúdo o método DownloadStringCompleted será executado
      wc.DownloadStringCompleted += wc_DownloadStringCompleted;
      //O método DownloadStringAsync inicia o download do conteúdo especificado pela Uri
      wc.DownloadStringAsync(new Uri("https://wcf-concursos.azurewebsites.net/Consulta.svc/xml/professor-etec"), "conteudo");
    }

    void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
      //Esse if é utilizado para ter certeza que iremos processar apenas o conteúdo específico do WebClient em questão
      if (e.UserState == "conteudo")
         //O código abaixo exibe no TextBlock txtAguarde o andamento do download do documento XML
         txbAguarde.Text = e.BytesReceived.ToString() + "/" + e.TotalBytesToReceive.ToString();
    }

    void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
      //Desligando o ProgressBar
      pgbDownload.IsIndeterminate = false;
      //Caso não tenha ocorrido nenhum problema ou o processo tenha sido cancelado
      if (e.Error == null && !e.Cancelled)
      {
        //Retirando o status de progressão do download da tela
        pgbDownload.Visibility = System.Windows.Visibility.Collapsed;
        txbAguarde.Visibility = System.Windows.Visibility.Collapsed;

        /****************************************************************
         * DECLARAÇÃO DOS ELEMENTOS NECESSÁRIOS PARA RECUPERAÇÃO DOS DADOS
         * REPARE QUE OS DADOS DO DOCUMENTO ESTÃO NO OBJETO dados E QUE
         * DECLARAMOS UM OBJETO ns PARA REPRESENTAÇÃO DO NAMESPACE DO
         * DOCUMENTO XML. O NAMESPACE NÃO SERIA NECESSÁRIO SE O DOCUMENTO
         * XML NÃO TIVESSE O ATRIBUTO xmlns EM SUA DECLARAÇÃO.
        */
        XElement dados = XElement.Parse(e.Result);
        XNamespace ns = "https://schemas.datacontract.org/2004/07/wcf_dados.Modelo";

        //Recuperando os dados desejados via consulta LINQ
        var escolas = (from d in dados.Descendants(ns + "ProcessoSeletivo")
                      orderby d.Element(ns + "Cidade").Value
                      select new Escola
                          {
                            NomeEscola = d.Element(ns + "NomeUnidade").Value,
                            Cidade = d.Element(ns + "Cidade").Value
                          }).ToList();
        //Indicando a origem dos dados para o ListBox
        lbEscolas.ItemsSource = escolas;
      }
      //Tratamento de erros
      else
        txbAguarde.Text = e.Error.InnerException.ToString();
    }
...
...

Espero ter ajudado e aproveito para agradecer meus ex-alunos e colegas Renan D. Buarraj e Lucas Azambuja pelas dicas e pelo webservice.

Grande abraço,

Eduardo Henrique Rizo (@eduardorizo)

MCP

Posts Relacionados: 

Fonte: Blog do Eduardo H. Rizo