CEFETES Unidade da Serra
Coordenadoria de Informática
Prof. Mateus Barcellos Costa
Notas de Aula – XML – Última Atualização: 2008-1
Criando documentos XML
Introdução
<?xml version='1.0' encoding='utf-8'?>
A definição acima denomina-se declaração do documento e deve ser o primeiro
elemento de um documento XML. No exemplo, a declaração está dizendo que:
• documento é compatível com a versão 1.0 de XML
• O documento utiliza o padrão de codificação de caracteres utf de 8 bits. Este
padrão não codifica acentos e c cidilha. Se quisermos usar um padrão de
codificação que aceite acento podemos usar o padrão ISO-8859-1.
Comentário em XML são elementos que devem ser ignorados pelo parser a ser
utilizado. O texto que segue é um comentário.
<!--COMENTÁRIOS -->
Depois da declaração, um documento XML define exatamente 1 elemento denominado
elemento raiz (root element). Qualquer outro elemento dentro do documento deverá
estar contido dentro do elemento raiz. A definição do elemento raiz e de qualquer
outro elemento será feita definindo-se uma tag. Por exemplo, o elemento slideshow que
a seguir será o nosso elemento raiz.
<slideshow>
</slideshow>
Todo elemento deve ser terminado por sua tag de fim. Note que XML é sensível ao
caso. Assim a tag final deve ser exatamente como a inicial.
Introduzindo Atributos a um Elemento
A apresentação de slides possui uma série de itens de dados. Como nenhum destes itens
requer estrutura, é natural definí-los como atributos do elemento slideshow. Para definir
estes atributos podemos fazer como segue:
<slideshow
title="Apresentação de Slides"
date="Data da publicação" author=" Nome do autor"
>
</slideshow>
•
•
•
Quando criamos uma tag ou um atributo podemos usar os caracteres menos (-)
underline ( _ ), dois pontos (:) ou ponto (.), além de números e letras
Valores para os atributos são sempre colocados entre aspas.
Conjuntos de atributos nunca são separados por vírgula ",".
Adicionando Elementos aninhados
XML permite dados hierarquicamente estruturados. Isso significa que um elemento
pode conter outros elementos.
No exemplo abaixo adicionamos um elemento slide que contem um outro elemento
denominado title. No elemento slide foi também definido o atributo type. O significado
deste atributo é ressaltar o tipo de audiência do slide.
<slideshow
title="Exemplo Apresentação de Slides"
date="Data da publicação"
author=" Nome do autor"
>
<slide type="all">
<title>Acordem para as grandes Novidades!</title>
</slide>
</slideshow>
A diferença entre coisas que serão elementos (ex. title) e coisas que serão atributos (ex.
type) é um importante aspecto deste ponto.
Não existe uma regra exata para isso. Portando deve-se aplicar certas heurísticas.
Destacamos aqui duas:
•
A primeira heurística aqui é a questão da visibilidade. O título será uma coisa
vista pela audiência. então ele será um elemento. O tipo, por outro lado, é algo
que nunca estará presente. Logo, ele é um atributo.
• Outra forma de se pensar a respeito de atributos e elementos filhos de um
elemento pai é imaginar que o elemento pai é um recipiente. O tipo do recipiente
é um atributo do recipiente como, por exemplo, garrafa, caixa ou lata. Logo ele
será o atributo do elemento pai. Já o título descreveria o conteúdo do recipiente,
por exemplo, leite, cerveja ou chocolate. Logo ele não é um atributo do
recipiente sendo representado neste caso como um elemento.
Conforme citamos, não existe uma regra exata para esta escolha.
Adicionando texto HTML
XML permite definir qualquer tipo de TAG. Logo, faz sentido definirmos um conjunto
de Tags semelhantes às tags HTML. O Padrão XHTML faz exatamente isto.
<slide type="all">
<title>Visão Geral</title>
<item>Por que <em>Novidades</em> são boas</item>
</item>
<item>Quem <em>compra</em> Novidades</item>
</slide>
A definição acima especifica um slide usando a tag html <em></em> que enfatiza o
texto entre elas (colocando em itálico).
Adicionando Elementos Vazios
Documentos XML devem ser obrigatoriamente bem-formados (well formed). Isso
significa que:
• Toda tag deve possuir uma tag de fim ou ser uma tag vazia.
• Um elemento vazio é pode ser definido com o nome da tag terminando com a /.
Por exemplo <item/> define um elemento item vazio. Um documento XML bem
formado também precisa respeitar os aninhamentos. Por exemplo, <b><i>
texto</i></b> é bem formada, ao passo que <b><i>texto</b></i> não é.
Finalizando, o documento completo em XML para a apresentação de Slides pode ser
visto abaixo
<?xml version='1.0' encoding='utf-8'?>
<slideshow
title="Exemplo de Apresentacao de Slides"
date="Data da publicacao"
author=" Nome do autor" >
<!—Titulo do SLIDE -->
<slide type="all">
<title>Acordem para as Novidades!</title>
</slide>
<!—Visao geral-->
<slide type="all">
<title>Visao Geral</title>
<item>Por que <em>Novidades</em> sao boas</item>
<item/>
<item>Quem <em>compra</em> Novidades</item>
</slide>
</slideshow>
Visão geral dos padrões e APIS para processamento de
Documentos XML.
Uma API (Interface de programa de aplicação – Application Program Interface),
fornece uma série de elementos de programação que permitem realizar uma atividade
específica como, por exemplo processar arquivos XML, comunicar-se usando sockets
ou acessar um banco de dados.
As APIs para processamento de XML obedecem a certos padrões definidos,
principalmente pela W3C – World Wide Web Consortium. As APIs para acesso a
documento podem ser:
Em modo serial – (SAX)
Em modo aleatório – (DOM)
Antes de estudarmos estas APIS vamos ver brevemente alguns dos principais padrões
de XML e tentar digerir esta verdadeira sopa de letras.
Padrões básicos
SAX – Simple API for XML
Este padrão materializa o protocolo de acesso serial a documento XML. SAX é a
maneira mais rápida de se ler e escrever documento XML. SAX pode ser visto como
um protocolo orientado a eventos. Isso porque, usando SAX, o manipulador de arquivos
se associa a um parser SAX, que responde a ocorrência de eventos (tags, erros, etc) na
leitura do documento ativando os métodos apropriados.
DOM – Document Object Model
O Modelo de objetos para documentos (DOM) é um protocolo que converte documento
XML em objetos de um programa. Após isto, os objetos podem ser manipulados como
qualquer outro objeto do programa. O mecanismos do DOM é chamado de protocolo de
acesso aleatório porque qualquer parte do documento pode ser visitada em qualquer
tempo. Esta visita implica que com o DOM é possível modificar, remover ou adicionar
dados ao documento.
DTD – Document Type Definiton
DTD é uma parte da especificação de XML, sendo entretanto opcional.
Um DTD especifica o conjunto de tags que podem ocorrer em um documento e os
arranjos válidos destas tags.
Um DTD portanto pode ser usado para verificar se um documento XML não está sendo
escrito incorretamente. Pode também ser usado para verificar se a estrutura de um
documento XML que está sendo lida é válida ou não.
Um DTD pode ser explicitado no início do documento XML como parte do prólogo do
documento ou ser uma entidade separada.
Namespaces – Namespaces permitem a construção de documentos XML utilizando um
ou mais conjuntos de tags de forma modular. A principal função de um namespace é
qualifica os nomes de forma a eliminar possíveis ambigüidades.
XSL - Extensible StyleSheet Language
O Padrão XML especifica como identificar dados e não com apresentá-los. HTMl por
outro lado permite definir como os dados são apresentados mas não o que são estes
dados.
XSL por sua vez possui as duas partes:
XSTL - Padrão de transformação
XSL-FO – A parte que define objetos de formatação (flow objects). XSL –
FO permite definir múltiplas área em uma pagina e ligar umas com as
outras. Quando a seqüência de texto é direcionada a uma coleção destas
áreas, ela preenche a primeira área e depois automaticamente flui para a
segunda área quando a primeira for totalmente preenchida.
XSLT – Padrão de transformação
XSLT é basicamente um mecanismo de permite transformar documento XML em um
formato de apresentação como, por exemplo, HTML, PDF ou OS.
XPATH – é mecanismo de endereçamento que pode ser usado para construir as
instruções de transformação
Fazendo um dump do documento através de um Parser SAX.
Um parser SAX é geralmente utilizado para obter os dados de um documento XML
para realizar algum tipo de processamento com os mesmo. Aqui utilizaremos o parser
didaticamente, para ler o documento XML e apresentar os dados que estão dentro do
mesmo.
O parser será definido na aplicação denominada Echo.java O esqueleto da classe e as
importações necessárias são mostradas a seguir:
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
public class Echo extends DefaultHandler {
static private Writer out;
public Echo() {
}
public static void main(String argv[]){
if (argv.length != 1) {
System.err.println("Usage: cmd filename");
System.exit(1);
}
try {
// Set up output stream
out = new OutputStreamWriter(System.out, "UTF8");
} catch (Throwable t) {
t.printStackTrace();
}
System.exit(0);
}
}
Analisando a classe echo vemos:
•
•
O método main foi especificado para ler o argumento de entrada (nome do
arquivo a ser processado)
Foi configurado o outputstream (out) onde será escrita a saída.
Para utilizarmos o parser, a principal interface usada é a ContentHandler. Esta
interface define uma série de operações usadas em resposta aos diversos eventos que
ocorrem no parsing.
A forma mais fácil de implementarmos uma interface ContentHandler é
estendermos a classe DefaultHandler. Vejam no código acima que a classe Echo
estende (herda) a classe DefaultHandler.
A seguir adicionamos o código necessário para realizar o parser:
public static void main(String argv[]){
if (argv.length != 1) {
System.err.println("Usage: cmd filename");
System.exit(1);
}
// Use uma instancia de Echo como o SAX EventHandler
DefaultHandler handler = new Echo();
// Usa o parser SAX default (sem validação)
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
// Configura a saída
out = new OutputStreamWriter(System.out, "UTF8");
// Processa a entrada
SAXParser saxParser = factory.newSAXParser();
saxParser.parse( new File(argv[0]), handler );
} catch (Throwable t) {
t.printStackTrace();
}
System.exit(0);
}
O código que segue implementa alguns métodos auxiliares para a apresentação do
documento. São eles, o método emit que apresenta uma string s na saída out e o método
nl que imprime uma mudança de linha em out.
private void emit(String s)
throws SAXException
{
try {
out.write(s);
out.flush();
} catch (IOException e) {
throw new SAXException("I/O error", e);
}
}
private void nl()
throws SAXException
{
String lineEnd = System.getProperty("line.separator");
try {
out.write(lineEnd);
} catch (IOException e) {
throw new SAXException("I/O error", e);
}
}
A seguir temos as implementações dos métodos startdocument, enddocument,
starelement e endelement definidos na interface DefaultHandler.
public void startDocument()
throws SAXException
{
//
emit("<?xml version='1.0' encoding='UTF-8'?>");
nl();
}
public void endDocument()
throws SAXException
{
try {
nl();
out.flush();
} catch (IOException e) {
throw new SAXException("I/O error", e);
}
}
public void startElement(String namespaceURI,
String
sName,
//
simple
name
(localName)
String qName, // qualified name
Attributes attrs)
throws SAXException
{
String eName = sName; // element name
if ("".equals(eName)) eName = qName; // namespaceAware =
false
emit("<"+eName);
if (attrs != null) {
for (int i = 0; i < attrs.getLength(); i++) {
String aName = attrs.getLocalName(i); // Attr
name
if ("".equals(aName)) aName = attrs.getQName(i);
emit(" ");
emit(aName+"=\""+attrs.getValue(i)+"\"");
}
}
emit(">");
}
public void endElement(String namespaceURI,
String sName, // simple name
String qName // qualified name
)
throws SAXException
{
emit("</"+sName+">");
}
public void characters(char buf[], int offset, int len)
throws SAXException
{
String s = new String(buf, offset, len);
emit(s);
}
Substituindo e Inserindo Texto em documentos XML
Tratando caracteres especiais
Entidades – Uma entidade em XML é uma estrutura ou texto que possui um nome.
Referenciando-se uma entidade pelo seu nome causa a inserção da entidade no
documento no local onde a referência foi feita.
Para se criar um referência a uma entidade, o nome da entidade e colocado entre os
caracteres & (ampersand – e comercial) e ; (semicolon – ponto e vírgula), como:
&nomedaentidade;
Entidades predefinidas:
Uma referencia a uma entidade como, por exemplo, &amp; Esta entidade se refere a
um texto que irá substituir a referência no documento, como uma macro em C.
Existem as seguintes entidades predefinidas para caracteres especiais:
Caractere Referência
&
&amp;
<
&lt;
>
&gt;
"
&quot;
'
&apos;
Caracteres podem ser referenciados com nomes de entidades se necessário. Nestes casos
o caractere ser representados pelo # seguido pelo unicode que o representa. Por
exemplo, &#65; representa a letra A.
Usando referências a entidades.
Suponha que você deseja inserir o texto Tamanho do Mercado < Previsto
O problema surge por que quando o parser ver o caractere < ele pensará que está sendo
iniciada uma nova tag. E procurará pelo nome da tag. Para contornar este problema
substituímos o < pela referência &lt;
Tratando Texto com sintaxe parecida com XML
Quando partes do texto incluem muitos caracteres especiais à sintaxe XML, pode se
tornar inconveniente ficar inserindo muitas referências a entidades. Para estas situações
pode-se usar uma seção CDATA
Em uma seção CDATA espaços em branco são considerados e nenhum caractere é
interpretado como caractere especial de XML.
Um seção CDATA inicia com <![CDATA[ e termina com ]]>
Exemplo:
<slide type="tech">
<title>How it Works</title>
<item>First we fozzle the frobmorten</item>
<item>Then we framboze the staten</item>
<item>Finally, we frenzle the fuznaten</item>
<item><![CDATA[Diagram:
frobmorten <------------ fuznaten
|
<3>
^
| <1>
|
<1> = fozzle
V
|
<2> = framboze
Staten+
<3> = frenzle
<2>
]]></item>
</slide>
No exemplo acima, o diagrama é tratado inteiramente como se fosse uma cadeia
de caracteres.
Definindo Data Types
Conforme vimos até agora, o parser só verifica o fato do documento XML ser bemformado. Entretanto, podemos inserir regras que de verificação sintática para os
documentos por meio de DTDs: Data Type Definition. DTD permitem verificar se um
documento bem formado é Válido.
O Documento abaixo é um DTD., que permite definir uma gramática para um
documento XML.
<!-- XML declaration -->
<?xml version='1.0' encoding='utf-8'?>
<!-- DTD for a simple "slide show". -->
<!ELEMENT slideshow (slide+)>
<!ELEMENT slide (title, item*)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT item (#PCDATA | item)* >
O item slide+ indica os conteúdos válidos para o elemento slideshow. Neste caso um
ou mais elementos do tipo slide. Os qualificadores podem ser +, ? ou *
Qualificador Nome
Significado
?
Interrogação Opcional (zero ou um)
Question Mark
*
Asterisco
Asterisk
+
Mais
Sign
-
Plus
Zero ou mais
Um ou mais
Pode também haver aninhamento de parênteses nos itens. Por exemplo ((title, image)+)
Nas declarações acima definimos o tipo do elemento slide e os tipos que constituem
este elemento: title e item
A declaração de title indica que seu conteúdo é formado puramente por conjuntos de
caracteres processáveis (Parsed Character Data - PCDATA). O caractere # indica que o
que segue é uma palavra reservada e não um elemento.
Na declaração item a "|" indica a condição OU, indicando que um PCDATA ou um
item podem ocorrer.
Limitação
Seria interessante se pudéssemos especificar se um item contem por exemplo um
PCDATA ou um PCDATA seguido de um item. Sintaticamente esta expressão ficaria
assim:
<!ELEMENT item (#PCDATA | (#PCDATA, item+)) >
Infelizmente esta especificação incorre em um erro pois, assim que o parser encontrar
um #PCDATA ele vai tentar encontrar um item. Isso ocorre porque ele não consegue
saber se o PCDATA que encontrou é da expressão
#PCDATA ou de
(#PCDATA,item+)
Definições duplas também não funcionam:
<!ELEMENT item (#PCDATA) >
<!ELEMENT item (#PCDATA, item+) >
Neste caso o Parser gera um warning e a ultima declaração é ignorada.
Também não existe forma de especificar posteriormente o tipo de conteúdo esperado
quando PCDATA é usado. Não é possível especificar se o dado é uma seqüência de
dígitos ou um formato de data, por exemplo.
Em DTDs não existe também nenhum sentido de hierarquia. Por exemplo, a definição
do elemento title para o slide aplica-se totalmente ao título de um item. Digamos que se
queira usar a mesma definição diferenciando apenas uma característica de um ou outro.
Por exemplo, o tamanho do texto quando o documento for apresentado. Isto não é
possível, a não ser que se defina dois elementos distintos (slide-title e item-title).
A falta de hierarquia força a introdução de "hierarquia hifenizada" (hyphenization
hierarchy).
Estas limitações são as motivações fundamentais para o desenvolvimento de padrões de
especificação de esquemas (XML Schema).
ANY e EMPTY
A utilização de ANY em um elemento indica que este elemento pode conter qualquer
outro elemento definido ou PCDATA.
A especificação EMPTY indica que um elemento não contem nenhum elemento.
Referenciando o DTD
Quando o DTD é descrito em um arquivo separado do documento XML associado este
precisa ser referenciado.
Para referenciar o DTD deve ser adicionada uma linha no documento XML como a
especificada abaixo:
<!DOCTYPE slideshow SYSTEM "slideshow.dtd">
<slideshow ..
A tag DOCTYPE indica que o documento é um slideshow. Ou seja o documento
consiste de um slideshow e de todos os elemento de dentro dele.
A tag DOCTYPE tem que ocorrer depois da declaração XML e antes do elemento raiz.
Um DTD pode ser colocado internamente em um documento XML. Da seguinte forma:
<!DOCTYPE slideshow SYSTEM "slideshow1.dtd" [
...local subset definitions here...
]>
Exercícios:
1. Cite duas semelhanças e duas diferenças entre XML e HTML.
2. Cite 3 cenários práticos onde XML pode ser aplicada.
3. Quais são as regras que um documento XML bem-formado deve seguir?
4. Analise o documento abaixo e responda às questões 4.1 a 4.5.
<artigo data=”01/02/2006” data=”01/02/2006”>
<autor nome=”João” sobrenome=”Silva”/>
<autor nome=”José” sobrenome=”Silva”/>
<titulo>Introdução a XML</titulo>
<resumo>Este artigo trata dos conceitos de XML. O que descrevemos
aqui é tão verdade quanto 5<4</resumo>
</artigo>
4.1. O documento acima é um documento bem formado? Se não, por quê?
4.2. Como seria possível usar o símbolo < no texto “5<4” para que não
houvesse erros na hora do parsing? Escreva pelo menos duas maneiras
diferentes.
4.3. Quem é o primeiro autor deste artigo?
Nomes
Elementos e Atributos em XML são referenciados por seus nomes. Para garantir que
estes nomes seja interpretados de forma não ambígua, tanto elementos e atributos
utilizam URIs (Uniform Resource Identifiers). URIs são utilizadas para garantir que
conflitos de nomes não irão ocorrer em documentos XML contendo elementos e
atributos vindos de diferentes fontes e com diferentes escopos.
Uma URI pode ser tanto um URN (Uniform Resource Name) ou um URL (Uniforme
Resource Locator).
Um URN é um identificador independente de localização, como, por exemplo um
UUID (Universally Unique Identifier). Um UUID é um número de 16 bytes com um
formato canônico. O númereo 550e8400-e29b-41d4-a716-446655440000 está no
formato de um UUID.
Já uma URL embute aspectos da localização no identificador. Em ambos os casos,
quando uma URI é utilizada para tratar ambigüidades de nomes em XML, esta é tratada
como um identificador de um conjunto abstrato de nomes chamados de Namespace.
Não é necessário que uma referência a um namespace vá produzir alguma coisa
diferente no documento XML. Preferencialmente, URIs serão
simplesmente
identificadores “opacos”.
Namespaces são críticos para a produção de documentos XML que serão trocados entre
múltiplas organizações, para identificar o contexto no qual elementos e atributos tem
significado. Namespaces também podem ser usados para tratar ambigüidades de
documentos internos de uma organização.
Elementos e atributos XML possuem dois componentes: um nome local e o namespace
URI. Um nome local deve obedecer a regra de produção de NCName (Ver em
http://www.w3.org/TR/1999/REC-xml-names-19990114/).
Um NCName inicia com caracteres alfabéticos ou anderscore seguido de 0 ou mais
caracteres alfanuméricos, pontos, hífens ou underscores.
Seja o elemento
< pessoas />
este elemento é identificado pelo seu nome local (pessoa) e não está relacionado com
nenhum namespace.
pessoas é um nome sobrecarregado que pode aceitar múltiplas interpretações, tanto por
parte de seres humanos, quanto por aplicações de software. Dessa forma, é conveniente
a utilização de namespaces. A forma seguinte introduz o namespace:
< pessoas xmlns = ‘uuid: 550e8400-e29b-41d4-a716-446655440000’ />
A declaração xmlns=’uri-reference’ associa a referência URI ao namespace default do
elemento. Dessa forma, o namespace definido aplica-se a todos os elementos filhos
deste elemento.
No documento abaixo, o namespace do elemento Pessoa é também ‘uuid: 550e8400e29b-41d4-a716-446655440000’.
< pessoas xmlns = ‘uuid: 550e8400-e29b-41d4-a716-446655440000’
<pessoa />
/pessoas>
Elementos filhos podem ter seus próprios namespaces.
< pessoas xmlns = ‘uuid: 550e8400-e29b-41d4-a716-446655440000’
<pessoa xmlns = ‘http://www.examplo.net/pessoas/schema’ />
/pessoas>
Se pessoa tiver elementos filho, o ns deles será http://www.examplo.net/pessoas/schema
e não o de pessoas.
Para remover pessoa de qualquer ns definido em seus pais:
< pessoas xmlns = ‘uuid: 550e8400-e29b-41d4-a716-446655440000’
<pessoa xmlns = ‘’/>
/pessoas>
Para facilitar a edição de documentos, pode-se usar apelidos para namespaces. Uma
declaração de um namesapce segue a seguinte forma:
xmlns:myns = ‘uri-reference’
O prefixo local ,myns segue a regra de formação de NCNames e será o apelido local
para o ns. Posteriormente este apelido pode ser usado para a construção de nomes de
elementos e atributos.
A combinação de apelidos com nomes locais deve aderir a regra de produção de nomes
Qualificados (QName)
(veja em http://www.w3.org/TR/1999/REC-xml-names19990114/).
Exemplo: < pessoas xmlns=‘http://www.examplo.net/pessoas/schema’
xmlns: meuns=’http://tdn.si.cefetes.br’ >
<meuns:pessoa />
</pessoas>
Se o nome de um elemento é constituído apenas do nome local sem prefixo, o seu ns
será o ns default.. Se um nome de um atributo é constituído apenas de seu nome local
este atributo não está associado a nenhum ns, independente do ns default de seu
elemento.
Declarações de ns podem ser aplicadas na definição de nomes do elemento onde foi
declarada, de seus atributos e seus filhos e atributos de seus filhos.
Exemplo: A declaração
< pessoas xmlns=‘http://www.examplo.net/pessoas/schema’
xmlns: meuns=’http://tdn.si.cefetes.br’ >
<meuns:pessoa />
</pessoas>
é equivalente a:
< pessoas xmlns=‘http://www.examplo.net/pessoas/schema’
<pessoa xmlns=’http://tdn.si.cefetes.br’ />
</pessoas>
e a:
< x: pessoas xmlns: x=‘http://www.examplo.net/pessoas/schema’
xmlns: meuns=’http://tdn.si.cefetes.br’ >
<meuns:pessoa />
</pessoas>
No caso de haver declarações de ns diferentes com o mesmo prefixo, fica valendo a
declaração mais interna (em termos de escopo).
No exemplo:
< x:a xmlns:x=’http://develop.com’>
<x:b xmlns:x= ‘http://exemplo.com’>
<x:c />
</x:b>
<x:d />
</x:a>
o ns de a e d é http://develop.com e o de b e c é http://exemplo.com.
Cada atributo de um elemento deve estar associado a um único par (ns, nomelocal).
Assim, a declaração abaixo é correta:
<a xmlns =’http://x.org’ xmlns:y=’http://y.org’
b:’Olá’ y:b=’Adeus’ />
O atributo b sem estar asociado a um ns é diferente de y:b, associado ao ns http://y.org.
Já a declaração abaixo está incorreta:
<a xmlns:x =’http://z.org’ xmlns:y=’http://z.org’
x:b:’Olá’ y:b=’Adeus’ />
Exercícios
Faça uma DTD que valide os documentos abaixo (uma única DTD deve ser
usada
para validar ambos os documentos). Adicione aos documentos XML a
declaração da
DTD (DOCTYPE):
Documento 1:
<publicacoes>
<artigo>
<autor>Jose</autor>
<autor estudante="true">Joao</autor>
<autor>Maria</autor>
<titulo>Uma avaliação de desempenho em ambientes paralelos</titulo>
<local-publicacao>
<cidade>Manaus</cidade>
<congresso>SBBD</congresso>
</local-publicacao>
<ano>2003</ano>
</artigo>
<artigo>
<autor estudante="true">Carlos</autor>
<autor>Joao</autor>
<autor>Márcia</autor>
<titulo>XML aplicado</titulo>
<local-publicacao>
<cidade>Gramado</cidade>
<congresso>SBBD</congresso>
</local-publicacao>
<ano>2002</ano>
<obs>Artigo muito bom sobre <assunto>XML</assunto></obs>
</artigo>
</publicacoes>
Documento 2:
<artigo>
<autor>Jose</autor>
<autor estudante="true">Jorge</autor>
<autor>Maria</autor>
<titulo>XML e suas aplicações</titulo>
<local-publicacao>
<cidade>Dallas</cidade>
<periodico>TODS</periodico>
</local-publicacao>
<ano>2003</ano>
<obs>Artigo muito bom sobre <assunto>XML</assunto></obs>
</artigo>
3 – Escreva uma DTD que siga os seguintes critérios:
• possui um elemento livro que pode conter título e vários autores
• título e autor são strings
• o elemento livro possui os seguintes atributos:
i. gênero, cujo valor pode ser: romance, policial ou suspense
ii. língua, cujo valor pode ser: inglês ou português, e o valor default é
português
iii. código, que é único no documento XML como um todo
4 – Escreva um documento XML válido de acordo com a DTD declarada no
exercício 3.
5 – Qual a diferença entre os valores possíveis de um atributo declarado como
CDATA e outro declarado como NMTOKEN?
6 – Explique os conceitos de documento válido e documento bem-formado. Um
conceito
pode ser considerado pré-requisito para o outro? Se sim, qual é pré-requisito
de qual?
Escrevendo uma aplicação distribuída usando Sockets
e XML
O Código abaixo implementa um cliente para um socket.
package client;
import java.io.*;
import java.net.*;
import system.Interface1;
public class KnockKnockClient {
public static void main(String[] args) throws IOException {
Socket kkSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
/** A declaraçao
* kkSocket = new Socket(Interface1.HOST, 4444);
* ria um novo objeto Socket com o nome de kkSocket.
* Um socket estará associado a
um ponto final TCP (Host
+porta)
* Neste caso o HOST está configurado como localhost e a
porta é
* a de número 4444, onde o servidor estár esperando por uma
conexao
*/
kkSocket = new Socket(Interface1.HOST, 4444);
/**
* A Declaraçao
* out = new PrintWriter(kkSocket.getOutputStream(), true);
* obtem o stream de saída do socket e o associa ao objeto
*
PrintWriter out. Entao, para
escrever no kkSocket
usaremos o objeto out.
*/
out = new PrintWriter(kkSocket.getOutputStream(), true);
/**
* A Declaraçao
*
in
=
new
BufferedReader(new
InputStreamReader(kkSocket.getInputStream()));
* obtem o stream de entrada do socket e o associa ao
objeto BufferReader in.
* Entao para lermos dados do kkSocket usamos o objeto in.
*/
in
=
new
BufferedReader(new
InputStreamReader(kkSocket.getInputStream()));
/**
* Se o host nao for encontrado gera a exceçao abaixo
*/
} catch (UnknownHostException e) {
System.err.println("Don't
know
about
host:"
+
Interface1.HOST + ".");
System.exit(1);
/**
* Se o servidor nao estiver escutando a porta procurada
ocorre a exceçao abaixo
*/
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection
to:" + Interface1.HOST + ".");
System.exit(1);
}
/**
* A declaraçao
*
BufferedReader stdIn = new BufferedReader(new
InputStreamReader(System.in));
* Cria um objeto BufferReader para permitir a leitura do
teclado
*/
BufferedReader
stdIn
=
new
BufferedReader(new
InputStreamReader(System.in));
String fromServer;
String fromUser;
/**
* Enquanto a leitura do Socket retornar uma string nao nula
continua no
* while abaixo
*/
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
/* Se o servidor retornar a string Bye. o cliente termina
*/
if (fromServer.equals("Bye."))
break;
/* le a pergunta do usuário */
fromUser = stdIn.readLine();
if (fromUser != null) {
/* envia a pergunta do usuário para o servidor através
do kkSocket */
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
out.close();
in.close();
stdIn.close();
kkSocket.close();
}
}
O Código do servidor é dado a seguir por duas classe uma classe que implementa um
protocolo de conversação e a classe que implementa o socket Server
package server;
public class KnockKnockProtocol {
private static final int WAITING = 0;
private static final int SENTKNOCKKNOCK = 1;
private static final int SENTCLUE = 2;
private static final int ANOTHER = 3;
private static final int NUMJOKES = 5;
private int state = WAITING;
private int currentJoke = 0;
private String[] clues = { "Turnip", "Little Old Lady", "Atch",
"Who", "Who" };
private String[] answers = { "Turnip the heat, it's cold in
here!",
"I didn't know you could yodel!",
"Bless you!",
"Is there an owl in here?",
"Is there an echo in here?" };
public String processInput(String theInput) {
String theOutput = null;
if (state == WAITING) {
theOutput = "Knock! Knock!";
state = SENTKNOCKKNOCK;
} else if (state == SENTKNOCKKNOCK) {
if (theInput.equalsIgnoreCase("Who's there?")) {
theOutput = clues[currentJoke];
state = SENTCLUE;
} else {
theOutput = "You're supposed to say \"Who's there?\"!
" +
"Try again. Knock! Knock!";
}
} else if (state == SENTCLUE) {
if
(theInput.equalsIgnoreCase(clues[currentJoke]
+
"
who?")) {
theOutput = answers[currentJoke] + " Want another?
(y/n)";
state = ANOTHER;
} else {
theOutput = "You're supposed to say \"" +
clues[currentJoke] +
" who?\"" +
"! Try again. Knock! Knock!";
state = SENTKNOCKKNOCK;
}
} else if (state == ANOTHER) {
if (theInput.equalsIgnoreCase("y")) {
theOutput = "Knock! Knock!";
if (currentJoke == (NUMJOKES - 1))
currentJoke = 0;
else
currentJoke++;
state = SENTKNOCKKNOCK;
} else {
theOutput = "Bye.";
state = WAITING;
}
}
return theOutput;
}
}
package server;
import java.net.*;
import java.io.*;
public class KnockKnockServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
/**
* A declaraçao
* serverSocket = new ServerSocket(4444);
* tenta criar um objeto ServerSocket associado a porta 4444
* Se esta porta estiver em uso ocorre a exceçao IOException
*/
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
/**
* A declaracao
* clientSocket = serverSocket.accept();
* é bloqueante e fica esperando até um cliente faça uma
conexao.
*/
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
/**
* Apos um cliente estabelecer uma conexao valida
* o servidor cria um objeto out e um in para escrever e ler
no
* socket associado ao cliente conectado
*/
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
String inputLine, outputLine;
/** o servidor cria também uma instancia do protocolo de
conversaçao
* KnockKnockProtocol.
perguntas
* e respostas.
*/
Este
é
um
protocolo
ilustrativo
de
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
}
Implementação de um sistema para envio e recebimento de Pedidos
Neste sistema, o cliente irá enviar um pedido através da emissão de um documento
pedido.xml para o servidor.
O servidor recebe o pedido, processa e armazena o pedido em um HashSet.
O código do cliente é o seguinte:
package edi.client;
import java.io.*;
import java.net.*;
import system.Interface1;
public class Emissor {
public Emissor() {
}
public static void main(String[] args) throws IOException {
Socket kkSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
/** A declaraçao
* kkSocket = new Socket(Interface1.HOST, 4444);
* ria um novo objeto Socket com o nome de kkSocket.
* Um socket estará associado a um ponto final TCP (Host
+porta)
* Neste caso o HOST está configurado como localhost e a
porta é
* a de número 4444, onde o servidor estár esperando por uma
conexao
*/
kkSocket = new Socket(Interface1.HOST, 4444);
/**
* A Declaraçao
* out = new PrintWriter(kkSocket.getOutputStream(), true);
* obtem o stream de saída do socket e o associa ao objeto
* PrintWriter out. Entao, para escrever no kkSocket
usaremos o objeto out.
*/
out = new PrintWriter(kkSocket.getOutputStream(), true);
/**
* A Declaraçao
* in = new BufferedReader(new
InputStreamReader(kkSocket.getInputStream()));
* obtem o stream de entrada do socket e o associa ao
objeto BufferReader in.
* Entao para lermos dados do kkSocket usamos o objeto in.
*/
in = new BufferedReader(new
InputStreamReader(kkSocket.getInputStream()));
/**
* Se o host nao for encontrado gera a exceçao abaixo
*/
} catch (UnknownHostException e) {
System.err.println("Nao encontrei o host:" +
Interface1.HOST + ".");
System.exit(1);
/**
* Se o servidor nao estiver escutando a porta procurada
ocorre a exceçao abaixo
*/
no host:"
} catch (IOException e) {
System.err.println("Nao obtive uma conexao com o servidor
+ Interface1.HOST + ".");
System.exit(1);
}
/**
* A declaraçao
* BufferedReader stdIn = new BufferedReader(new
InputStreamReader(System.in));
* Cria um objeto BufferReader para permitir a leitura do
teclado
*/
BufferedReader stdIn = new BufferedReader(new
InputStreamReader(System.in));
String fromServer;
String fromUser;
String linha;
BufferedReader pedido = new BufferedReader(new
FileReader("pedido.xml"));
/**
* Enquanto a leitura do Socket retornar uma string nao nula
continua no
* while abaixo
*/
System.out.println("Enviando o arquivo Pedido.xml..");
while ((linha = pedido.readLine()) != null) {
out.println(linha);
}
System.out.println("Arquivo Pedido.xml enviado com sucesso..");
out.close();
in.close();
stdIn.close();
kkSocket.close();
}
}
A interface Interface1 especifica a constante HOST
package system;
public interface Interface1 {
public static final String HOST = "LOCALHOST";
}
A implementação do Servidor envolve as seguintes classes:
HashSet
(from util)
IOException
Interface
(from io)
(from server)
Interface()
main()
ColecaoDePedidos
(from server)
ColecaoDePedidos()
Pedido
(from server)
1
umPedido
Receptador
(from server)
*
Receptador()
recebePedido()
Item
(from server)
Attributes
Date
(from sax)
(from util)
Processador
(from server)
-$out
Writer
(from i o)
DefaultHandler
(from helpers)
SAXException
(from sax)
As classes Pedido e Item possuem os seguintes atributos e operações:
Pedido
empresa : Logical View::java::lang::String
data : Date
cliente : Logical View::java::lang::String
itens : HashSet
Item
descricao : Logical View::java::lang::String
marca : Logical View::java::lang::String
embalagem : Logical View::java::lang::String
quantidade : int
getItens()
getEmpresa()
getData()
setCliente()
setItens()
setEmpresa()
setData()
getCliente()
AdicionaItem()
Pedido()
getMarca()
getDescricao()
getQuantidade()
setEmbalagem()
setMarca()
setDescricao()
setQuantidade()
getEmbalagem()
Item()
A seguir temos o código de cada classe implementada:
Item
package edi.server;
public class Item {
private String descricao;
private String marca;
private String embalagem;
private int
quantidade;
public String getMarca() {
return marca;
}
public String getDescricao() {
return descricao;
}
public int getQuantidade() {
return quantidade;
}
public void setEmbalagem(String embalagem) {
this.embalagem = embalagem;
}
public void setMarca(String marca) {
this.marca = marca;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
public void setQuantidade(int quantidade) {
this.quantidade = quantidade;
}
public String getEmbalagem() {
return embalagem;
}
public Item() {
}
}
Pedido
package edi.server;
import
import
import
import
java.util.Calendar;
com.sun.tools.javac.v8.util.Set;
java.util.Date;
java.util.HashSet;
public class Pedido {
private String empresa;
private Date data;
private String cliente;
private HashSet itens;
public HashSet getItens() {
return itens;
}
public String getEmpresa() {
return empresa;
}
public Date getData() {
return data;
}
public void setCliente(String cliente) {
this.cliente = cliente;
}
public void setItens(HashSet itens) {
this.itens = itens;
}
public void setEmpresa(String empresa) {
this.empresa = empresa;
}
public void setData(Date data) {
this.data = data;
}
public String getCliente() {
return cliente;
}
public void AdicionaItem(Item item){
itens.add(item);
}
public Pedido() {
this.itens= new HashSet();
}
}
ColecaoDePedidos
package edi.server;
import java.util.HashSet;
public class ColecaoDePedidos extends HashSet{
public ColecaoDePedidos() {
}
}
Receptador
package edi.server;
import java.net.*;
import java.io.*;
public class Receptador {
public Receptador() {
}
public Pedido recebePedido() throws IOException {
ServerSocket serverSocket = null;
try {
/**
* A declaraçao
* serverSocket = new ServerSocket(4444);
* tenta criar um objeto ServerSocket associado a porta 4444
* Se esta porta estiver em uso ocorre a exceçao IOException
*/
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Nao consigo escutar na porta: 4444. Ela
deve estar ocupada");
System.exit(1);
}
Socket clientSocket = null;
try {
/**
* A declaracao
* clientSocket = serverSocket.accept();
* é bloqueante e fica esperando até um cliente faça uma
conexao.
*/
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Falha no Accept.");
System.exit(1);
}
/**
* Apos um cliente estabelecer uma conexao valida
* o servidor cria um objeto out e um in para escrever e ler no
* socket associado ao cliente conectado
*/
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
BufferedWriter doc= new BufferedWriter(new FileWriter("doc.xml"));
String inputLine, outputLine;
while ((inputLine = in.readLine()) != null) {
doc.write(inputLine);
}
out.close();
in.close();
doc.close();
clientSocket.close();
serverSocket.close();
Processador p= new Processador();
return p.processaPedido("doc.xml");
}
}
Processador
package edi.server;
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import java.util.Date;
public class Processador extends DefaultHandler {
static private Writer out;
Pedido umPedido;
public Processador() {
umPedido = new Pedido();
}
public
Pedido processaPedido(String pedido){
DefaultHandler handler = this;
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
out = new OutputStreamWriter(System.out, "ISO-8859-1");
// Parse the input
SAXParser saxParser = factory.newSAXParser();
saxParser.parse( new File(pedido), handler );
} catch (Throwable t) {
t.printStackTrace();
}
return this.umPedido;
}
private void emit(String s)
throws SAXException
{
try {
out.write(s);
out.flush();
} catch (IOException e) {
throw new SAXException("I/O error", e);
}
}
private void nl()
throws SAXException
{
String lineEnd = System.getProperty("line.separator");
try {
out.write(lineEnd);
} catch (IOException e) {
throw new SAXException("I/O error", e);
}
}
public void startDocument()
throws SAXException
{
}
public void endDocument()
throws SAXException
{
try {
//
nl();
out.flush();
} catch (IOException e) {
throw new SAXException("I/O error", e);
}
}
public void startElement(String namespaceURI,
String
sName,
//
simple
name
(localName)
String qName, // qualified name
Attributes attrs)
throws SAXException
{ Item umItem;
String eName = sName; // element name
if ("".equals(eName))
eName = qName; // namespaceAware = false
if (eName.equals("pedido")){
this.umPedido = new Pedido();
if (attrs != null) {
for (int i = 0; i < attrs.getLength(); i++) {
String aName = attrs.getLocalName(i); // Attr
name
if ("".equals(aName))
aName = attrs.getQName(i);
if (aName.equals("empresa"))
this.umPedido.setEmpresa(attrs.getValue(i));
if (aName.equals("date"))
this.umPedido.setData(new
Date(attrs.getValue(i)));
if (aName.equals("cliente"))
this.umPedido.setCliente(attrs.getValue(i));
}
}
}
else
if (eName.equals("item")){
umItem = new Item();
if (attrs != null) {
for (int i = 0; i < attrs.getLength(); i++) {
String aName = attrs.getLocalName(i); // Attr
name
if ("".equals(aName))
aName = attrs.getQName(i);
if (aName.equals("descricao")){
umItem.setDescricao(attrs.getValue(i));
emit("Descricao: " + attrs.getValue(i));
}
if (aName.equals("marca"))
umItem.setMarca(attrs.getValue(i));
if (aName.equals("embalagem"))
umItem.setEmbalagem(attrs.getValue(i));
if (aName.equals("quantidade"))
umItem.setQuantidade(new
Integer(attrs.getValue(i)).intValue());
}
umPedido.AdicionaItem(umItem);
}
}
}
public void endElement(String namespaceURI,
String sName, // simple name
String qName // qualified name
)
throws SAXException
{
// emit("</"+sName+">");
// nl();
}
public void characters(char buf[], int offset, int len)
throws SAXException
{
String s = new String(buf, offset, len);
// emit(s);
}
}
Usando XSTL para apresentar os dados
XSLT é uma linguagem para transformar documentos XML em outros documentos
XML.
XSL é abreviação de eXtensible Stylesheet Language (Linguagem de Folha de Estilos
Extensível). O World Wide Web Consortium (W3C) começou a desenvolver o XSL
porque havia uma necessidade linguagem de filha de estilos baseada em XML.
XML não usa tags predefinidas (as tags podem ser ao "gosto do freguês") e os
significados dessas tags são não "interpretáveis".
A tag <table> pode significar uma tabela HTML ou um móvel, e o browser não sabe
como mostrá-la.
Deve haver algo então, que adicionado ao documento XML, descreve como o
documento deve ser mostrado; e isso é o XSL!
XSL consiste de 3 partes:
XSLT é uma linguagem para transformar documentos XML
XPath é uma linguagem para definir partes de um documento XML
XSL-FO é uma linguagem para formatar documentos XML
Pense em XSL como um conjunto de linguagens que podem transformar XML em
XHTML, filtrar e ordenar dados XML, definir partes de um documento XML,
formatar dados XML baseados nos valores dos dados, como mostrar valores negativos
em vermelho, e exportar dados XML para mídias diferentes, como telas, papel ou voz.
Transformações XSLT
XSLT é a parte mais importante dos padrões XSL. Ele é a parte do XSL usada para
transformar um documento XML em outro documento XML, ou um outro tipo de
documento que é reconhecido por um browser, como HTML e XHTML. Normalmente
XSLT faz isso transformando cada elemento XML em um elemento (X)HTML.
XSLT também pode adicionar novos elementos no arquivo de saída, ou remover
elementos. Ele pode rearranjar e ordenar elementos, testar e tomar decisões sobre quais
elementos mostrar, e muito mais.
Um modo comum de descrever o processo de transformação é dizer que o XSLT
transforma uma árvore de origem XML em uma árvore de resultado XML.
Declarando um documento XSL
O elemento raiz que declara o documento a ser uma folha de estilos XSL é
<xsl:stylesheet> ou <xsl:transform>.
Nota: <xsl:stylesheet> e <xsl:transform> são completamente sinônimos e um ou
outro pode ser usado!
A maneira correta de declarar uma folha de estilos XSL de acordo com a
Recomendação W3C XSLT é:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
ou:
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Exemplo:
Vamos supor que queiramos apresentar o conteúdo do documento XML abaixo:
<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
.
.
.
</catalog>
O documento original está em cdcatalog.xml.
Para tanto vamos criar uma folha de estilo (cdcatalog.xsl) com o seguinte conteúdo:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th align="left">Title</th>
<th align="left">Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Para ligar o documento XML com a folha de estilo deve-se adicionar a seguinte linha
após a declaração do arquivo XML:
<?xml-stylesheet type="text/xsl" href="cdcatalog.xsl"?>
O elemento <xsl:template>
Uma folha de estilos XSL consiste de um conjunto de regras chamados moldes
(templates).
Cada elemento <xsl:template> contém regras para aplicar quando um nó específico é
encontrado. XSL utiliza moldes para definir como um elemento deve ser aproesentado.
O atributo match é usado para associar um molde com um elemento XML. O atributo
match também pode ser usado para definir um molde para toda uma seção de um
documento XML (por exemplo, match="/" define o documento todo)..
A folha de estilos XSL a seguir contém um molde para emitir o Catálogo de CDs XML
de nosso exemplo:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<tr>
<td>.</td>
<td>.</td>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
A tag <xsl:template> define o início de um molde. O atributo match="/" associa
(combina) o molde com a raiz (/) do documento XML de origem.
O resto do documento contém o molde propriamente dito, exceto pelas duas últimas
linhas que definem o fim do molde e o fim da folha de estilos.
O elemento <xsl:value-of>
O elemento <xsl:value-of> extrai o valor de um nó selecionado e pode ser usado para
selecionar o valor de um elemento XML e adicioná-lo no resultado da transformação:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<tr>
<td><xsl:value-of select="catalog/cd/title"/></td>
<td><xsl:value-of select="catalog/cd/artist"/></td>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
O valor do atributo select requerido contém uma expressão XPath. Ela funciona como
a navegação num sistema de arquivos onde uma barra à frente (/) seleciona
subdiretórios.
O elemento <xsl:for-each>
O elemento <xsl:for-each> permite a você fazer iterações (loops) em XSLT e pode ser
usado para selecionar todo elemento XML de um conjunto de nós específico:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
O for-each aparece no exemplo 6
Filtrando a saída
Nós podemos filtrar a saída de um arquivo XML adicionando um critério ao atributo
select de um elemento <xsl:for-each>.
<xsl:for-each select="catalog/cd[artist='Bob Dylan']">
Operadores de filtragem válidos são:
•
•
•
•
= (igual)
!= (diferente)
&lt; (menor que)
&gt; (maior que)
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr>
<th>Title</th>
<th>Artist</th>
</tr>
<xsl:for-each select="catalog/cd[artist='Bob Dylan']">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
O filtro está no exemplo 6
O elemento <xsl:sort>
O elemento <xsl:sort> é usado para ordenar o resultado.
Para gerar um arquivo XML como um arquivo XHTML, e ordená-lo ao mesmo tempo,
simplesmente adicione um elemento sort dentro de um elemento for-each no seu
arquivo XSL:
<xsl:for-each select="catalog/cd">
<xsl:sort select="artist"/>
o sort aparece no exemplo 7.
O elemento <xsl:if>
O elemento <xsl:if> contém um padrão que só será aplicado se uma
condição específica for verdadeira.
Para colocar um teste condicional frente ao conteúdo de um arquivo, simplesmente
adicione um elemento <xsl:if> no documento XSL como abaixo:
<xsl:if test="price &gt; 10"> alguma saida... </xsl:if>
O valor do atributo obrigatório test será a expressão a ser avaliada.
O if aparece no exemplo 8.
O elemento <xsl:choose>
O elemento <xsl:choose> é usado em conjunto com <xsl:when> e
<xsl:otherwise> para expressar múltiplos testes condicionais.
Para inserir o teste condicional choose frente ao conteúdo de um arquivo XML,
simplesmente adicione os elementos <xsl:choose>, <xsl:when> e <xsl:otherwise>
no seu arquivo XSL como abaixo:
<xsl:choose> <xsl:when test="price &gt; 10"> ...algum código... </xsl:when>
<xsl:otherwise> ...algum código... </xsl:otherwise> </xsl:choose>
Os arquivos xsl 9 e 10 apresentam o uso de choose.
Download

Introdução a XML