XSLT Transforming XML A manipulação de ficheiros XML implica transformar o código fonte do documento XML em qualquer outra coisa (por exemplo em HTML ou pdf) de modo a permitir apresentar a informação numa dada plataforma (por exemplo um browser ou um editor de imagem). É neste contexto que surge o XML Stylesheet Language Transformations - XSLT. O XSLT não é uma linguagem de programação mas sim um conjunto de regras (templates) que serão declarados num documento de stylesheet. Cada regra é definida por um padrão e por um corpo como o seguinte exemplo: <xsl:template match= autor > <xsl:text>isto é um exemplo</xsl:text> O modo de funcionamento do processador XSLT baseia-se simplesmente num percurso nó a nó dos elementos do documento testando se existe alguma regra que possa ser aplicada a esse nó. Se existir o corpor da regra é instanciado com o elemento. X Y Z Processador XSLT aa bb cc Documento XML X aa Y bb Z cc XSLT StyleSheet Resultado Ambientes de Desenvolvimento aula27 1
Um exemplo de uma transformação XSLT O documento XML <nobeldata-v1> <!-- Number of American prizes(literature) in the 20th century --> <prizes continent="america" prizes="0" decade="1900s"/> <prizes continent="america" prizes="0" decade="1910s"/> <prizes continent="america" prizes="0" decade="1920s"/> <prizes continent="america" prizes="3" decade="1930s"/> <prizes continent="america" prizes="2" decade="1940s"/> <prizes continent="america" prizes="1" decade="1950s"/> <prizes continent="america" prizes="2" decade="1960s"/> <prizes continent="america" prizes="3" decade="1970s"/> <prizes continent="america" prizes="3" decade="1980s"/> <prizes continent="america" prizes="2" decade="1990s"/> </nobeldata-v1> A StyleSheet URI do namespace <xsl:template match="/nobeldata-v1"> <html> <!-- Non-XSLT Elements are simply copied --> <body> <p>number of American Nobel Awards by decade</p> <table border="1"> <tr><th>decade</th><th>awards</th></tr> <xsl:apply-templates select="*"/> </table> </html> <xsl:template match="prizes"> <!-- For each decade... --> <tr><td> <xsl:value-of select="@decade"/> </td><td> <xsl:value-of select="@prizes"/> </td></tr> Quando o processador XSLT encontra um template necessita de ser explicitamente instruido para processar os filhos desse elemento Ambientes de Desenvolvimento aula27 2
Sintaxe XSLT O XSLT é composto por várias partes cada uma das quais refere uma funcionalidade especifica (inserir texto, instruções ciclicas e condicionais,...). O documento XML O documento XML seguinte servirá de base á apresentação do XSLT. <bestnovels> <book year="1922"> <title>ulysses</title> <author><name>james</name> <surname>joyce</surname></author> </book> <book year="1987"> <title>the Great Gatsby</title> <author><name>f. Scott</name> <surname>fitzgerald</surname></author> </book> <book year="1934"> <title>a Portrait of the Artist as a Young Man</title> <author><name>james</name> <surname>joyce</surname></author> </book> <book year="1929"> <title>lolita</title> <author><name>vladimir</name> <surname>nabokov</surname></author> </book> </bestnovels> Ambientes de Desenvolvimento aula27 3
Inserção de novos elementos e atributos A inserção de novos elementos é bastante fácil pois se não se tratar de uma instrução XSLT então ela será imediatamente copiada para o resultado. Por exemplo: <?xml version= 1.0?> <xsl:stylesheet xmlns:xsl=http://www.w3.org/1999/xsl/transform> <xsl:template match= / > <html> <body> <h1>os melhores livros do Sec XX</h1> <hr/> </html> Como não se invoca o comando xsl:apply-templates dentro desta regra os elementos book não serão visitados e logo só o HTML desta regra será apresentado. Outro modo de inserir elementos é utilizar as instruções XSLT xsl:element e xsl:attribute. O xsl:element tem unicamente como atributo o nome do elemento. De igual forma o xsl:attribute terá como argumento o nome do atributo e terá de ser especificado dentro da criação do elemento correspondente. Por exemplo, se pretendermos uma lista dos autores tornando os seus nomes links que permitam fazer pesquisas no Google pelo nome do autor poderiamos utilizar o seguinte XSLT. Ambientes de Desenvolvimento aula27 4
<xsl:template match="/"> <html> <body> <h1> Os melhores livros do Sec XX </h1> <hr/> <xsl:apply-templates/> </body> </html> <xsl:template match="book"> <br/> <xsl:element name="a"> <xsl:attribute name="href"> http://www.google.com/search?q= <xsl:value-of select="author/name"/> + <xsl:value-of select="author/surname"/> </xsl:attribute> <xsl:value-of select="author/name"/> <xsl:value-of select="author/surname"/> </xsl:element> Ambientes de Desenvolvimento aula27 5
Inserção de texto A inserção de texto pode ser feita directamente. <h1> Os melhores livros do Sec XX </h1> Outro modo implica recorrer ao xsl:text <xsl:text>exemplo</xsl:text> Uma caracteristica importante do xsl:text é o facto de permitir activar o escape de caracteres XML o que permite incluir caracteres que de outro modo seriam de utilização difícil. Por exemplo, suponha-se que se quer utilizar a sequência <<<<<<. Se se utilizar a sequência directamente <xsl:template match= * > <<<<<< haverá um erro de má formação do XML uma vez que < indica o inicio de um novo elemento. Por outro lado se se uilizar a entidade < <xsl:template match= * ><<<<<< como o escape de caracteres está desctivado obteriamos uma sequência de < Utilizando o atributo disable-output-escaping do xsl:text <xsl:text disable-output-escaping = yes > <<<<<< </xsl:text> obter-se-ia o resultado pretendido. Ambientes de Desenvolvimento aula27 6
Inserção de conteudos textuais de elementos A inserção dos conteudos dos elementos é feita por meio da instrução xsl:value-of que possui o atributo select representando o caminho na estrutura hierarquica XML para o elemento em causa. O seguinte exemplo produz uma listagem dos títulos dos livros: <xsl:output method="text"/> <! não queremos XML --> <xsl:template match="book"> <xsl:value-of select="title"/> Cópias A instrução xsl:copy permite criar uma cópia do ramo corrente (a partir do nó que esteja a ser visitado) da árvore hierarquica. Para além do nó esta intrução permite copiar os namespaces dos nós visiveis a partir deste ponto da árvore. O exemplo seguinte produz uma cópia do documento <xsl:template match="attribute::* node()"> <xsl:copy> <xsl:apply-templates select="@* node()"/> </xsl:copy> Ambientes de Desenvolvimento aula27 7
Enumeração A instrução xsl:number avalia uma expressão passada no seu atributo value. O seguinte exemplo conta o número de elemntos (nós) do documento XML. <xsl:output method="text"/> <xsl:template match="/bestnovels"> <xsl:text>there are </xsl:text> <xsl:number value="count(*)"/> <xsl:text> elements in the source document.</xsl:text> Uma utilização comum desta instrução é enumeração. O valor por defeito do atributo value é a posição relativa do nó entre os nós com o mesmo nome value=position(). O exemplo seguinte enumera os books. <xsl:template match="/bestnovels"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> <xsl:template match="book"> <! aplica a todos os book --> <xsl:copy> <xsl:attribute name="rated"><xsl:number/></xsl:attribute> <xsl:apply-templates select="@* node()"/> </xsl:copy> <xsl:template match="@year name surname title text()"> <xsl:copy> <xsl:apply-templates/></xsl:copy> <! copia o resto --> Ambientes de Desenvolvimento aula27 8
Estrutura de decisão O XSLT faculta duas instruções para implementar estruturas de decisão. São elas o xsl:choose e o xsl:if. O xsl:if possui o atributo test que contem a expressão booleana que servirá de condição. O xsl:choose fornece uma série de alterativas que serão comparadas com o nó corrente. O exemplo seguinte lista todos os anos dos books e assinala aqueles que foram publicados nos anos 50. <xsl:template match="book"> <xsl:apply-templates select= @year </xsl: template> <xsl:template match= @year > <xsl:value-of select= string() /> <xsl:if test= contains(string(), 195 ) > <xsl:text>este livro foi escrito na decada de 50</xsl:text> </xsl:if> O exemplo seguinte cria uma tabela de livros por décadas Ambientes de Desenvolvimento aula27 9
<xsl:template match="/bestnovels"> <html> <body> <h1>books vs decades</h1> <hr/> <table border="1"> <tr> <th>book</th><th>1940</th><th>1950</th><th>outro</th> </tr> <xsl:apply-templates select="book"/> </table> </body> </html> <xsl:template match="book"> <tr> <td><xsl:value-of select="title"/></td> <xsl:apply-templates select="@year"/> </tr> <xsl:template match="@year"> <xsl:choose> <xsl:when test="contains(string(),'194')"> <td><img src="check.gif"/></td><td/><td/> </xsl:when> <xsl:when test="contains(string(),'195')"> <td/><td><img src="check.gif"/></td><td/> </xsl:when> <xsl:otherwise> <td/><td/><td><img src="check.gif"/></td> </xsl:otherwise> </xsl:choose> Ambientes de Desenvolvimento aula27 10
Estruturas Cíclicas A utilização de ciclos em XSLT faz-se por meio do xsl:for-each. A semântica deste elemento é muito simples. Ele possui um atributo de nome select cujo valor é uma expressão que representará uma lista de nós. O conteudo deste elemento irá instanciar com cada nó da lista. O exemplo seguinte irá escrever os nomes de todos os autores dos books. <xsl:template match="book"> <xsl:for-each select="author/name"> <xsl:text>first Name: </xsl:text> <xsl:value-of select="."/> </xsl:for-each> Ambientes de Desenvolvimento aula27 11
Variáveis A utilização de variáveis em XSLT é feita recorrendo ao elemento xsl:variable que possui três tipos de inicialização: 1. Se o conteudo do elemento xsl:variable for vazio e o atributo select contiver uma expressão, o valor da variável é o valor da expressão. <xsl:variable name= x select= position() /> <xsl:variable name= y select= ola /> 2. Se o conteudo do elemento xsl:variable não for vazio e não existir atributo select, o valor da variável é o conteudo do elemento; <xsl:variable name= cadeira >Matematica</xsl:variable> 3. Por último, se o elemento fôr vazio e não tiver select, a variável é inicializada com uma string nula. A utilização da variável requere apenas que se preceda o nome da variável pelo simbolo $. Em XSLT os valores das variáveis não podem ser alterados. <xsl:template match="book"> <xsl:variable name="y" select="@year"/> <xsl:variable name="message"> <b>this is a 60's author</b> </xsl:variable> <xsl:for-each select="author/name"> <xsl:if test="contains($y,'196')"> <xsl:copy-of select="$message"/> </xsl:if> </xsl:for-each> Ambientes de Desenvolvimento aula27 12
Named Templates O XSLT permite reutilização de templates. Para isso ser possível, torna-se necessário atribuir um nome a um template. Essa atribuição é feito por meio do atributo name da instrução xsl:template. O exemplo seguinte cria uma imagem HTML e formata-a por meio de CSS. <xsl:template name="point"> <xsl:element name="img"> <xsl:attribute name="src">point.gif</xsl:attribute> <xsl:attribute name="style"> <xsl:text>{position: absolute; left: 34 pt; top: 34pt} </xsl:attribute> </xsl:element> A utilização do template é feita por meio do elemento <xsl:call-template name= point > Ambientes de Desenvolvimento aula27 13
Passagem de Parâmetros para Templates A passagem de parâmetros é feita por meio do elemento xsl:with-parameter que tem que estar imediatamente abaixo de xsl:call-template. <xsl:call-template name= point > <xsl:with-parameter name= x select= 60 /> </xsl:call-template> Por sua vez o named template deverá ter uma declaração do parâmetro por meio de xsl:param. O atributo select permite atribuir um valor por defeito ao parâmetro. Por exemplo: <xsl:template name="point"> <xsl:param name= x select= 0 /> <xsl:element name="img"> <xsl:attribute name="src">point.gif</xsl:attribute> <xsl:attribute name="style"> <xsl:text>{position: absolute; left:</xsl:text> <xsl:value-of select= $x /> <xsl:text>pt; top: 34pt;}</xsl:text> </xsl:attribute> </xsl:element> O exemplo seguinte pretende apresentar uma representação gráfica cartesiana dos diversos books pelos diversos anos de publicação. Ambientes de Desenvolvimento aula27 14
<xsl:template match="/bestnovels"> <html> <title>rating vs year</title> <body bgcolor="#ffffff"> <img src="cartesian.gif"/> </body> <xsl:for-each select="book"> <xsl:call-template name="point"> <xsl:with-param name="x" select="@year"/> <xsl:with-param name="y" select="@rated"/> </xsl:call-template> </xsl:for-each> </html> <xsl:template name="point"> <xsl:param name="x" select="0"/> <xsl:param name="y" select="0"/> <!-- add the Y coord --> <xsl:element name="img"> <xsl:attribute name="src">point.gif</xsl:attribute> <xsl:attribute name="style"> <xsl:text>{position: absolute; left:</xsl:text> <!-- if a book is rated 10, the point is 30 --> <xsl:value-of select="substring($x,3)*5-30"/> <xsl:text>pt; top: </xsl:text> <!-- if a year was written in 1940, the point is 40 --> <xsl:value-of select="30+$y*10"/> <xsl:text>pt;} </xsl:text> </xsl:attribute> </xsl:element> Ambientes de Desenvolvimento aula27 15