Extensões, XSLT 3.0 e Produção
Aula 5 de 5
EXSLT — Extensões Comunitárias
EXSLT adiciona funções matemáticas, de string, data e regex ao XSLT 1.0.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times"
xmlns:math="http://exslt.org/math"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="date math str">
<!-- Data atual -->
<p>Gerado em: <xsl:value-of select="date:date-time()"/></p>
<!-- Matemática -->
<p>Média: <xsl:value-of select="math:avg(//preco)"/></p>
<p>Maior: <xsl:value-of select="math:max(//preco)"/></p>
<p>Menor: <xsl:value-of select="math:min(//preco)"/></p>
<!-- String tokenize e replace -->
<xsl:for-each select="str:split(nomes, ';')">
<li><xsl:value-of select="."/></li>
</xsl:for-each>
</xsl:stylesheet>
# Saxonica/saxon9he já inclui suporte a EXSLT
java -jar saxon9he.jar -s:dados.xml -xsl:exslt.xsl -o:output.html
Extensões Saxon
O processador Saxon oferece funcionalidades avançadas proprietárias.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:saxon="http://saxon.sf.net/"
extension-element-prefixes="saxon">
<!-- Tokenização com regex -->
<xsl:for-each select="tokenize(descricao, '\s+')">
<span><xsl:value-of select="."/> </span>
</xsl:for-each>
<!-- Análise de strings JSON -->
<xsl:variable name="json"
select="unparsed-text('config.json')"/>
</xsl:stylesheet>
XSLT 3.0 — Novidades
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map">
<!-- Streaming: processa documentos grandes sem carregar tudo -->
<xsl:mode streamable="yes"/>
<xsl:template match="produto">
<p><xsl:value-of select="nome"/></p>
</xsl:template>
<!-- Maps e Arrays (estruturas de dados JSON-like) -->
<xsl:variable name="config" as="map(xs:string, xs:string)">
<xsl:map>
<xsl:map-entry key="'host'" select="'localhost'"/>
<xsl:map-entry key="'port'" select="'8080'"/>
</xsl:map>
</xsl:variable>
<!-- Transformação em cadeia -->
<xsl:variable name="transformado">
<xsl:transform select="'<root><item>X</item></root>'">
<xsl:output method="xml"/>
</xsl:transform>
</xsl:variable>
</xsl:stylesheet>
XML para PDF via XSL-FO
XSL-FO (Formatting Objects) é uma linguagem para formatação de páginas, usada para gerar PDF.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="pagina">
<fo:region-body margin="2cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="pagina">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="18pt" font-weight="bold" space-after="1cm">
Relatório de Produtos
</fo:block>
<xsl:for-each select="//produto">
<fo:block font-size="12pt" space-after="0.5cm">
<xsl:value-of select="concat(nome, ' - R$ ', preco)"/>
</fo:block>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
# Gerar PDF com Apache FOP
fop -xml dados.xml -xsl relatorio-fo.xsl -pdf saida.pdf
Build Tooling e Performance
<!-- Ant build para pipeline XSLT -->
<project name="xslt-pipeline" default="transform">
<target name="transform">
<xslt in="dados.xml" out="output.html" style="template.xsl">
<param name="categoria" expression="Eletrônicos"/>
<param name="limite" expression="100"/>
</xslt>
</target>
<target name="all" depends="transform">
<xslt in="output.xml" out="final.pdf" style="fo.xsl"/>
</target>
</project>
# Dicas de performance
# 1. Use keys para lookups em vez de XPath aninhado
# 2. Prefira xsl:for-each-group a Muenchian se XSLT 2.0+
# 3. Use xsl:mode streamable="yes" para documentos grandes
# 4. Evite //desnecessário — seja específico no XPath
# Benchmark de transformação
time xsltproc template.xsl grande.xml > /dev/null
time java -jar saxon9he.jar -s:grande.xml -xsl:template.xsl -o:/dev/null
Lab: Pipeline de Transformação Completo
# 1. Documento XML
cat << 'EOF' > dados.xml
<?xml version="1.0"?>
<produtos>
<produto>
<nome>Notebook Dell</nome>
<preco>4999.00</preco>
<categoria>Eletrônicos</categoria>
</produto>
<produto>
<nome>Monitor 27"</nome>
<preco>1599.00</preco>
<categoria>Eletrônicos</categoria>
</produto>
</produtos>
EOF
# 2. Transformar para HTML
cat << 'EOF' > to-html.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<h1>Produtos</h1>
<xsl:for-each select="//produto">
<p><xsl:value-of select="concat(nome, ' - R$ ', preco)"/></p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
EOF
# 3. Pipeline
echo "=== Passo 1: XML -> HTML ==="
xsltproc to-html.xsl dados.xml > output.html
type output.html
echo ""
echo "=== Passo 2: Validar saída ==="
echo "Arquivo gerado: $(wc -c < output.html) bytes"
echo ""
echo "=== Passo 3: Usando Saxon ==="
if command -v java &> /dev/null; then
echo "Saxon disponível (pule se não tiver o jar)"
fi
echo ""
echo "=== Bônus: EXSLT date ==="
cat << 'EOF' > exslt-demo.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times"
extension-element-prefixes="date">
<xsl:template match="/">
<html><body>
<p>Relatório gerado em: <xsl:value-of select="date:date-time()"/></p>
<p>Ano: <xsl:value-of select="date:year()"/></p>
<p>Timestamp: <xsl:value-of select="date:seconds()"/></p>
</body></html>
</xsl:template>
</xsl:stylesheet>
EOF
XSLT 3.0 com streaming e maps torna o XSLT moderno competitivo com linguagens de transformação como JavaScript e Python.