Utilice las funciones XPath integradas
Al desarrollar uno de los cursos de formación en línea de Altova, organicé una lista de libros por autores. Me di cuenta de que el campo de autor era una cadena de texto que contenía el nombre completo del autor, por lo que los libros se ordenaban según la primera letra de esa cadena, es decir, el primer nombre del autor. No era adecuado modificar el ordenamiento dentro del curso, pero se puede extraer fácilmente el apellido de una cadena de texto y utilizarlo como clave de ordenamiento utilizando funciones de XPath. Si luego se utilizan los títulos de los libros como clave de ordenamiento secundaria, se presenta un problema con los títulos que comienzan con "A", "An" o "The". Quiero utilizar el título como clave de ordenamiento secundaria, pero ignorando el artículo definido o indefinido inicial.
![]()
Analicemos cómo creamos este código XSLT. Este artículo se escribió utilizando XMLSpy como plataforma, pero las mismas expresiones XPath se pueden utilizar dentro de MapForce o StyleVision para obtener resultados similares. Podemos empezar con una lista XML sencilla de libros. Tenemos 4 libros, cada uno con nodos de autor y título.
![]()
Una transformación XSLT para crear una lista de libros podría tener este aspecto:
![]()
Esto generará el siguiente resultado:
![]()
Los libros se generan en el orden en que aparecen en el archivo de datos original. Si añadimos la etiqueta xsl:sort al bucle xsl:for-each, podemos organizar la salida de otras maneras.
![]()
Esto generará una lista ordenada, pero no estará ordenada correctamente.
![]()
Ordenar los autores como cadenas de texto da como resultado que "Jules Verne" aparezca antes que "Mark Twain". Además, "A Connecticut Yankee in King Arthur's Court" aparece antes que "Adventures of Huckleberry Finn". Queremos ignorar el artículo indefinido "A" para que "Adventures of Huckleberry Finn" aparezca antes que "A Connecticut Yankee in King Arthur's Court". Podemos utilizar expresiones XPath para extraer las claves de ordenamiento que deseamos.
![]()
Analicemos el código antes de examinar el resultado. Reemplazamos "author" con "reverse(tokenize(author, ' '))[1]". La función "tokenize" divide la cadena "author" en tokens, utilizando un espacio simple como separador. Por lo tanto, "Jules Verne" se divide en "Jules" y "Verne". La función "reverse" invierte el orden de los tokens, resultando en "Verne" y "Jules". El elemento entre corchetes [1] selecciona el primer elemento de la lista, que es "Verne". Este es el valor que se utiliza en la función xsl:sort para ordenar los libros. No es la solución perfecta, pero funciona en nuestro caso. El título parece complicado, pero la lógica es sencilla. La expresión "tokenize(title, ' ')[1]" extrae la primera palabra del título. Por lo tanto, la primera condición "if" es: "¿Es la primera palabra del título la palabra "A"?". Si es así, devolvemos la subcadena del título que comienza con su tercera letra, eliminando así "A" y el espacio. Si la primera palabra del título no es "A", entonces necesitamos volver a comprobar si la primera palabra del título es "The". Si lo es, utilizamos la subcadena del título que comienza con su quinto carácter, eliminando así "The" y un espacio. Si ambas pruebas fallan, simplemente pasamos el título como clave de ordenación. Podríamos añadir otra prueba a nuestro código para ver si la primera palabra es "An", pero no es necesario para este conjunto de datos. Al ejecutar esta última transformación XSLT, obtenemos el siguiente resultado.
![]()
"Mark Twain" ahora aparece antes que "Jules Verne". "Las aventuras de Huckleberry Finn" se muestra antes que "La famosa rana saltarina del condado de Calaveras" y "Un yanqui en la corte del rey Arturo". El problema en nuestro enfoque para la cadena de autores es que queremos que "Jules Verne" se trate como "Verne, Jules" para la ordenación, de modo que, si tuviéramos un libro de "Jimmy Verne", la ordenación los trataría como autores diferentes. Nuestro código no lo hace. Utilizar "concat(reverse(tokenize(author, ' '))[1], reverse(tokenize(author, ' '))[2])" ordenaría correctamente "Jules Verne" y "Jimmy Verne", pero esta solución solo funciona con nombres de dos palabras. Si un autor tuviera un sufijo ("Martin Luther King, Jr.") o múltiples palabras ("George Herbert Walker Bush"), el código fallaría. Existen muchas excepciones a las reglas generales de ordenación alfabética de nombres, y el código necesario para permitir todas las variantes está más allá del alcance de este artículo. Lo que queríamos demostrar es la capacidad de manipular datos XML sobre la marcha utilizando expresiones XPath. No siempre tenemos control total sobre el formato de nuestras fuentes de datos, pero utilizando el poder de las expresiones XPath, podemos transformar los datos al formato que necesitamos. Una copia de los archivos utilizados en estos ejemplos está disponible aquí.