XSLT : local-name()

Récupération d'un élément appartenant à un espace de nom

Définition

La fonction XSLT local-name() retourne le noeud passé en paramètre de la fonction en s'affranchissant de l'espace de nom.

En effet, par défaut, une transformation XSL traite les noeuds appartenant à un espace de nom bien précis et ne s'occupe pas de ceux qui n'ont pas été spécifiés. local-name() permet de contourner ce problème et de récupérer les noeuds manquants. Cela peut-être fort utile lorsque le fichier source provient d'un traitement qu'on n'a pas les moyens de paramétrer ou de modifier.

Ainsi, lorsque la transformation rencontrera :

<element xmlns="namespace-uri">
...
</element>

la fonction local-name() retournera le noeud element en omettant son espace de nom.

A contrario, la fonction namespace-uri() retourne l'adresse d'espace de nom défini par xmlns.

Utilisation

Récupération d'un noeud

Par défaut, le XSL ne traite que les noeuds n'appartenant pas à un espace de nom (c'est-à-dire un espace de nom non spécifié). Donc, si il devient nécessaire de récupérer spécifiquement les noeuds d'un espace de nom donné, alors il convient d'utiliser la fonction local-name(). Par exemple, dans le cas d'un flux atom, l'espace de nom étant http://www.w3.org/2005/Atom, il conviendra de traiter les noeuds de la façon suivante:

<xsl:template match="/*[local-name()='feed']">
...
</xsl:template>

ou encore :

<xsl:value-of select="/*[local-name()='feed']/*[local-name()='entry']/link[@rel='related']/@href"/>

Nous voyons que la notation est rapidement alourdie. Fort heureusement, le XSLT 2.0 corrige en grand partie ce problème.

Copie quasi-conforme sans les espaces de nom

Dans le cadre d'un traitement de fichier HTML ou XML, il peut arriver que des espaces de noms subsistent et perturbent un traitement XSL. Les noeuds appartenant à un espace de nom non spécifié ne sont pas traités.

Par exemple, dans le cas d'une normalisation d'un fichier HTML (généré par Excel) en XHTML par l'intermédiaire de tidy, nous obtenons :

<html xmlns="http://www.w3.org/1999/xhtml">
...
</html>

La partie xmlns="http://www.w3.org/1999/xhtml" concerne l'espace de nom. Et dans un traitement générique sans espace de nom spécifié, tous les noeuds fils seront ignorés. Comme l'espace de nom se situe au niveau de la racine html dans le cas présent, cela signifie que le traitement ne retournera rien.

Pour supprimer les espaces de noms, il faut donc, par exemple, convertir le fichier en une copie quasi-identique, sans les espaces de nom. Pour cela, la fonction local-name() permet d'extraire le nom local d'un élément appartenant à un espace de nom. Ainsi, le nom local de :

<html xmlns="http://www.w3.org/1999/xhtml">
...
</html>

est html.

L'élément sans son espace de nom peut être recréé grâce à xsl:element.

Un simple transformation peut s'occuper de supprimer tous les espaces de noms :

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output
method="xml"
indent="yes"
encoding="utf-8"/>


<xsl:template match="*">
<!-- retire les éléments s'ils existent -->
<xsl:element name="{local-name()}">
<!-- attributs -->
<xsl:for-each select="@*">
<!-- retire les attributs, s'ils existent -->
<xsl:attribute name="{local-name()}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates />
</xsl:element>
</xsl:template>

</xsl:stylesheet>

Cet exemple copie tous les éléments de la source, sauf les attributs des espaces de noms. Ensuite, ce fichier débarrassé des espaces de noms peut alors être traité aisément, de façon générique.

XSLT 2.0

Avec le XSLT 2.0, récupérer un espace de nom est plus facile, notamment dans le cas d'un espace de nom par défaut, comme c'est le cas pour un document XHTML qui possède toujours xmlns="http://www.w3.org/1999/xhtml". Pour cela, il suffit de définir l'attribut xpath-default-namespace="http://www.w3.org/1999/xhtml" dans la définition de la transformation :

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://www.w3.org/1999/xhtml">
<xsl:output
method="xml"
indent="yes"
encoding="utf-8"/>

...
</xsl:stylesheet>

Et dans ce cas, plus besoin d'utiliser local-name(), excepté pour des espaces de nom locaux différent de xmlns="http://www.w3.org/1999/xhtml".