2010-01-12 11 views
1

J'écris un modèle XSL qui extrait des données de nombreuses sources secondaires. Un exemple document secondaire ressemble à ceci:XSL: Ignorer/supprimer les espaces de noms dans les documents secondaires

<toplevel xmlns:foo1="http://foo1"> 
<path xmlns="http://foo1"> 
    <mytag>bar</mytag> 
    </path> 
</toplevel> 

Dans le XSL, je fais ceci:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:foo1="http://foo1" 
exclude-result-prefixes="foo1"> 
    <xsl:variable name="secondary1" select="document('secondary1.xml')/toplevel"/> 
    <foo> 
    <xsl:value-of select="$secondary1//foo1:path/foo1:mytag"/> 
    </foo> 
</xsl:stylesheet> 

Avec beaucoup de sources secondaires, dont chacun utilise un espace de noms différent, préfixer chaque balise est fastidieux, et que beaucoup de répétitions ne peuvent pas être la bonne chose à faire de toute façon. Est-il possible d'utiliser document() de telle sorte que l'espace de noms de l'ensemble de nœuds importé soit supprimé (ou pour obtenir le même effet d'une autre manière)?

+0

Je présume que vous vouliez inclure une déclaration d'espace de noms par défaut dans le premier document: xmlns = "http: // foo1" Comme c'est le cas actuellement, les éléments ne sont pas dans un espace de noms. (Désolé pour l'espace supplémentaire dans l'URI d'espace de noms, je ne sais pas comment empêcher SO de le rendre comme un lien "foo1".) –

+0

Désolé, et oui, c'est ce que je voulais dire. J'ai édité la question en conséquence. – knipknap

Répondre

2

En substance, un nœud avec un espace de noms est animal entièrement différent qu'un nœud avec un autre espace de noms - même si elles partagent le même nom local. (Cela ressemble beaucoup à la façon dont les espaces de noms fonctionnent partout - il n'y a pas moyen d'ignorer les espaces de noms.)

L'approche propre consisterait à mentionner chaque espace de noms pourrait rencontrer dans le XSLT et travailler avec des préfixes, même si cela semble répétitif.

La façon pas si propre est la suivante:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
    <xsl:variable name="secondary1" select="document('secondary1.xml')"/> 

    <xsl:template match="/"> 
    <foo source="1"> 
     <xsl:value-of select=" 
     $secondary1//*[local-name() = 'path']/*[local-name() = 'mytag'] 
     "/> 
    </foo> 
    </xsl:template> 
</xsl:stylesheet> 

Ce n'est pas vraiment plus agréable à l'œil que de travailler avec des préfixes, il est plus long et plus difficile à lire, il est ambigu, et dernier mais pas des moindres - il est plus lent car le moteur doit tester un prédicat sur à chaque étape sur XPath. Faites votre choix.

3

Dans XPath/XSLT 1.0, pour sélectionner un élément qualifié d'espace de noms par son nom, vous devez utiliser un préfixe. Dans XSLT 2.0, vous pouvez utiliser la fonctionnalité xpath-default-namespace, qui vous permet de définir l'espace de noms par défaut pour les expressions XPath, de sorte que vous n'avez plus besoin d'utiliser les préfixes. Voir XSLT 2.0: xpath-default-namespace pour plus de détails. Vous pouvez utiliser cet attribut sur n'importe quel élément de votre feuille de style et il s'applique à tous les éléments descendants, sauf s'il est surchargé. (Qualifiez-le avec xsl: lorsque vous voulez le placer sur un élément non-XSLT, par exemple un élément de résultat littéral.)

Dans XPath 1.0, vous pouvez également sélectionner des éléments par nom local plutôt maladroitement en utilisant, par exemple, *[local-name() = 'path']/*[local-name() = 'mytag'] . Dans XPath 2.0, pour une plus grande concision, vous pouvez utiliser des caractères génériques d'espace de noms, comme dans *:path/*:mytag, as described here. C'était un ajout quelque peu controversé, car il semble encourager et/ou justifier la même utilisation douteuse des espaces de noms que votre système semble employer.

+0

+1 pour ajouter les subtilités 2.0. – Tomalak