web-dev-qa-db-fra.com

Pourquoi XSLT affiche-t-il tout le texte par défaut?

Salut, j'avais effectué une transformation qui supprime une balise si elle est nulle.

Je voulais vérifier si ma transformation fonctionnait bien, donc au lieu de la vérifier manuellement, j'ai écrit un code XSLT de plus qui vérifie simplement la présence de cette balise particulière dans le XML de sortie, si elle est nulle, le deuxième XSLT devrait sortir un texte "TROUVE". (Je n'ai pas vraiment besoin d'une sortie XML mais j'utilise simplement XSLT pour la recherche.)

Quand j'ai essayé avec ce code XSL ::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
</xsl:stylesheet>

Il génère toutes les DONNÉES TEXTE présentes dans le fichier XML,

pour éviter cela, j'ai dû écrire ce code ::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>

pourquoi l'ancien code produisait-il TEXT, pourquoi devrais-je insister pour que XSL ignore tous les autres textes? est que le comportement de tous les analyseurs XML ou seulement le mien (j'utilise l'analyseur msxml).

71
InfantPro'Aravind'

pourquoi l'ancien code produisait-il TEXT, pourquoi devrais-je insister pour que XSL ignore tout autre texte? est que le comportement de tous les analyseurs XML ou seulement le mien

Vous découvrez l'une des fonctionnalités XSLT les plus fondamentales telles que spécifiées dans la spécification: les modèles intégrés de XSLT.

De la spécification:

Il existe une règle de modèle intégrée pour permettre au traitement récursif de continuer en l'absence d'une correspondance de modèle réussie par une règle de modèle explicite dans la feuille de style. Cette règle de modèle s'applique aux nœuds d'élément et au nœud racine. Ce qui suit montre l'équivalent de la règle de modèle intégrée:

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

Il existe également une règle de modèle intégrée pour chaque mode, qui permet au traitement récursif de continuer dans le même mode en l'absence d'une correspondance de modèle réussie par une règle de modèle explicite dans la feuille de style. Cette règle de modèle s'applique aux nœuds d'élément et au nœud racine. Ce qui suit montre l'équivalent de la règle de modèle intégrée pour le mode m.

<xsl:template match="*|/" mode="m">
  <xsl:apply-templates mode="m"/>
</xsl:template>

Il existe également une règle de modèle intégrée pour le texte et les nœuds d'attribut qui copie le texte via:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

La règle de modèle intégrée pour le traitement des instructions et des commentaires est de ne rien faire.

<xsl:template match="processing-instruction()|comment()"/>

La règle de modèle intégrée pour les nœuds d'espace de noms est également de ne rien faire. Aucun modèle ne peut correspondre à un nœud d'espace de noms; par conséquent, la règle de modèle intégrée est la seule règle de modèle appliquée aux nœuds d'espace de noms.

Les règles de modèle intégrées sont traitées comme si elles avaient été importées implicitement avant la feuille de style et ont donc une priorité d'importation inférieure à toutes les autres règles de modèle. Ainsi, l'auteur peut remplacer une règle de modèle intégrée en incluant une règle de modèle explicite.

Ainsi, le comportement signalé est le résultat de l'application des modèles intégrés - le 1er et le 2e des trois.

C'est un bon modèle de conception XSLT pour remplacer les modèles intégrés par les vôtres qui émettront un message d'erreur à chaque appel afin que le programmeur connaisse immédiatement son la transformation "fuit":

Par exemple , s'il existe ce document XML:

<a>
  <b>
    <c>Don't want to see this</c>
  </b>
</a>

et il est traité avec cette transformation :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="a|b">
   <xsl:copy>
      <xsl:attribute name="name">
        <xsl:value-of select="name()"/>
      </xsl:attribute>
      <xsl:apply-templates/>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

le résultat est :

<a name="a">
   <b name="b">Don't want to see this</b>
</a>

et le programmeur sera très confus sur la façon dont le texte indésirable est apparu.

Cependant, il suffit d'ajouter ceci catch-all template permet d'éviter une telle confusion et de détecter immédiatement les erreurs :

 <xsl:template match="*">
  <xsl:message terminate="no">
   WARNING: Unmatched element: <xsl:value-of select="name()"/>
  </xsl:message>

  <xsl:apply-templates/>
 </xsl:template>

Maintenant, en plus de la sortie déroutante, le programmeur reçoit un avertissement qui explique immédiatement le problème :

 WARNING: Unmatched element: c

Ajout ultérieur de Michael Kay pour XSLT 3.0

Dans XSLT 3.0, plutôt que d'ajouter une règle de modèle fourre-tout, vous pouvez spécifier le comportement de secours sur un xsl:mode déclaration. Par exemple, <xsl:mode on-no-match="shallow-skip"/> fait sauter tous les nœuds qui ne correspondent pas (y compris les nœuds de texte), tandis que <xsl:mode on-no-match="fail"/> traite une absence de correspondance comme une erreur et <xsl:mode warning-on-no-match="true"/> entraîne un avertissement.

146
Dimitre Novatchev

Il existe plusieurs règles de modèle intégrées en XSL, dont l'une est la suivante:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

Il produit du texte.

14
Oded