Uma característica muito interessante porém pouco utilizada no VB.Net são os XML Literals. Pegando carona na idéia do Linq, a equipe do VB.Net introduziu o XML Literals como forma de simplificar/flexibilizar a manipulação de dados XML em memória ou peristidos com uma sintaxe mais direta e que pode ser associada ao Linq to XML. Na sintaxe do XML Literals o XML é manipulado como se estivéssemos digitando diretamente XML ao invés de código que gere XML. Para entendermos melhor como isso funciona, vamos considerar um arquivo XML com a seguinte estrutura:
<?xml version="1.0" encoding="utf-8" ?>
<som>
<producoes>
<album nome="Nothing Safe" artista="Alice in Chains" ano="1999">
<selo>Sony Music Distribution</selo>
</album>
<album nome="Return of the Killer A's: The Best of Anthrax" artista="Anthrax" ano="1999">
<selo>Beyond</selo>
</album>
<album nome="Starfish" artista="The Church" ano="1988">
<selo>Arista</selo>
</album>
<album nome="Collective Soul" artista="Collective Soul" ano="1995">
<selo>Atlantic</selo>
</album>
</producoes>
</som>
Para trabalharmos esse arquivo em memória teremos que carregá-lo, mas ao invés de recorrermos ao System.Xml para isso, vamos usar XML Literals através do namespace System.Xml.Linq:
Dim xmlDoc As XDocument = XDocument.Load("C:\Som.xml")
A partir daí para ler elementos do arquivo, usamos XML Literals. Por exemplo, para identificar todos os selos presentes no arquivo podemos montar o código assim:
Debug.WriteLine("Selos:")
For Each xeAlbum As XElement In xmlDoc...<producoes >.<album>
Debug.WriteLine(xeAlbum...<selo>.Value)
Next
No trecho acima, xmlDoc...<producoes>
se refere à todos os elementos producoes que sejam descendentes do elemento raiz, enquanto .<album> representa um elemento album descendente de <producoes>. Percorremos então todos os albums de <producoes> lendo o valor do elemento <selo>. Agora considere o trecho abaixo:
Debug.WriteLine("Albuns:")
For Each xeAlbum As XElement In xmlDoc...<producoes>.<album>
Debug.WriteLine(xeAlbum.@nome)
Next
Aqui a idéia é obter o nome de cada album. Como os nomes estão representados por atributos, utilizamos o caracter @ como em @nome
para ler o valor do atributo. Se o objetivo for obter dados genéricos sobre os elementos, isso também é possível. Aqui obtemos o total de albuns existentes no arquivo:
Dim intAlbums As Integer = xmlDoc...<producoes>.<album>.Count
Linq to XML e XML Literals
O XML Literals incorpora os recursos do Linq de forma a simplificar ainda mais a leitura dos dados. Por exemplo, podemos localizar todos os albuns produzidos em um determinado ano usando expressões Lambda:
Dim enumAno = xmlDoc...<producoes>.<album>.Where(Function(a) a.@ano = 1999)
For Each xeAlbum In enumAno
Debug.WriteLine(xeAlbum.@nome)
Next
Ou claúsulas Linq, como neste exemplo para localizar um album especifico trazendo seu nome e artista:
Dim xeItem = (From b In xmlDoc...<album> _
Where b.@nome.ToString.Contains("Starfish")).FirstOrDefault
Debug.WriteLine(String.Format("{0} - {1}", xeItem.@nome, xeItem.@artista))
Repare que em ambos os exemplos as variáveis são por inferência, do tipo IEnumerable(Of XElement) e XElement, o que desfaz a necessidade de declararmos o tipo do objeto. Na verdade, esse recurso pode ser desligado a nível de projeto ou módulo através da cláusula Option Infer Off, embora não seja exatamente necessário.
Vimos como ler dados em XML na memória utilizando Linq to XML e XML Literals. Para saber como criar aqrquivos XML usando XML Literals, leia o próximo artigo sobre o assunto.