Curso Windows Phone – Como ler dados de documentos XML usando LINQ como forma de consulta

xml_51Olá 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 http://wcf-concursos.azurewebsites.net/Consulta.svc/xml/professor-etec, que devolve a seguinte estrutura de dados:


<ArrayOfProcessoSeletivo xmlns="http://schemas.datacontract.org/2004/07/wcf_dados.Modelo" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
 <ProcessoSeletivo>
   <Cidade>Adamantina</Cidade>
   <DataFimInscricao>2015-01-27T00:00:00</DataFimInscricao>
   <Link>http://cpssitevm.cloudapp.net/dgps/selecoespublicas/ProcessoSeletivo/055/055/01/2015/055-01-2015-ps-27-01-2015.pdf</Link>
   <NomeUnidade>Escola Técnica Estadual Professor Eudécio Luiz Vicente</NomeUnidade>
   <NumeroAviso>055/01/2015</NumeroAviso>
   <Unidade>55</Unidade>
 </ProcessoSeletivo>
 <ProcessoSeletivo>
   <Cidade>Assis</Cidade>
   <DataFimInscricao>2015-02-11T00:00:00</DataFimInscricao>
   <Link>http://cpssitevm.cloudapp.net/dgps/selecoespublicas/ProcessoSeletivo/095/095/02/2015/095-02-2015-ps.pdf</Link>
   <NomeUnidade>Escola Técnica Estadual Pedro D'Arcádia Neto</NomeUnidade>
   <NumeroAviso>095/02/2015</NumeroAviso>
   <Unidade>95</Unidade>
 </ProcessoSeletivo>
......

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

...
...
<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  <TextBlock Text="Lista de Escolas" Style="{StaticResource PhoneTextAccentStyle}" />
  <TextBlock Text="Fazendo download dos dados. Aguarde..."
             Margin="0,50,0,0" Name="txbAguarde"
             HorizontalAlignment="Center" />
  <ProgressBar IsIndeterminate="True" Name="pgbDownload" />

  <ListBox Name="lbEscolas" Height="Auto" MaxHeight="570">
    <ListBox.ItemTemplate>
      <DataTemplate>
        <StackPanel Orientation="Vertical">
          <TextBlock FontSize="30" Text="{Binding NomeEscola}" />
          <TextBlock Text="{Binding Cidade}" />
        </StackPanel>
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
</StackPanel>
...
...

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("http://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 = "http://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

MCP

Posts Relacionados: 

[twitter-follow screen_name=’eduardorizo’ show_count=’yes’]

 

6 comentários em “Curso Windows Phone – Como ler dados de documentos XML usando LINQ como forma de consulta”

  1. Pingback: Free: Curso Windows Phone – Vários tópicos | Blog do Eduardo H. Rizo

  2. Olá Eduardo, você poderia fazer um tutorial básico de desenvolvimento para Windows Phone com o Visual Studio 2013 update 4 e o SDK do Windows Phone 8.1, seria de grande ajuda.

    1. Bom dia Kayque, tudo bom?

      Poderia especificar um pouco melhor seu pedido? Você gostaria que eu fizesse uma vídeo aula sobre como começar a criar um projeto Windows Phone a partir do zero?

      Abraços,
      Eduardo H. Rizo

Deixe um comentário para Kayque Moreira Cancelar resposta