Translate this page now :



Gostou da Página?
Clique no botão abaixo para indicar esta página para um amigo!



Pesquisa personalizada
Pesquisar Dicas:








Quer saber mais?
Certifique-se como MCP em SQL Server
Faça um treinamento na Búfalo Informática


Trocando dados em XML com SQL Server Parte 2 : XPATH
Utilizando XPATH para fazer querys ao SQL Server


Continuando a série que iniciamos na última revista, nosso próximo passo é vermos como funcionam as querys via XPATH.

XPATH é uma escrita que nos permite fazer referencia a dados dentro de um arquivo XML hierarquicamente, de forma semelhante a que fazemos referência a um diretório no disco. Dai que acessar dados via XPATH é aparentemente simples, bastando completar a URL com o caminho referente aos dados.

Nos exemplos de query via URL que vimos no artigo anterior criamos um diretório virtual chamado SQL utilizando o snap-in de configuração de suporte a XML do SQL Server. Neste artigo faremos os exemplos a partir deste diretório virtual, que aponta para uma pasta c:\testexml e para o banco PUBS do SQL Server.

Para realizar a query via XPATH, porém, é necessário criar um virtual name. Existem 3 tipos de virtual name : dbobject, schema e template.

Para distinguir os 3 tipos primeiramente precisamos distinguir 2 tipos de recuperação de dados : A recuperação binária e a recuperação em XML. A recuperação binária realiza a transmissão de dados de forma binária, como se encontram. Pode ser utilizada para recuperar fotos, por exemplo, tirando isso não tem grande utilidade. Permite apenas a recuperação de um campo por vez.

Já a recuperação em XML faz com que os dados sejam transmitidos em XML para o client. Neste caso o volume de campos recuperados pode ser maior, podendo até mesmo ser montada uma estrutura hierárquica para a recuperação.

Como o XML é muito flexivel, para que seja feita a recuperação de dados via XPATH em formato XML é necessário que haja uma especificação do formato do XML de retorno, ou seja, a estrutura de seus elementos. A Microsoft vem desenvolvendo uma linguagem para este fim chamada XML Schemas, na verdade uma linguagem derivada do XML. O XML Schemas ainda não encontra-se totalmente aprovado pelo W3C, mas versões preliminares já foram aprovadas. A primeira delas foi o XDR, atualmente já houve uma evolução para o XSD. Vamos inicialmente ver exemplos utilizando XDR.

Vale mencionar que a utilização do XDR é compreendida pelo SQL Server 2000, mas a utilização do XSD depende da instalação de uma atualização chamada SQLXML v. 3.0 (as atualizações denominadas sqlxml extendem o suporte a XML do SQL Server 2000).

O XDR permite a validação do formato de um arquivo XML, normalmente é utilizado para verificar se um XML recebido encontra-se realmente no formato esperado, mas no nosso caso ele será utilizado para indicar ao SQL Server o formato em que desejamos que ele gere as informações.

Outra opção para realização de querys é utilizar um template de query pré-armazenado no servidor e que seja disparado via URL.

Desta forma temos os 3 tipos de virtual names : dbobject, que permite a recuperação de dados binários, Schemas, que permite o uso de schemas para a determinação do formato do XML de retorno e templates, que faz uso de templates para a execução das querys.


Figura 1: Criação de um virtual name chamado pubs

Na Figura 1 você pode observar a criação de um virtual name do tipo dbobject chamado pubs. Veja um exemplo de acesso a este virtual name :

http://localhost/sql/pubs/authors/@au_fname

Observe a sequencia :

Nome do Servidor
Nome do diretório virtual
Virtual Name
Objeto do Banco
Campo a ser recuperado


Observe que o SQL Server por padrão retorna os valores dos campos como atributos de um elemento, dai a utilização da @ na especifação XPATH authors/@au_fname no final da URL.

Como poderá ver pelo resultado, o retorno não é muito útil e de difícil tratamento, desta forma este recurso acaba só sendo utilizado em casos especiais, como a recuperação de imagens. Este nosso exemplo encontra-se apontando para o Pubs. Se criarmos um outro diretório virtual apontando para o northwind e criarmos um outro virtual name podemos utilizar uma query como esta :

http://localhost/sql2/nwind/Employees[@EmployeeID='1']/@Photo

E veremos a foto de um funcionário. Observe que a síntaxe Employees[@EmployeeID='1']/@Photo é característica do XPATH, que neste exemplo está filtrando os dados pelo campo @Employeeid.

Para podermos retornar mais informações e com a formatação que desejarmos devemos montar um virtual name e um schema que nos permita fazer a recuperação das informações via XPATH do banco Pubs.

O primeiro truque importante que deve ser respeitado é que virtual name deve ter o mesmo nome que o diretório em disco para o qual estará apontando. Iremos criar um virtual name chamado Schemas. consequentemente apontando para um diretório Schemas que, apenas por questão de exemplo, iremos criar abaixo do caminho físico do diretório virtual SQL.

Você pode observar no Quadro 1 o schema XDR utilizado para determinar o formato no qual desejamos as informações. Observe o namespace adicional, SQL, que é utilizado no mapeamento dos elementos especificados no schema com os objetos do banco de dados.

Neste primeiro exemplo, bem simples, apenas utilizamos o atributo sql:relation, que é utilizado para mapear um elemento com uma tabela de banco de dados. Observe que após haver realizado a especificação do relation todos os atributos contidos dentro do ElementType passam automaticamente a estarem se referindo a campos deste relation.

Para testarmos esse exemplo basta gravar o exemplo do Quadro 1 no diretório Schemas e chama-lo da seguinte forma :

http://localhost/sql/Schemas/authors.xml/author[@au_id="172-32-1176"]

<?xml version="1.0" ?>
       <Schema xmlns="urn:schemas-microsoft-com:xml-data"
       xmlns:dt="urn:schemas-microsoft-com:datatypes"
       xmlns:sql="urn:schemas-microsoft-com:xml-sql">       
 <ElementType name="author" sql:relation="authors">
 <AttributeType name="au_id" />
         <AttributeType name="au_fname" />
         <AttributeType name="au_lname" />
 <attribute type="au_id" />
         <attribute type="au_fname" />
         <attribute type="au_lname" />
         </ElementType>
         </Schema>
       


Quadro 1: Schema XDR para recuperação de dados da tabela authors - authors.xml

<?xml version="1.0" ?>
       <Schema xmlns="urn:schemas-microsoft-com:xml-data"
       xmlns:dt="urn:schemas-microsoft-com:datatypes"
       xmlns:sql="urn:schemas-microsoft-com:xml-sql">       
 <ElementType name="idautor" sql:field="au_id"          />
         <ElementType name="PriNome" sql:field="au_fname"          />
         <ElementType name="ult_Nome" sql:field="au_lname"          />
 <ElementType name="autor" sql:relation="authors">
 <element type="idautor" />
         <element type="PriNome" />
         <element type="ult_Nome" />
 </ElementType>
         </Schema>
       


Quadro 2 : Schema XDR retornando as informações da tabela authors na forma de elementos - authors2.xml

Já no Quadro 2 o Schema foi alterado de forma a que os dados retornem na forma de elementos e não de atributos. Observe o uso do atributo sql:field para fazer o mapeamento dos elementos com os campos correspondentes. As alterações requerem uma nova chamada para teste, muda basicamente o nome do template, do elemento e do campo sendo filtrado. Veja :

http://localhost/sql/Schemas/authors2.xml/autor[idautor="172-32-1176"]

Private Sub cmdBuscar_Click()
       'Define as variáveis : uma de comunicação, uma do documento        e uma do root
       Dim xHTTP As New MSXML2.ServerXMLHTTP
       Dim doc As DOMDocument
       Dim root As IXMLDOMElement
       'Configura a comunicação, via get
       'utilizando os parâmetros conforme o diretório virtual
       'do sql server
       'Neste caso estamos esperando um único autor, por isso não        foi necessário
       ' preencher o parâmetro root
       xHTTP.open "GET", "http://localhost/sql/Schemas/authors2.xml/autor[idautor=""" & _ 
                txtauid.Text & """]", False
       'faz a requisição
       xHTTP.send       
 'Obtem o documento e o root da resposta
         Set doc = xHTTP.responseXML
         Set root = doc.documentElement
         
         'Verifica se é valido e exibe o resultado
         If root Is Nothing Then
         MsgBox "Autor não encontrado !"
         Else
         MsgBox root.childNodes(1).Text & " " & root.childNodes(2).Text
         End If
 End Sub
       


Quadro 3 : Código em Vb Acessando as informações via XPATH com o schema definido

Figura 2 : Exemplo de uso da aplicação VB de acesso a dados via XPATH


Podemos, da mesma forma, utilizar uma aplicação VB para recuperar essas informações.

Nesta aplicação foi feito um references para a biblioteca COM "Mcrosoft XML" (menu project->References no VB). Foi utilizado o objeto ServerXMLHTTP, que é um objeto que permite a comunicação via XML através de HTTP. Este objeto é, de certa forma, equivalente ao objeto XMLHTTP. O objeto ServerXMLHTTP, porém, é otimizado para que possa ser utilizado em um servidor, a partir de uma aplicação ASP ou um serviço instalado no servidor. O XMLHTTP, porém, possui problemas de performance o que tornam recomendável que seja usado apenas por aplicações client.

Conforme você pode observar no Quadro 3 e na Figura 2 , com a aplicação VB foi possível fazer um tratamento mais cuidadoso da resposta fornecida pelo servidor, tanto validando a comunicação sem que o usuário veja um erro como também buscando mais informações do servidor.

Neste primeiro exemplo fizemos a recuperação de informações de apenas uma tabela, mas a síntaxe de XDR do SQL Server nos permite fazer a recuperação de dados de múltplas tabelas a partir de um schema.

Veja o exemplo no Quadro 4. Ao invés de apenas um ElementType temos 2 ElementTypes, cada um com seu próprio atributo sql:relation.

Neste exemplo está sendo feito um relacionamento entre as tabelas Publishers e Employee do banco pubs, ambas com a chave pub_id (o funcionário trabalha em uma editora).

No ElementType da tabela Publishers você pode observar que existe a especificação do element apontando para a tabela employee. Isso indica que cada elemento de Publisher terá elementos filhos de employee.

Ainda no ElementType Publisher você observa o elemento sql:relation inserido dentro do Element de employee para especificar a relação entre Publisher e Employee. Observe os atributos que esse elemento possui :

key-relation : A tabela pai no relacionamento, neste exemplo Publishers
key : A chave da tabela pai usada no relacionamento. Em um banco bem modelado é a chave primária
foreign-key : A chave estrangeira contida na tabela filho e que se relacionará com a chave primária da tabela pai
foreign-relation : Nome da tabela filho, no caso Employee

Desta forma especificamos um relacionamento entre Publishers e Employee. Agora podemos buscar informações destas tabelas utilizando XDR, veja :

http://localhost/sql/Schemas/pubs.xml/Publisher[@pub_id=0877]

O resultado, contido na Figura 3, mostra o publisher de ID 0877 e seus funcionários.

Veja um outro exemplo de query, neste caso trazendo multiplos publishers :

http://localhost/sql/Schemas/pubs.xml/Publisher[@country='usa']?root=Editores

Observe a necessidade de indicar ?root=Editores , isso porque esta instrução teria trazido multiplos publishers, gerando um XML com multiplos nós raiz e consequentemente inválido. Observe que a ? representa uma transmissão GET. Desta forma, transmitindo a variável root como "Editores", esta será a raiz do XML, conforme demonstrado no Figura 4

<?xml version="1.0" ?>
       <Schema xmlns="urn:schemas-microsoft-com:xml-data"
       xmlns:dt="urn:schemas-microsoft-com:datatypes"
       xmlns:sql="urn:schemas-microsoft-com:xml-sql">
       <ElementType name="Employee" sql:relation="Employee"        >
       <AttributeType name="Emp_Id" />
       <AttributeType name="fname" />
       <AttributeType name="lname" />       
 <attribute type="Emp_Id" />
         <attribute type="fname" />
         <attribute type="lname" />
</ElementType>
         <ElementType name="Publisher" sql:relation="Publishers"          >
         <AttributeType name="pub_id" />
         <AttributeType name="pub_name" />
         <AttributeType name="city" />
         <AttributeType name="country" />
 <attribute type="pub_id" />
         <attribute type="pub_name" />
         <attribute type="city" />
         <attribute type="country" />
         <element type="Employee" >
         <sql:relationship 
         key-relation="Publishers"
         key="pub_id"
         foreign-key="pub_id"
         foreign-relation="Employee" />
         </element>
         </ElementType>
         </Schema>
       

Quadro 4 : Schema XDR relacionando duas tabelas do banco pubs - pubs.xml

Como você já deve ter imaginado, também é possível aplicarmos um XSL sobre este XML. No quadro xxx você vê o código de um arquivo XSL que pode ser aplicado com a seguinte instrução:

http://localhost/sql/Schemas/pubs.xml/Publisher[@country='usa']?xsl=publishers.xsl&root=Editores

Podemos criar uma página HTML para fazer uma consulta com essa query. Observe no Quadro 6 como fica o código. Foi necessário montar em javascript o valor do action do form para transmitir a informação via URL. Esta página nem ao menos precisa ser uma página ASP, pode ser um simples arquivo .HTM. Observe que não estamos falando de uma página acessando um banco, mas estamos falando de uma página se comunicando via HTTP com o banco, o que permite que página e banco estejam em locais diversos sem prejudicar a segurança, pois toda a comunicação ocorre via porta 80 (HTTP).


Figura 3 : Resultado de consulta XPATH utilizando schema com relacionamento entre duas tabelas


Neste exemplo não existe nenhum processamento da informação, o XML já volta com o XSL aplicado. Já no exemplo do quadro xxx temos uma página ASP fazendo a requisição do XML e processando seus dados. Esse exemplo é simples, apenas faz a mesma exibição que o XSL já estava fazendo, mas o objetivo deste exemplo é mostrar como é possível processar a informação livremente antes de exibi-la.

Observe que neste código ASP não utilizamos o parâmetro XSL na chamada da url (xhttp.open) e nem poderíamos, pois o ASP desejava tratar o XML gerado.

Por outro lado, o código ASP do Quadro 7 se baseia no uso do parâmetro XSL, mas este código não conseguiria processar os dados recebidos, pois já foram transformados para HTML, perdendo assim uma das grandes vantagens do XML. Para este exemplo a página HTML de chamada fica bem mais simples, como você pode observar no Quadro 6 .


Figura 4 : Exemplo de uma query com relacionamento entre tabelas recuperando multiplos publishers e especificando o nó raiz.
Também é possível fazer a recuperação em VB, os dados poderiam ser exibidos na forma de um Tree View.

No próximo artigo iremos nos aprofundar no uso de templates para XPATH e templates para querys.

 

Dennes Torres
MCSD,MCSE,MCDBA

<html>
       <head>
       <script>
       function enviar()
       {
       form1.action="http://localhost/sql/Schemas/pubs.xml/Publisher[@country='" + form1.txtcountry.value + "']?xsl=publishers.xsl&root=Editores"
       form1.submit()
       }
       </script>
       </head>
       <body>
       <form method="post" id=form1>
       Pais : <input type=text id=txtcountry><br>
       <input type=button value="Pesquisar" language="javascript" onclick="enviar()">
       </form>
       </body>
       </html>
     


<?xml version="1.0" ?> 
       <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"        version="1.0"> 
       <xsl:template match = "/"> 
       <HTML>
       <head>
       <style>
       .pub {background-color:lightblue}
       .emp {background-color:lightgreen}
       </style> 
       </head>
       <BODY> 
       <table width="100%" border="0" cellspacing="0"        cellpading="0">
       <xsl:apply-templates select="//Publisher" />
       </table>
       </BODY> 
       </HTML> 
       </xsl:template>       
 <xsl:template match="//Publisher">
         <tr class="pub">
         <xsl:apply-templates select="./@*" />
         </tr>
         <xsl:apply-templates select="./Employee" />
         </xsl:template>
 <xsl:template match="//Employee">
         <tr class="emp">
         <xsl:apply-templates select="./@*" />
         </tr>
         </xsl:template>
 <xsl:template match="//@*">
         <td>
         <xsl:value-of select="." />
         </td> 
         </xsl:template>
</xsl:stylesheet>
       


Quadro 5 : StyleSheet utilizada para exibir o resultado de uma query via XPATH com schema envolvendo duas tabelas - Publishers.XSL

<html>
       <head>
       </head>
       <body>
       <form method="post" action="exibepubs.asp">
       Pais : <input type=text name=txtcountry><br>
       <input type=submit value="Pesquisar">
       </form>
       </body>
       </html>
     


Quadro 6 : Página HTML fazendo a requisição de informações via XPATH ao SQL Server - Publishers.XSL

<HTML>
       <head>
       <style>
       .pub {background-color:lightblue}
       .emp {background-color:lightgreen}
       </style> 
       </head>
       <BODY> 
       <table width="100%" border="0" cellspacing="0"        cellpading="0">
       <% dim xhttp,doc,root,nodelist1,nodelist2,node,attr,node2       
set xhttp=createobject("msxml2.serverxmlhttp")
         xHTTP.open "GET", "http://localhost/sql/Schemas/pubs.xml/Publisher[@country='"          _ 
         & request.form("txtcountry") & "']?root=Editores",          False
xhttp.send
         set doc=xhttp.responsexml
         set root=doc.documentelement
set nodelist1=root.childnodes
for each node in nodelist1
         response.write("<tr class='pub'>")
         for each attr in node.attributes
         %>
         <td>
         <%=attr.value %>
         </td>
         <%
         next
         response.write("</tr>")
         set nodelist2=node.childnodes
         for each node2 in nodelist2
         response.write("<tr class='emp'>")
         for each attr in node2.attributes
         %>
         <td>
         <%=attr.value %>
         </td>
         <%
         next
         next
         next
         %>
         </table>
         </BODY> 
         </HTML> 
       

Quadro 7 : Código ASP recuperando informações via XPATH e manipulando o XML resultante - exibepubs.asp



� Búfalo Informática, Treinamento e Consultoria - Rua Álvaro Alvim, 37 Sala 920 - Cinelândia - Rio de Janeiro / RJ
Tel.: (21)2262-1368 (21) 9240-5134 (21) 9240-7281 e-Mail:
contato@bufaloinfo.com.br