Escolar Documentos
Profissional Documentos
Cultura Documentos
apostilaXLS PDF
apostilaXLS PDF
visie.com.br tableless.com.br
Muito se tem falado de XML e da forma como essa linguagem vai revolucionar a internet, nos dando a Web
Semntica e nossos dados em qualquer lugar. Mas pouca gente est de fato trabalhando com XML na prtica e muita
gente comeou a estudar o assunto, aprendeu a escrever um arquivo XML e ficou se perguntando o que fazer com
isso.
Precisamos ento de um cenrio prtico, um caso "do mundo real", para que nosso estudo no sejaapenas uma
teoria vaga que voc acha interessante mas no sabe exatamente pra que serve.
XML na prtica
Vamos analisar alguns exemplos de trabalho com dados em que XML parece ser uma resposta bastante natural:
Tabela de preos
O website de uma escola, em PHP, precisa exibir logo abaixo de suatabela de preos de matrcula e mensalidades, a
tabela de preos dos materiais escolares extrada do site de uma papelaria parceira, que feito em Java. Os
desenvolvedores do site da papelaria preparam ento um aplicativo que atualiza um arquivo XML em seu servidor.
Voc pode com facilidade usar a funo fopen do PHP para obter este XML. Seu trabalho ento process-lo para
transform-lo em uma tabela de preos HTML.
Calendrio de Entrevistas
Uma pequena empresa de recursos humanos envia candidatos escolhidospara uma empresa parceira, de grande
porte. A empresa maior marca uma entrevista individual num dia e horrio determinado para cadacandidato, e
fornece um arquivo xml com a agenda de entrevistas de todos os candidatos de todas as empresas parceiras. O site
da empresa menor, feito em Java/JSP, precisa exibir uma agenda, em HTML, apenas das entrevistas dos candidatos
indicados por ela.
Gerenciador de Contedos
Eis um caso real! O gerenciador de contedos da Inia, indstria de cosmticos, gera um XML do contedo, como
voc pode ver em http://www.ionia.com.br/xml.asp. Voc precisa transformar este contedo em um bonito site
HTML.
Xpath - Linguagem de localizao de elementos em um arquivo XML. a primeira que vamos estudar
XSLT - Linguagem de transformao de XML, esta que faz a mgica toda.
XSL-FO - Linguagem de formatao XML. Ainda no h implementaes populares de XSL-FO e seu uso por
enquanto muito restrito.
Como eram trs linguagens distintas, com objetivos diferentes, que compunham a XSL, o W3C mudou a
especificao antes de aprov-la, e hoje a linguagem XSL-FO passou a se chamar XSL (e a antiga XSL, que englobava
as trs, no ganhou nome). Apesar disso conviente notar que, uma vez que XSL (XSL-FO) ainda no foi adotada
pelo mercado, seus usos hoje ainda so muito restritos e ela praticamente deconhecida dos desenvolvedores,
quando as pessoas dizem "XSL" ou "XSLT" hoje elas geralmente querem dizer a mesma coisa: XSLT.
Diagrama XSLT
Ou seja, tendo um arquivo XML de origem (que nos nossos trs exemplos j foram fornecidos por terceiros) o papel
da XSLT transformar esse arquivo em um outro formato, HTML, XML, PDF ou outro. Assim, tendo um
interpretador XML que suporte XSLT, nos nossos trs exemplos bastaria escrever um arquivo XSLT que
transformasse nossos dados em HTML.
A maioria dos ambientes de desenvolvimento hoje oferece interpretadores de XML com suporte a XSL.
PHP
O PHP j vem com uma extension que trabalha com XSLT. Veja mais em:
http://br2.php.net/manual/pt_BR/ref.xslt.php
Java
Use o Jax:http://java.sun.com/xml/
Python
Experimente a libxslt:http://xmlsoft.org/XSLT/python.html
ASP
Use os componentes do pacote MSXML, verso 3 ou superior.
Para demonstrar como simples usar um interpretador XML para XSLT, segue um exemplo de como fazer a
transformao em ASP:
'Carrega o XML
xmldoc.LoadXML(codigoxml)
'Executa a transformao
xslproc.input = xmldoc
xslproc.transform
transforma = xslproc.output
end function
Como voc pode ver, o cdigo simples, e precisa ser escrito uma nica vez.
<?xml version="1.0"?>
<loja>
<categoria id="1" description="Cadernos">
<produto id="11">
<descricao>Caderno Univ. 100 folhas</descricao>
<preco>25.80</preco>
</produto>
<produto id="12">
<descricao>Caderno Univ. 10 mat.</descricao>
<preco>33.50</preco>
</produto>
</categoria>
<categoria id="2" description="Reguas">
<produto id="21">
<descricao>Regua Comum, 20cm</descricao>
<preco>0.80</preco>
</produto>
<produto id="22">
<descricao>Esquadro 15x20cm</descricao>
<preco>1.10</preco>
</produto>
</categoria>
</loja>
Como voc pode ver, o Quanta tem um interpretador de XML que leu meu arquivo e organizou os dadosnuma
estrutura de rvore. Cada elemento naquela estrutura chamado de n. Existem trs tipos de ns:
Elementos
Cada tag do XML um elemento. O primeiro elemento, loja, envolve todos os outros e chamado de
elemento-raiz.
Atributos
Embora no sejam mostrados pelo TreeView do Quanta, os atributos de cada elemento tambm so ns na
estrutura do XML.
Texto
Como voc pode ver na figura, o texto de cada elemento representa um n separado do prprio elemento.
(Na verdade exitem mais de trs tipos de ns. Os comentrios, por exemplo, tambm so ns do XML. Mas para
nosso estudo agora bastam estes trs tipos.)
Os ns contidos por um elemento so chamados de filhos (e o elemento que os contm de pai, claro.) Os ns filhos
de um mesmo pai e que esto no mesmo nvel so chamados de adjacentes, como descricao e preco.
O melhor meio de comear a entender XPath atravs de exemplos prticos. Vamos ao bsico:
/loja
O cdigo acima selecionaria, no documento de exemplo, o elemento-raiz loja. Veja este agora:
/loja/categoria/produto
Como voc pode ver, a estrutura semelhante da construo de URLs em diretrios. Aqui selecionamos todos os
elementos produto que esto dentro de um elemento categoria dentro do elemento raiz loja.
Tambm voc pode notar que sempre comeamos nossa seleo no elemento-raiz (/). Dentro da XSLT voc vai
precisar usar XPath para selecionar elementos iniciando de um outro n qualquer. O n de onde voc comea sua
seleo chamado de n de contexto. Assim, se o n de contexto, o n de onde estivermos iniciando, for um
elemento categoria e quisermos selecionar os precos de seus produtos:
produto/preco
Note a ausncia da barra inicial. Isso faz com que a comece no n de contexto e no no elemento raiz. Voc tambm
pode subir nveis. Digamos de o n de contexto seja um elemento preco e queiramos selecionar as categorias:
../../../categoria
/loja//produto
Este cdigo localiza todos os produtos dentro de loja, no importa quantos nveis abaixo. Ou seja, ao usar // o
interpretador varre toda a rvore de filhos do elemento procurando por elementos coincidentes. Outro exemplo
interessante:
Este cdigo seleciona qualquer elemento imediatamente dentro de loja. O asterisco significa "qualquer elemento".
Vamos comear a complicar isso. Podemos usar colchetes para fazer testes:
//produto[2]
Este cdigo seleciona o segundo produto em cada categoria. A explicao bvia. Um nmero dentro dos colchetes
seleciona o elemento com aquele ndice, assim elemento[3] seleciona o terceiro elemento. Veja este agora:
//produto[preco]
Este cdigo seleciona todos os elementos produto que contm um elemento preco. Podemos usar testes de n mais
complexos dentro dos colchetes:
//categoria[produto/preco]
Este cdigo seleciona todas as categorias que contm um elemento produto contendo um elemento preco. Veja este
agora:
//produto[preco=0.80]
Este cdigo seleciona todos os produtos que contm um elemento preco com valor 0.80, ou seja, todos os produtos
que custam 80 centavos. A XPath tambm nos fornece funes que podemos invocar, por exemplo:
count(//produto)
Retorna o valor 4, o nmero de elementos produto. A funo last(), por exemplo, retorna o ndice do ltimo
elemento.
/loja/categoria[last()]
/*/categoria[last()]/produto[preco>1]/descricao
Seleciona a descrio dos produtos mais caros que R$1,00 na ltima categoria. Voc tambm pode selecionar ns em
caminhos diferentes separando-os com o caractere de pipe, assim:
//produto/descricao | //produto/preco
/loja/categoria[1]/@id
O cdigo acima seleciona o atributo id do primeiro elemento categoria. Voc tambm pode usar atributos nos
colchetes de teste, por exemplo:
/loja/categoria[@id=1]/produto[@id]/preco
Esse cdigo seleciona os elementos preco dentro dos elementos produto que possuem um atributo id dentro da
categoria cujo id tem valor 1.
Expresses e funes
Operadores Descrio
+ Adio numrica. 2+3 retorna o valor 5
- Subtrao numrica. 3-2 retorna o valor 1.
* Multiplicao numrica. 2*3 retorna o valor 6.
Diviso numrica. O sinal de / no utilizado porque ele j usado para definir caminhos
div
(/loja/categoria por exemplo.) 6 div 2 retorna o valor 3.
mod Resto. 11 mod 5 retorna o valor 1.
= Igualdade. 2=2 retorna true e 2=3 retorna false.
!= Diferena. 2!=2 retorna false e 2!=3 retorna true.
Comparadores numricos. Em um arquivo XSLT, afim de escrever um XML vlido, troque os
< <= > >=
operadores < e <= por < e <=.
and or Operadores lgicos and e or.
Voc pode encontrar uma referncia bastante completa das funes disponveis na XSLT em
http://www.w3schools.com/xpath/xpath_functions.asp
count(nodes)
Retorna o nmero de ns em nodes.
last()
Retorna o ndice do ltimo elemento no conjunto de ns atual.
name(node)
Retorna o nome da tag de node.
position()
Retorna o ndice do n de conteto atual.
contains(str1,str2)
Testa se str1 contm str2 e retorna true ou false
starts-with(str1,str2)
Testa se str1 comea com str2 e retorna true ou false
round(num)
Arredondada num para o inteiro mais prximo
not(exp)
Retorna true se exp for false e vice-versa
number(var)
Converte var para um nmero
string(var)
Converte var para uma string
boolean(var)
Converte var para um boolean
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
</xsl:stylesheet>
template
O cdigo acima varre todo o arquivo XML, comeando pelo n raiz, elemento por elemento, listando o texto de
cada elemento. Se o aplicarmos ao XML da loja o resultado ser:
Ou seja, apenas o texto de todos os elementos. Ns podemos mudar este comportamento. Listar apenas o texto de
cada elemento chamado de "template padro". Podemos criar outro template para o elemento que desejarmos. Por
exemplo, se quisermos que o XSLT retorne a palavra "Produto" ao encontrar cada elemento produto podemos fazer:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="produto">Produto
</xsl:template>
</xsl:stylesheet>
Aqui alteramos o template padro para outro, contendo a palavra Produto e uma quebra de linha. Ao aplicarmos
esse XSLT o resultado ser:
Produto
Produto
Produto
Produto
apply-templates
Voc deve ter notado acima que foi gerada a palavra "Produto" para cada um dos produtos encontrados e o
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="produto">
Produto: <xsl:apply-templates />
</xsl:template>
</xsl:stylesheet>
Aqui, ao encontrar cada um dos produtos, o interpretador vai escrever "Produto:" e em seguidaaplicar o template
padro para preco e descricao, o que resultar em:
O atributo match aceita qualquer expresso XPath. Voc tambm pode aplicar um template personalizado para os
elementos filhos:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="produto">
Produto: <xsl:apply-templates />
</xsl:template>
<xsl:template match="preco"> [Preo oculto]</xsl:template>
</xsl:stylesheet>
Aqui, ao encontrar um elemento descricao o interpretador vai aplicar o template padro, mas ao encontrar um
elemento preco vai aplicar o template personalizado, gerando o seguinte:
Que tal tentar gerar uma tabela HTML com o que aprendemos at aqui? Veja um exemplo:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="loja">
<h1>Tabela de Preos</h1>
<table>
<tr>
<th>Produto</th><th>Preo</th>
</tr>
<xsl:apply-templates />
</table>
</xsl:template>
<xsl:template match="produto">
<tr>
<td><xsl:apply-templates select="descricao" /></td>
<td><xsl:apply-templates select="preco" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>
Aqui temos dois templates. O primeiro, executado quando o interpretador encontra o elemento loja, cria um ttulo
para a pgina (h1), inicia a tabela e cria a primeira linha, com os cabealhos "Produto" e "Preo". O segundo
template, executado em todos os produtos, cria uma linha da tabela com os valores de descricao e preco, um em
copy-of
Suponha que voc queira copiar um elemento inteiro, todo o seu cdigo XML, e no apenas seu texto. fcil:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="loja">
<xsl:copy-of select="categoria[1]" />
</xsl:template>
</xsl:stylesheet>
Se a expresso XPath no atributo select selecionar mais de um elemento o copy-of listar o cdigo XML de todos os
elementos selecionados seqencialmente, um aps o outro.
value-of
O elemento value-of da XSLT exibe o retorno de um valor XPath. Ou seja, ele avalia uma expresso XPath. Se o
resultado dessa expresso for um nmero, string ou valor booleano, ele o exibe. Se for um atributo, exibe o valor do
atributo. Se for um conjunto de ns, exibe o texto do primeiro n. Veja este exemplo:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="loja">
<h1>Tabela de Preos</h1>
<table border="1">
<xsl:apply-templates />
</table>
</xsl:template>
<xsl:template match="categoria">
<tr>
<th colspan="3"><h3><xsl:value-of select="@description" /></h3></th>
</tr><tr>
<th>Cd.</th><th>Descrio</th><th>Preo</th></tr>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="produto">
<tr>
<td><xsl:value-of select="@id" /></td>
Vou deixar para voc o privilgio de entender o cdigo acima. Veja como fica o HTML gerado, quando visto no
navegador:
attribute
Imagine agora que queremos colocar, em cada linha da nossa tabela de produtos, um link para a pgina
detalhes_produto.asp?cod={cdigo do produto}. Essa na verdade uma situaomuito comum. O cdigo HTML
para faz-lo deve ficar, para o produto de id 11.
Como inserir o cdigo do produto dentro do atributo href? Atravs do elemento attribute, observe:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<img>
<xsl:attribute name="src">logo.gif</xsl:attribute>
</img>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<img align="left">
<xsl:attribute name="src">logo.gif</xsl:attribute>
<xsl:attribute name="border">0</xsl:attribute>
</img>
</xsl:template>
</xsl:stylesheet>
Que gera:
Ou seja, podemos combinar atributos escritos diretamente no elemento com elementos attribute. Agora veja:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<div>
<xsl:attribute name="id">sep1</xsl:attribute>
Teste
<xsl:attribute name="class">sep</xsl:attribute>
</div>
</xsl:template>
</xsl:stylesheet>
Vai gerar:
<div id="sep1">
Teste
</div>
Ou seja, o interpretador vai ignorar elementos attribute se eles no estiverem no incio do elemento-pai, antes do
contedo.
Podemos inserir outros elementos XSL dentro do elemento attribute, o que resolve nosso problema da listagem de
produtos com links, veja:
<xsl:template match="loja">
<h1>Tabela de Preos</h1>
<table border="1">
<xsl:apply-templates />
</table>
</xsl:template>
<xsl:template match="categoria">
<tr>
<th colspan="3"><h3><xsl:value-of select="@description" /></h3></th>
</tr><tr>
<th>Cd.</th><th>Descrio</th><th>Preo</th>
</tr>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="produto">
<tr>
<td><xsl:value-of select="@id" /></td>
<td>
<a><xsl:attribute
name="href">detalhes_produto.asp?cod=<xsl:value-of
select="@id" /></xsl:attribute><xsl:value-of
select="descricao" /></a>
</td>
<td><xsl:value-of select="preco" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>
call-template
Uma outra maneira de se chamar um template, dando-lhe um nome, assim:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="produto">
<xsl:call-template name="pr" />
</xsl:template>
<xsl:template name="pr">
<xsl:value-of select="descricao" />
- R$ <xsl:value-of select="preco" /> |
</xsl:template>
</xsl:stylesheet>
Aqui usamos o elemento <i>call-template</i> para chamar o segundo template pelo nome. Note que o n de
contexto ao chamar o segundo template o mesmo do primeiro (produto).
if
O cdigo do elemento if bastante simples:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="produto">
<xsl:value-of select="descricao" />
</xsl:stylesheet>
Ou seja, ao encontrar um elemento if o interpretador vai avaliar a expresso XPath test. Se o resultado for
verdadeiro, ele executa o que h dentro do elemento if, caso contrrio o ignora. Vamos, com isso, inserir maisum
recurso em nossa tabela de preos:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="loja">
<h1>Tabela de Preos</h1>
<table border="1">
<xsl:apply-templates />
</table>
</xsl:template>
<xsl:template match="categoria">
<tr>
<th colspan="3"><h3><xsl:value-of select="@description" /></h3></th>
</tr><tr>
<th>Cd.</th><th>Descrio</th><th>Preo</th>
</tr>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="produto">
<tr>
</xsl:stylesheet>
choose
O elemento choose funciona de maneira semelhante ao if, dando-nos porm mais flexibilidade. Veja:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:choose>
<xsl:when test="preco < 1"> | Promoo!</xsl:when>
<xsl:when test="preco < 2"> | Preo bom!</xsl:when>
<xsl:otherwise> | 3X no carto!</xsl:otherwise>
</xsl:choose>|
</xsl:template>
</xsl:stylesheet>
E seu resultado:
Esquadro 15x20cm
R$ 1.10 | Preo bom! |
Ao encontrar um elemento choose o interpretador executa o test no primeiro elemento when. Se for verdadeiro,
executa o contedo deste when, caso contrrio testa o prximo. Se nenhum dos testes when for verdadeiro o
interpretador executar o contedo do bloco otherwise, se houver. Veja o que vamos fazer com nossa tabela de
preos:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="loja">
<h1>Tabela de Preos</h1>
<table border="1">
<xsl:apply-templates />
</table>
</xsl:template>
<xsl:template match="produto">
<tr>
<td><xsl:value-of select="@id" /></td>
<td>
<a><xsl:attribute
name="href">detalhes_produto.asp?cod=<xsl:value-of
select="@id" /></xsl:attribute><xsl:value-of
select="descricao" /></a>
</td>
<td>
R$ <xsl:value-of select="preco" />
<xsl:choose>
<xsl:when test="preco < 1">
<b> Promoo!</b>
</xsl:when>
<xsl:when test="preco < 2">
<b> Preo bom!</b>
</xsl:when>
<xsl:otherwise>
<b> 3X no carto!</b>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="categoria">
== <xsl:value-of select="@description" /> ==
<xsl:for-each select="produto">
- <xsl:value-of select="descricao" /> -
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Veja o resultado:
== Cadernos ==
- Caderno Univ. 100 folhas -
- Caderno Univ. 10 mat. -
== Reguas ==
- Regua Comum, 20cm -
- Esquadro 15x20cm -
A dica : voc pode usar for-each para simplificar o cdigo e no precisar escrever um nmero enorme de templates
para fazer coisas simples. Se o contedo do for-each for complexo, ou voc forreutiliz-lo em outros lugares,
escreva-o num template separado e no num for-each.
sort
Provavelmente voc estava se perguntando se no havia um meio de ordenar os dados. H. Veja:
<xsl:template match="loja">
<xsl:apply-templates select="categoria/produto">
<xsl:sort select="descricao" order="descending" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="produto">
- <xsl:value-of select="descricao" /> -
</xsl:template>
</xsl:stylesheet>
E veja o resultado:
select
Uma expresso XPath retornando o valor a ordenar
order
Pode ser ascending (ascendente) ou descending (descendente). O default ascending.
data-type
O tipo de dado a ordenar, pode ser number ou text. O default text.
O elemento sort tambm pode ser usado dentro de um elemento for-each, desde que seja o primeiro elemento. O
cdigo abaixo faz exatamente a mesma coisa que o anterior:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="loja">
<xsl:for-each select="categoria/produto">
<xsl:sort select="descricao" order="descending" />
...
<xsl:template match="produto">
<xsl:param name="codigo" />
Cdigo: <xsl:value-of select="$codigo" />
</xsl:template>
...
<xsl:apply-templates select="//produto">
<xsl:with-param name="codigo" value="9" />
</xsl:apply-templates>
Seu documento XSL tambm pode receber um parmetro, se o elemento param for colocado como filho do
elemento stylesheet, assim:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="codigo" />
<xsl:template match="loja">
<xsl:for-each select="categoria/produto[@id=$codigo]">
<xsl:value-of select="descricao" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
O arquivo acima vai exibir a descrio do produto cujo id for recebido atravs do parmetro "codigo". Voc deve
consultar a documentao de sua linguagem de programao ou de seu interpretador de XML para entender como
passar parmetros para um arquivo XSLT.
<xsl:apply-imports />
Voc deve imaginar as possibilidades que isto lhe d em termos de reuso de cdigo e organizao de templates.