Desenvolvimento - XML

Acessando XML remoto e buscando informações com o Namespace System.Xml.XPath

Há certas ocasiões onde precisamos obter informações de um arquivo xml de outro site por exemplo e por mais que seja um XML não podemos encará-lo como um WebService, pois não foi criado com tal objetivo. Neste artigo mostro a navegação em um documento XML utilizando o Namespace XPath.

por Rodrigo Glauser



Há certas ocasiões onde precisamos obter informações de um arquivo xml de outro site por exemplo e por mais queseja um XML não podemos encará-lo como um WebService,pois não foi criado com tal objetivo. Esses arquivos xmlna maioria das vezes não podemser importados para um DataSet com o Método ReadXml por sua incompatibilidade na formalização da estrutura dodocumento e nesta hora é necessário procurar classes específicas no Namespace System.XML. Neste artigo mostro a navegação em um documento XML utilizando o Namespace XPath.

No .NET framework 1.1 há um Namespace inteiro para a utilização deste padrão, o System.XML.XPath. Entretando antes de utilizá-lo o programador terá que saber os conceitos de um Arquivo XML.

Estrutura de um Documento XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<brasil>
<cidade id="1">
<nome>Itararé</nome>
<populacao>65000</populacao>
<idade>690</idade>
</cidade>
<!-- Isto é um Comentário -->
<cidade id="2">
<nome>Ponta Grossa</nome>
<populacao>300000<populacao>
<idade>1800</idade>
</cidade>
</brasil>

Onde:
<?xml version="1.0" standalone="yes/no" encoding="encoding"?> - Dos atributos, version é o único obrigatório e deve ter o valor = "1.0".
<brasil> - é um elemento, neste caso podemos chamá-lo de elemento Pai.
<nome> - Dados em um documento XML são hierárquicos. Elementos podem conter outros elementos que são chamados de elementos filhos.O elemento nome é elemento filho do elemento cidade:
id="2" - id é um Atributo. Atributos são informações adicionais sobre um elemento.
Ponta Grossa - é o Texto ou Valor do Elemento nome.

Agora que já conhecemos os conceitos básicos do XML podemos começar a utilizar o XPath para fazer a pesquisa no documento.O Documento que iremos pesquisar será o de boletim das condições metereológicas do Paraná que está disponível em http://www.simepar.br/tempo/boletimxml.jsp

1º Passo - Fazer a solicitação do documento

Antes de tudoimporte osnamespacesSystem.Net , System.Xml e System.Xml.XPath. Como o nosso documento está em um site remoto na internet faremos a requisição com as classes WebRequest e WebResponse.

Dim myRequest As WebRequest
Dim myResponse As WebResponse
Dim VarStream As Stream
Dim xmlreader As XmlTextReader
Dim xpathDoc As XPathDocument

If Me.Cache("xpathDoc") Is Nothing Then
" Verifica se objeto xpathDoc está em Cache
myRequest = WebRequest.Create("http://www.simepar.br/tempo/boletimxml.jsp")
" Criação do Objeto myRequest que prepara a requisição que será enviada ao URL remoto
myResponse = myRequest.GetResponse()
" Faz a requisição
VarStream = myResponse.GetResponseStream()
" O Conteúdo da requisição fica armazenado no objeto VarStream
xmlreader = New XmlTextReader(VarStream)
" O XmlTextReader é necessário para instanciar o XPathDoc
xpathDoc = New XPathDocument(xmlreader)
" XPathDocument é a classe que contém todo o documento XML
" Se você desejar abrir um xml no servidor utilize:
" xpathDoc = new XPathDocument(Server.MapPath("arquivo.xml"))
Me.Cache.Insert("xpathDoc", xpathDoc, Nothing, _
Now.AddMinutes(60), Caching.Cache.NoSlidingExpiration)
" Coloca em Cache o objeto xpathDoc para otimização da página.
" Isso porque o conteúdo do XML não apresenta alterações frequentes,
" portanto a requisição pode ser feita em períodos determinados.
" Neste caso60 minutos.

Else
xpathDoc = CType(Me.Cache("xpathDoc"), XPathDocument)
" Utilização do objeto em cache otimizando a performance.
End If

2º Passo - Utilizando o XPath

Agora com o documento requisitado no objeto Stream já podemos iniciar a pesquisa porém antes vamos entender melhor o que é a Tecnologia XPath.
XPath é um padrão da W3C, lançado em 1999 como um linguagem para endereçamento de partes de um documento XML. XPath usa expressões para localizar nós ( elementos ) em um XML. As expressões são simples de se usar e muito ricas em funcionalidades.

Fragmento do Documento XML da Simepar para exemplificar as expressões:
<?xml version="1.0" encoding="ISO-8859-1"?>
<boletim data="04/01/2005" periodo="tarde">
<municipio id="4106902" nome="Curitiba">
<dia1 data="04/01/2005" diadasemana="Ter">
<tempo>
<legendanoite id="14" icone="14.gif">nublado com chuva e trovoadas</legendanoite>
</tempo>
</dia1>
</municipio>
</boletim>

Exemplos de expressões:
A Expressão a seguir seleciona todos os elementos dia1 de todos os elementos municipio:
/boletim/municipio/dia1
Resultado:
<dia1 data="04/01/2005" diadasemana="Ter"></dia1>
A Expressão a seguir seleciona todos os elementos dia1 e seus elementos filhos:
/boletim/municipio/dia1/*
<dia1 data="04/01/2005" diadasemana="Ter">
<tempo>
<legendanoite id="14" icone="14.gif">nublado com chuva e trovoadas</legendanoite>
</tempo>

A Expressão a Seguir seleciona todos os elementos legendanoite que contenham o atributo id="14"
/boletim/municipio/dia1/tempo/legendanoite[@id="14"]
<legendanoite id="14" icone="14.gif">nublado com chuva e trovoadas</legendanoite>

As expressões são muito variadas, elas podem retornar elementos e também valores de atributos.Existem funções para as expressões e podem ser encontradas com maiores detalhes em http://www.w3schools.com/xpath/xpath_syntax.asp

Na Pratica com o XPath

"Continuando o código
Dim xmlNav As XPathNavigator
" Cria o Objeto da Classe Navigator que tem métodos para a navegação
"Tratamento de Erros
Try
xmlNav = xpathDoc.CreateNavigator()
Catch ex As XPathException
Response.Write(ex.Message)
Catch ex As Exception
Response.Write(ex.Message)
End Try
Dim xmlNI As XPathNodeIterator
" Criação do Objeto da Classe XPathNodeIterator
xmlNI = xmlNav.Select("/boletim/municipio[@id=4106902]/dia2/@data")
" Solicitação da pesquisa, neste caso estamos solicitando o atributo data do elemento dia2
"que é um elemento filho do elemento municipio que tem um atributo que colocamos como
"critério id=4106902 e é um elemento filho do elemento nó boletim.

"Obs: Os atributos são representados pelo simbolo @.
While (xmlNI.MoveNext())
Response.Write(xmlNI.Current.Value())
End While
" Outras expressões que poderiam ser utilizadas seriam:
""/boletim/municipio[@id=" & id & "]/dia2/@data"
""/boletim/municipio[@id=" & id & "]/dia2/@diadasemana"
""/boletim/municipio[@id=" & id & "]/dia3/tempo/legendadia/@icone"
""/boletim/municipio[@id=" & id & "]/dia3/tempo/legendadia"
""/boletim/municipio[@id=" & id & "]/dia3/temperatura/min"
""/boletim/municipio[@id=" & id & "]/dia3/temperatura/max"
""/boletim/municipio[@id=" & id & "]/dia3/vento/direcao"
""/boletim/municipio[@id=" & id & "]/dia3/vento/intensidade"
""/boletim/municipio[@id=" & id & "]/dia3/visibilidade"

Tudo bem, fizemos a pesquisa em um XML mas até agora a pesquisa retornou um atributo ou um valor de um elemento. Mas como fazer para buscar um elementoe seus filhos e percorrê-los??

xmlNI = xmlNav.Select("/boletim/municipio")
"Buscamos todos os elementos municipio
While (xmlNI.MoveNext())
"Percorremos cada um dos elementos municipio retornados
If xmlNI.Current.HasAttributes Then
" A Propriedade Current do objeto xmlNI é do tipo XmlPathNavigator e esta classe contém
"diversos métodos para mover em um nó e de informações. O Método HasAttributes é do
"tipo boolean e indica se há atributos neste elemento

xmlNI.Current.MoveToFirstAttribute()
"Se houver atributos vamos percorrer cada um deles e escrever na tela seu valor
Do
Response.Write(xmlNI.Current.Name & ":" & xmlNI.Current.Value & "<br>")
Loop While xmlNI.Current.MoveToNextAttribute
End If
End While

Como foi visto acima conseguimos resgatar informações dos atributos de um elemento.
Para percorrer um elemento filho você terá que utilizar ós métodos próprios para
isto. Eis uma tabela com os principais.

Método Que Faz?
MoveToFirst() Move ao primeiro elemento/atributo do nó atual
MoveToFirstAttribute() Move ao primeiro atributo do nó atual. Verifique se onó atual tem algumatributo antes.
MoveToFirstChild() Move ao primeiro elemento filho do nó atual. Verifique se o nó atual tem algum elemento filho antes.
MoveToNext() Move ao próximo elemento/atributo/valor do nó atual
MoveToNextAttribute() Move ao atributo seguinte.
MoveToNextChild() Nao disponível! Use MoveToNext() preferivelmente.
MoveToParent() Move ao pai do nó atual. Chame este método para retornar o cursor à posição original após ter processado seus atributos ou para percorrer elementos filhos.
MoveToPrevious() Move ao elemento/atributo/valor precedente do nó atual.
MoveToRoot() Move ao nó raiz.

O XPath é o namespace definitivoque procurávamos para fazer acesso em XML. O .NET só facilitou as coisas mas outras linguagens também podem usufluir de suas funcionalidades. Espero queeste artigopossaajudar à comunidade Dotnet.

A classe completa para acesso aos dados de previsão do tempo estão disponíveis aqui. ( Faça o download Simepar.vb.txt )

Aguardo comentários e até o próximo artigo

Rodrigo Glauser

Rodrigo Glauser - É líder do Grupo de Usuários Gup.NET Ponta Grossa/PR, desenvolvedor coorporativo da Masisa do Brasil LTDA, trabalha atualmente em um projeto de integração .NET e SAP em filiais da empresa localizadas no Brasil, Argentina, Chile, Venezuela e México, trabalha com .NET há 2 anos e com programação web há 4 anos. Também concentra esforços em soluções para internet na solucoesweb.com.
The Spoke:
http://br.thespoke.net/MyBlog/rglauser/MyBlog.aspx