kb.erickguedes.com
XSLT: Transformação de Documentos

XPath Avançado em XSLT

Aula 2 de 5

Eixos Avançados

Eixos definem a direção da navegação na árvore XML dentro de templates XSLT.

<xsl:template match="produto">
  <!-- Eixos de navegação -->
  <xsl:value-of select="preceding-sibling::produto[1]/nome"/>
  <xsl:value-of select="following-sibling::produto[1]/nome"/>
  <xsl:value-of select="ancestor::catalogo/@id"/>
  <xsl:value-of select="descendant::*/preco"/>

  <!-- Atalhos -->
  <xsl:value-of select="../produto"/>       <!-- parent:: -->
  <xsl:value-of select=".//preco"/>         <!-- self::descendant:: -->
</xsl:template>

Funções Especiais do XSLT

current()

Retorna o nó atual (diferente do nó de contexto).

<xsl:for-each select="//categoria">
  <!-- current() é o nó da iteração, . é o contexto -->
  <xsl:value-of select="//produto[categoria = current()/nome]"/>
</xsl:for-each>

document()

Acessa documentos XML externos.

<xsl:template match="/">
  <xsl:for-each select="document('precos.xml')//produto">
    <p><xsl:value-of select="nome"/> - R$ <xsl:value-of select="preco"/></p>
  </xsl:for-each>
</xsl:template>

generate-id()

Gera identificadores únicos para nós.

<xsl:template match="livro">
  <a name="{generate-id()}">
    <xsl:value-of select="titulo"/>
  </a>
</xsl:template>

Seleção Condicional com XPath

<!-- Usando predicados para seleção condicional -->
<xsl:template match="/">
  <h2>Livros caros</h2>
  <xsl:apply-templates select="//livro[preco > 50]"/>

  <h2>Autores de ficção</h2>
  <xsl:apply-templates select="//livro[genero='ficcao']/autor"/>

  <h2>Primeiros 3 livros</h2>
  <xsl:apply-templates select="//livro[position() &lt;= 3]"/>
</xsl:template>

Concatenação e Formatação

<xsl:template match="livro">
  <!-- Concatenação -->
  <p><xsl:value-of select="concat(titulo, ' - ', autor, ' (', ano, ')')"/></p>

  <!-- Formatação de strings -->
  <p><xsl:value-of select="concat('R$ ', format-number(preco, '#.00'))"/></p>

  <!-- Substring e normalização -->
  <p><xsl:value-of select="substring(normalize-space(descricao), 1, 100)"/>...</p>
</xsl:template>

Lab: Transformação com XPath Avançado

# 1. Documento XML
cat << 'EOF' > catalogo.xml
<?xml version="1.0"?>
<catalogo>
  <categoria id="ELETRO">Eletrônicos</categoria>
  <categoria id="LIVRO">Livros</categoria>

  <produto id="P001" cat="ELETRO">
    <nome>Notebook Pro</nome>
    <preco>4999.00</preco>
    <estoque>15</estoque>
  </produto>
  <produto id="P002" cat="LIVRO">
    <nome>XML na Prática</nome>
    <preco>89.90</preco>
    <estoque>30</estoque>
  </produto>
  <produto id="P003" cat="ELETRO">
    <nome>Mouse Wireless</nome>
    <preco>129.90</preco>
    <estoque>42</estoque>
  </produto>
</catalogo>
EOF

# 2. Folha XSLT com XPath avançado
cat << 'EOF' > catalogo.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>
    <head><title>Catálogo Avançado</title></head>
    <body>
      <h1>Catálogo de Produtos</h1>

      <!-- Agrupamento por categoria usando XPath -->
      <xsl:for-each select="//categoria">
        <h2>Categoria: <xsl:value-of select="."/></h2>
        <ul>
          <xsl:for-each select="//produto[@cat = current()/@id]">
            <li>
              <xsl:value-of select="concat(nome, ' - R$ ', preco)"/>
              <xsl:if test="number(estoque) &lt; 20">
                <strong> (ESTOQUE BAIXO: <xsl:value-of select="estoque"/> un.)</strong>
              </xsl:if>
            </li>
          </xsl:for-each>
        </ul>
      </xsl:for-each>

      <hr/>
      <p>Total de produtos:
        <xsl:value-of select="count(//produto)"/>
      </p>
      <p>Produtos com estoque baixo:
        <xsl:value-of select="count(//produto[number(estoque) &lt; 20])"/>
      </p>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>
EOF

# 3. Executar
xsltproc catalogo.xsl catalogo.xml > catalogo.html
type catalogo.html

Domine XPath e você dominará XSLT — toda seleção e condição começa com uma expressão precisa.