---
title: "Utilize as funções XPath integradas"
date: "2011-07-12"
categories: 
  - "xpath"
tags: 
  - "altova-online-training"
  - "altova-xmlspy"
  - "data-mapping"
  - "education"
  - "learn-xml"
  - "xml-editor"
  - "xmlspy"
  - "xpath"
  - "xslt"
description: Este artigo explora a utilização de funções XPath para ordenar dados XML de forma eficiente, com foco na extração de apelidos e no tratamento de artigos definidos em títulos.
---
Status: #blog

Tags:  #altova-online-training #altova-xmlspy #data-mapping #education #learn-xml #xml-editor #xmlspy #xpath #xslt

Categories: [xpath+xquery](/blog/pt/category/xpathxquery.md)
# Utilize as funções XPath integradas

No desenvolvimento de um dos cursos de formação online da [Altova](https://www.altova.com/pt/aot/online-training.aspx), organizei uma lista de livros por autor. Percebi que o campo "autor" continha uma cadeia de caracteres com o nome completo do autor, pelo que os livros estavam organizados pela primeira letra dessa cadeia, ou seja, pelo primeiro nome do autor. Não era adequado corrigir a organização dentro do curso, mas é possível extrair facilmente o apelido de uma cadeia de caracteres e utilizá-lo como chave de organização, usando funções XPath. Se, posteriormente, usar os títulos dos livros como chave de organização secundária, surgirá um problema com títulos que começam por "A", "An" ou "The". Gostaria de usar o título como chave de organização secundária, mas ignorar os artigos definidos ou indefinidos que apareçam no início.

![Gerar a lista de livros, com a ordenação corrigida utilizando expressões XPath](https://lh4.ggpht.com/-OBe9_xfjlpQ/TgD1tUSi6sI/AAAAAAAAAGw/nLwMwUDQTJ4/correct-sort-xsl2_thumb%25255B2%25255D.png?imgmax=800) 

Vamos analisar como criámos este código XSLT. Este artigo foi escrito utilizando o [XMLSpy](https://www.altova.com/pt/xmlspy.html) como plataforma, mas as mesmas expressões XPath podem ser utilizadas no [MapForce](https://www.altova.com/pt/mapforce.html) ou no [StyleVision](https://www.altova.com/pt/stylevision.html) para obter resultados semelhantes. Podemos começar com uma lista XML simples de livros. Temos 4 livros, cada um com os elementos "autor" e "título". 

[![Lista de três livros](https://lh5.ggpht.com/-oP0T7tap1j8/TgD1qZFjeJI/AAAAAAAAAGI/Q9N1sefXpr8/book-list-xml2_thumb%25255B6%25255D.png?imgmax=800 "book_list.xml")](http://lh5.ggpht.com/-1XkQTBtjxgI/TgD1p7e9jRI/AAAAAAAAAGE/r5x-fYqrXB4/s1600-h/book-list-xml2%25255B8%25255D.png) 

Um código XSLT para criar uma lista de livros teria a seguinte aparência:

[![Exibir a lista de livros sem ordenação](https://lh6.ggpht.com/-Xl2drxDYvWk/TgD1qyCS-tI/AAAAAAAAAGQ/XtlE-ha3aPY/no-sort-xsl2_thumb%25255B3%25255D.png?imgmax=800 "no_sort.xsl")](http://lh6.ggpht.com/-0QjJb5fadso/TgD1qitzcrI/AAAAAAAAAGM/ENp-px5_e1g/s1600-h/no-sort-xsl2%25255B7%25255D.png) 

Isto irá gerar o seguinte resultado: 

[![Lista de livros não organizada](https://lh4.ggpht.com/-84ZeFnOVnX0/TgD1ruHFFII/AAAAAAAAAGY/rtui-dgtCUQ/no-sort-output_thumb%25255B2%25255D.png?imgmax=800 "Output from XSL with No Sort")](http://lh6.ggpht.com/-DcGmqHHaQi4/TgD1rJWB_GI/AAAAAAAAAGU/V9i4088XoKs/s1600-h/no-sort-output%25255B4%25255D.png) 

Os livros são apresentados na ordem em que aparecem no ficheiro de dados original. Se adicionarmos a instrução `xsl:sort` ao ciclo `xsl:for-each`, podemos organizar a saída de outras formas. 

[![Exibir a lista de livros com uma ordenação básica](https://lh4.ggpht.com/-JX9qbo9fYjo/TgD1sKu_YVI/AAAAAAAAAGg/rtHXnh_x94o/sort-xsl2_thumb%25255B2%25255D.png?imgmax=800 "sort.xsl")](http://lh4.ggpht.com/-WEIuCC1NRNw/TgD1rzIgzPI/AAAAAAAAAGc/q79Va9UWMgo/s1600-h/sort-xsl2%25255B4%25255D.png) 

Isto irá gerar uma lista ordenada, mas não ordenada corretamente. 

[![Resultado da transformação XSL com ordenação básica](https://lh3.ggpht.com/-kN0aSY1DhE8/TgD1spmsmLI/AAAAAAAAAGo/BsxQW6XYwWk/sort-output_thumb%25255B2%25255D.png?imgmax=800 "Output from XSL with Basic Sort")](http://lh3.ggpht.com/-2JAA_7dIt4o/TgD1sYIFl-I/AAAAAAAAAGk/M5g2B1vVC_M/s1600-h/sort-output%25255B4%25255D.png) 

Ordenar os autores como strings resulta em "Jules Verne" aparecendo antes de "Mark Twain". Além disso, "A Connecticut Yankee in King Arthur's Court" aparece antes de "Adventures of Huckleberry Finn". Queremos ignorar o artigo indefinido "A", para que "Adventures of Huckleberry Finn" apareça antes de "A Connecticut Yankee in King Arthur's Court". Podemos usar expressões XPath para extrair as chaves de ordenação que desejamos. 

[![Gerar a lista de livros, com a ordenação corrigida utilizando expressões XPath](https://lh4.ggpht.com/-OBe9_xfjlpQ/TgD1tUSi6sI/AAAAAAAAAGw/nLwMwUDQTJ4/correct-sort-xsl2_thumb%25255B2%25255D.png?imgmax=800 "correct_sort.xsl")](http://lh4.ggpht.com/-1797dSMl6G0/TgD1tIvfZnI/AAAAAAAAAGs/G8i7ztztp9Y/s1600-h/correct-sort-xsl2%25255B4%25255D.png) 

Vamos analisar o código antes de examinarmos o resultado. Substituímos "author" por "reverse(tokenize(author, ' '))[1]". A função "tokenize" divide a string "author" em tokens, utilizando um único espaço como separador. Assim, "Jules Verne" é dividido em "Jules" e "Verne". A função "reverse" inverte a ordem dos tokens, resultando em "Verne" e "Jules". O elemento entre parênteses retos seleciona o primeiro elemento da lista, que é "Verne". Este é o valor utilizado na função "xsl:sort" para organizar os livros. Esta não é a solução perfeita, mas funciona no nosso caso. O título parece complicado, mas a lógica é simples. A expressão "tokenize(title, ' ')[1]" extrai a primeira palavra do título. Portanto, o primeiro teste "if" é: "A primeira palavra do título é a palavra 'A'?". Se for, então retornamos a substring do título que começa na sua terceira letra, eliminando assim "A" e o espaço. Se a primeira palavra do título não for "A", então precisamos testá-la novamente para ver se a primeira palavra do título é "The". Se for, utilizamos a substring do título que começa no seu quinto caractere, eliminando assim "The" e um espaço. Se ambos os testes falharem, simplesmente passamos o título como a chave de ordenação. Poderíamos adicionar outro teste ao nosso código para verificar se a primeira palavra é "An", mas não é necessário para este conjunto de dados. Ao executar esta última transformação XSLT, obtemos o seguinte resultado. 

[![Resultado do XSL com ordenação corrigida](https://lh5.ggpht.com/-78G5M2Z81Ow/TgD1uRmfiQI/AAAAAAAAAG4/YStPJ1HRDj0/correct-sort-output_thumb%25255B2%25255D.png?imgmax=800 "Output from XSL with Corrected Sort")](http://lh3.ggpht.com/-h5AD7I5C60o/TgD1tsVI9fI/AAAAAAAAAG0/Nj8_cO10i2s/s1600-h/correct-sort-output%25255B4%25255D.png) 

"Mark Twain" está agora à frente de "Jules Verne". "As Aventuras de Huckleberry Finn" aparece antes de "A Incrível Sapo Saltador do Condado de Calaveras" e "Um Yankee em Corte de Rei Arthur". A falha na nossa abordagem à cadeia de autores é que queremos que "Jules Verne" seja tratado como "Verne, Jules" para a ordenação, para que, se tivéssemos um livro de "Jimmy Verne", a ordenação os tratasse como autores diferentes. O nosso código não faz isso. Utilizar "concat(reverse(tokenize(author, ' '))[1], reverse(tokenize(author, ' '))[2])" ordenaria corretamente "Jules Verne" e "Jimmy Verne", mas esta solução só funciona com nomes de duas palavras. Se um autor tivesse um sufixo ("Martin Luther King, Jr.") ou várias palavras ("George Herbert Walker Bush"), o código falharia. Existem muitas exceções às regras gerais de ordenação alfabética de nomes, e o código para permitir todas as variantes vai muito além do âmbito deste artigo. O que queríamos demonstrar era a capacidade de manipular dados XML em tempo real utilizando expressões XPath. Nem sempre temos controlo total sobre o formato das nossas fontes de dados, mas, utilizando o poder das expressões XPath, podemos transformar os dados para o formato que precisamos. Uma cópia dos ficheiros utilizados nestes exemplos está disponível [aqui](https://www.altova.com/pt/library/Using_XPath_Functions.zip).
