LINQ - Apresentando LINQ To XML


Uma das grandes novidades da plataforma .NET versão 3.5 é o projeto LINQ que introduz um modelo de programação que permite acessar diretamente uma fonte de dados , documentos XML, estrutura de dados, coleção de objetos, etc. usando uma sintaxe parecida com a linguagem SQL.

Já escrevi diversos artigos sobre LINQ To SQL , um dos membros do projeto LINQ, e, neste artigo vou dar uma visão resumida sobre o LINQ To XML outro membro integrante do LINQ.

O LINQ to XML é um provedor de dados LINQ que é implementado no namespace System.Xml.LINQ a partir da versão 3.5 da plataforma .NET. Ele fornece um modelo de programação que permite ler, construir e escrever dados XML. Você pode usar LINQ To XML para realizar consultas LINQ sobre dados no formato XML que podem ser retornados do arquivo de sistemas, de uma URL HTTP remota, de um web service ou partir de qualquer XML em memória existente.

O LINQ To XML fornece mais recursos e facilidades para tratar com XML do que a API presente no namespace System.XML(XmlReader/XmlWriter) da versão anterior da plataforma .NET, sendo também mais eficiente, por usar menos memória, que a API DOM do XmlDocument fornece.

Apenas para mostrar uma comparação entre as duas técnicas temos abaixo um trecho de um documento XML e em seguida o código para a criação do documento usando a API DOM e o LINQ to XML:

arquivo XML
<contatos>
   <contato>
      <nome>Macoratti</nome>
      <fone tipo="residencia">9986-55-44</fone>
      <fone tipo="trabalho">9986-25-85</fone>
      <endereco>
         <rua>rua Mirassol, 100</rua>
         <cidade>Brasilia</cidade>         
         <estado>DF</estado>
         <postal>7860-456</postal>
      </endereco>
   </contato>
</contatos>		

Vamos criar um projeto do tipo Windows Application  no VB 2008 Express para exibir o documento XML criado em um TextBox.

Abra o VB 2008 Express e crie um novo projeto Windows Application e no formulário padrão form1.vb inclua dois botões de comando e uma caixa de texto - TextBox1 - com sua propriedade Multiline igual a True. a seguir inclua o código abaixo no evento Click dos respectivos botões:

Button1 - Código para gerar o arquivo XML usando a API DOM

Dim doc As New XmlDocument()

Dim nome As XmlElement = doc.CreateElement("nome")

nome.InnerText = "Macoratti"

Dim fone As XmlElement = doc.CreateElement("fone")

fone.SetAttribute("tipo", "residencia")

fone.InnerText = "9986-55-44"

Dim fone1 As XmlElement = doc.CreateElement("fone")

fone1.SetAttribute("tipo", "trabalho")

fone1.InnerText = "9986-25-85"

Dim rua As XmlElement = doc.CreateElement("rua")

rua.InnerText = "Rua Mirassol , 100"

Dim cidade As XmlElement = doc.CreateElement("cidade")

cidade.InnerText = "Brasilia"

Dim estado As XmlElement = doc.CreateElement("estado")

estado.InnerText = "DF"

Dim postal As XmlElement = doc.CreateElement("postal")

postal.InnerText = "77860-456"

Dim endereco As XmlElement = doc.CreateElement("endereco")

endereco.AppendChild(rua)

endereco.AppendChild(cidade)

endereco.AppendChild(estado)

endereco.AppendChild(postal)

Dim contato As XmlElement = doc.CreateElement("contato")

contato.AppendChild(nome)

contato.AppendChild(fone)

contato.AppendChild(fone1)

contato.AppendChild(endereco)

Dim contatos As XmlElement = doc.CreateElement("contatos")

contatos.AppendChild(contato)

doc.AppendChild(contatos)


TextBox1.Text = doc.InnerXml

 

Button2 - Código para gerar o XML usando LINQ to XML
 Dim contatos As New XElement("contatos", _
                                     New XElement("contato", _
                                     New XElement("nome", "Macoratti"), _
                                     New XElement("fone", "9986-55-44", New XAttribute("tipo", "residencia")), _
                                     New XElement("fone", "9986-85-25", New XAttribute("tipo", "trabalho")), _
                                     New XElement("endereco", New XElement("rua", "Rua Mirassol, 100"), _
                                        New XElement("cidade", "Brasila"), _
                                        New XElement("estado", "DF"), _
                                        New XElement("postal", "7786-456"))))
  TextBox1.Text = contatos.ToString

Perceba que no código onde usamos DOM os nós, incluindo elementos e atributos, precisam ser criados no contexto de um documento XML:


Dim
doc As New XmlDocument()

Dim nome As XmlElement = doc.CreateElement("nome")
 

O conceito de documento XML é fundamental no DOM e os nós XML são criados no contexto do documento XML, se você desejar usar um elemento através de múltiplos documentos vai precisar importar os nós através do documento. O LINQ To XML simplifica essa abordagem.

No LINQ to XML você pode criar elementos XML diretamente: Ex: Dim nome As New XElement("nome")

Vejamos a seguir a figura que mostra a hierarquia de classes do LINQ To XML

Analisando a hierarquia de classes destacamos:

As principais classes do LINQ To XML são:

Nome da Classe Descrição
XDocument Atua como um container para a árvore XML e deve ser usado somente se necessário. Você pode salvar o documento com um arquivo XML.
XElement Permite criar elementos , modificar o conteúdo dos elementos (incluir, remover, modificar elementos filhos), modifica os atributos dos elementos , salvar como um arquivo XML.
XAttribute Usado para criar um par nome/valor no interior de um elemento do arquivo XML.
XName Representa um nome completo XML consistindo de um objeto XNamespace e do nome local.
XComment Representa um comentário XML.
XDocumentType Representa um documento XML DTD - Document Type Definition.
XProcesingInstruction Representa o processamento de uma instrução de um documento XML.
XTest Representa um nó Texto.
XDeclaration Representa uma declaração XML.

Vamos ver então como esse tal de LINQ To XML funciona...

Para poder usar os recursos do LINQ você vai precisar possuir instalado o Visual Basic 2008 Express Edition: Se não tiver pegue aqui: Visual Basic 2008 Express Edition

Criando documentos XML

Para criar documentos completos XML você deve primeiro instanciar o objeto XDocument e então incluir o elemento XElement, XAtributte ou outra entidade que o documento necessita. Se você deseja criar apenas um fragmento XML a classe XElement é tudo que você precisa. Vamos criar a seguir um documento XML contendo nomes.

A estrutura do arquivo XML criado deverá ser igual a:


<clientes>
  <cliente codigo="1">
    <nome>Macoratti</nome>
    <email>macoratti@yahoo.com</email>
  </cliente>
  <cliente codigo="2">
    <nome>Jessica</nome>
    <email>jessica@bol.com.br</email>
  </cliente>
</clientes>

Abra o VB 2008 e crie um novo projeto do tipo Windows Application com nome VB8_LNQ_XML1.

No formulário form1.vb inclua um componente TextBox com nome txtXmlDoc e um botão de comando - Gerar XML segundo o seguinte leiaute:

A seguir temos duas maneiras distintas de obter o XML:

1- Usando somente a classe XElement podemos gerar diretamente o XML desejado. Inclua o código abaixo no evento Click do botão de comando:

Dim xmlDoc As New XElement("clientes", _
                   New XElement("cliente", _
                       New XAttribute("codigo", "1"), _
                       New XElement("nome", "Macoratti"), _
                       New XElement("email", "macoratti@yahoo.com")), _
                   New XElement("cliente", _
                       New XAttribute("codigo", "2"), _
                       New XElement("nome", "Jessica"), _
                       New XElement("email", "jessica@bol.com.br")))

        txtXmlDoc.Text = xmlDoc.ToString

2- Usando o objeto Xdocument

Neste caso vamos criar uma função chamada CriarDocumentoXML() conforme abaixo:

Function criarDocumentoXML() As XDocument

        Return New XDocument( _
            New XDeclaration("1.0", Nothing, Nothing), _
                   New XElement("clientes", _
                   New XElement("cliente", _
                       New XAttribute("codigo", "1"), _
                       New XElement("nome", "Macoratti"), _
                       New XElement("email", "macoratti@yahoo.com")), _
                   New XElement("cliente", _
                       New XAttribute("codigo", "2"), _
                       New XElement("nome", "Jessica"), _
                       New XElement("email", "jessica@bol.com.br"))))


    End Function

Agora no evento Click do botão de comando inclua o código:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim xmldoc = criarDocumentoXML()
        txtXmlDoc.Text = xmldoc.ToString
    End Sub

O resultado final seria o mesmo:

Podemos ainda criar o documento XML reescrevendo a função CriarDocumentoXML usando o seguinte código:

 Function criarDocumentoXML() As XDocument

        Return <?xml version="1.0" encoding="UTF-16" standalone="yes"?>
               <clientes>
                   <cliente codigo="1">
                       <nome>Macoratti</nome>
                       <email>macoratti@yahoo.com</email>
                   </cliente>
                   <cliente codigo="2">
                       <nome>Jessica</nome>
                       <email>jessica@bol.com.br</email>
                   </cliente>
               </clientes>

    End Function

O código acima além de mais legível apresenta o xml agora sendo usado como um tipo do Visual Basic.

Realizando Consultas

Vamos realizar agora uma consulta no documento criado usando LINQ To XML.

Inclua um novo controle TextBox com o nome txtXmlConsulta com Multiline=true e um botão de comando : Consulta XML, conforme o leiaute abaixo:

Agora inclua no evento Click do botão de comando Consulta XML o código para obter o cliente de código igual a 2:

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim xmldoc = criarDocumentoXML()

        Dim clientes = From c In xmldoc...<cliente> _
                             Where c.@codigo = "2"

        For Each cliente In clientes
            txtXmlConsulta.Text = cliente.ToString
        Next

    End Sub

Executando o projeto obtemos o seguinte resultado:

Carregando um arquivo XML

Podemos carregar um arquivo XML já existente o  LINQ To XML oferece múltiplas opções de fontes de entrada incluindo : um arquivo, um XMLReader, um TextReader ou uma string.

Se a entrada for uma string usamos o método Parse. Veja um exemplo:

Dim contatos As XElement = XElement.Parse("<?xml version= '1.0'?>" & _
                                                        "<clientes>" & _
                                                            "<cliente codigo='1'>" & _
                                                                "<nome>Macoratti</nome>" & _
                                                                "<email>macoratti@yahoo.com</email>" & _
                                                            "</cliente>" & _
                                                            "<cliente codigo='2'>" & _
                                                                "<nome>Jessica</nome>" & _
                                                                "<email>jessica@bol.com.br</email>" & _
                                                            "</cliente>" & _
                                                        "</clientes>")

        txtCarregaXML.Text = contatos.ToString

Para carregar um arquivo XML de outra fonte use o método Load:

Dim testeXML As XElement = XElement.Load("c:\teste\Macoratti.xml")

Como vimos a API  LINQ To XML se propõe a efetuar o tratamento XML de uma maneira mais eficiente e com desempenho melhor.

Aguarde em breve mais artigos sobre LINQ To XML...

Pegue o projeto completo aqui : VB8_LINQ_XML1.zip

Referências:


José Carlos Macoratti