No post anterior eu mostrei como acessar um XML de forma fortemente tipada criando um arquivo XSD.
Podemos facilitar muito mais ainda nossa vida utilizado o LINQ para executar nossas queries. O framework .Net possui embutido o Linq To XML mas pelo fato de não ser fortemente tipado, precisamos fazer vários castings, deixando o desenvolvimento mais complicado.
No entanto, a equipe XML da Microsoft está desenvolvendo o Linq to XSD. Ele está em versão Alpha, mas já está bem usável.
Em dois computadores que instalei tive problemas durante a instalação. Por isso, vou deixar um link para baixar o pacote já instalado. O LinqToXSD não passa de um exe, uma dll que é usada na geração das classes e uma dll que deverá ser referenciada no projeto:
Mostrarei como utilizar o LINQ to XSD usando o mesmo arquivo gpx do post anterior, no entanto, ao invés de gerar o arquivo XSD, usarei o arquivo XSD "oficial" com a definição dos campos.
Para identificar onde puxar o XSD oficial de um tipo de documento XML, basta olharmos no cabeçalho:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="" version="1.1"
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
Neste caso está indicando o endereço http://www.topografix.com/GPX/1/1/gpx.xsd . Ao acessar esse endereço, clique em Salvar Como para salvar uma cópia local.
O primeiro passo será a geração do arquivo fonte. Para isso,abriremos um prompt de comando no diretório onde está nosso xsd e digitaremos o comando LinqToXsd.exe gpx.xsd . Note que o arquivo LinqToXsd.exe deve estar visível no path, bem como as dlls:
Pronto! A parte mais difícil está pronta!
Crie uma nova solution no Visual Studio do tipo Console Application e com o botão direito sobre o projeto, adicione o gpx.cs gerado através da opção Add->Existing Item. O Visual Studio ira importar o arquivo xsd também automaticamente.
Antes de continuarmos, vamos trocar o Namespace do arquivo gerado. Por default, o LinqToXsd.exe usa o mesmo namespace do XSD, mas para nós isso ficará esquisito:
www.topografix.com.GPX.Item1.Item1
Abra o arquivo gpx.cs e altere o namespace. Sugiro o nome GPX11 (que é a versão do formato). Use o Search & Replace (CTRL+H) para substituir em todos os lugares. O nome dos tipos são gerados de acordo com a definição do XSD e normalmente não são muito amigáveis. Você pode alterá-los se for necessário.
Adicione uma referência para a DLL Microsoft.Xml.Schema.Linq.DLL que vem junto com o pacote do LinqToXSD.
Lendo um XML (gpx)
Da mesma forma que no LinqToSQL, no LinqToXSD também temos uma classe gerenciadora (Context no LinqToSQL). No nosso caso, a classe chama-se gpx (assim mesmo, em minúsculas).
Para instanciar um "objeto contexto" a partir de um XML, utilize o seguinte comando:
GPX.gpx documento = GPX.gpx.Load("gpx.gpx");
Agora todos os dados do XML estão disponíveis para consulta!
Veja um exemplo completo:
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
GPX.gpx documento = GPX.gpx.Load("gpx.gpx");
var tracks = from t in documento.trk
select t;
foreach (var segs in tracks)
{
foreach (var seg in segs.trkseg)
{
var minor = seg.trkpt.Min(w => w.ele);
var max = seg.trkpt.Max(w => w.ele);
var avg = seg.trkpt.Average(w => w.ele);
foreach (var tp in seg.trkpt)
{
Console.WriteLine("Latitude: {0} / Longitude {1}", tp.lat, tp.lon);
}
Console.WriteLine("Elevação Média do segmento : {0}", avg);
Console.WriteLine("Elevação Mínima do segmento: {0}", minor);
Console.WriteLine("Elevação Máxima do segmento: {0}", max);
}
}
Console.ReadLine();
}
}
Além das operações de consulta, você pode também alterar e/ou inserir informações em seu XML:
GPX.wptType p1 = new GPX.wptType();
p1.ele = 90;
p1.lat = 24;
p1.lon = 25;
GPX.trksegType seg1 = new GPX.trksegType();
seg1.trkpt.Add(p1);
GPX.trkType t1 = new GPX.trkType();
t1.trkseg.Add(seg1);
GPX.gpx doc = new GPX.gpx();
doc.trk.Add(t1);
doc.creator = "Bizness";
doc.Save("teste.gpx");
Abaixo você pode puxar o código completo e funcional.