XSLT xsl:sequence. Qu'est-ce bon pour..?

je sais que la question suivante est un peu de débutant mais j'ai besoin de votre aide pour comprendre un concept de base.

je voudrais dire d'abord que je suis programmeur XSLT depuis 3 ans et pourtant il y a des choses nouvelles et assez fondamentales que j'ai appris ici que je n'ai jamais su (dans mon travail, quelqu'un apprend à programmer seul, il n'y a pas de cours impliqué).

ma question Est: Quelle est l'utilisation de xsl:sequence?

j'ai utilisé xsl:copy-of pour copier nœud aussi est-à -xsl:apply-templates afin de modifier les noeuds que j'ai sélectionnés et value-of pour un texte simple.

je n'ai jamais eu la nécessité d'utiliser xsl:sequence. J'apprécierais que quelqu'un me montre un exemple de xsl:sequence usage qui est préférable ou ne peut être atteint sans ceux que j'ai mentionnés ci-dessus.

encore Une chose, j'ai lu sur le xsl:sequence définition, bien entendu, mais je ne pouvais pas comprendre comment il est utile.

30
demandé sur StuartLC 2013-01-16 19:16:11

4 réponses

<xsl:sequence> sur une valeur atomique (ou d'une séquence de valeurs atomiques) est le même que <xsl:copy-of> les deux renvoient juste une copie de leur entrée. La différence vient quand vous considérez les nœuds.

si $n est un noeud à un seul élément, par exemple défini par quelque chose comme

<xsl:variable name="n" select="/html"/>

<xsl:copy-of select="$n"/>

renvoie un copier du noeud, il a le même nom et la structure de l'enfant mais c'est un noeud avec une nouvelle identité (et pas de parent.)

<xsl:sequence select="$n"/>

renvoie le noeud $n, le noeud retourné a le même parent que $n et est égal à lui par le is Xpath de l'opérateur.

la différence est presque entièrement masquée dans l'usage traditionnel (style XSLT 1) du template car vous n'avez jamais accès au résultat de l'une ou l'autre opération le résultat du constructeur est implicitement copié sur l'arbre de sortie de sorte que le fait que xsl:sequence ne fait pas une copie est masqué.

<xsl:template match="a">
   <x>
   <xsl:sequence select="$n"/>
   </x>
</xsl:template>

est le même en tant que

<xsl:template match="a">
    <x>
    <xsl:copy-of select="$n"/>
    </x>
</xsl:template>

les deux font un nouveau noeud d'élément et copier le résultat du contenu que les enfants du nouveau nœud x.

cependant la différence est rapidement visible si vous utilisez des fonctions.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="data:,f">

    <xsl:variable name="s">
        <x>hello</x>
    </xsl:variable>

    <xsl:template name="main">
        ::
        :: <xsl:value-of select="$s/x is f:s($s/x)"/>
        :: <xsl:value-of select="$s/x is f:c($s/x)"/>
        ::
        :: <xsl:value-of select="count(f:s($s/x)/..)"/>
        :: <xsl:value-of select="count(f:c($s/x)/..)"/>
        ::
    </xsl:template>

    <xsl:function name="f:s">
        <xsl:param name="x"/>
        <xsl:sequence select="$x"/>
    </xsl:function>

    <xsl:function name="f:c">
        <xsl:param name="x"/>
        <xsl:copy-of select="$x"/>
    </xsl:function>

</xsl:stylesheet>

Produit

$ saxon9 -it main seq.xsl
<?xml version="1.0" encoding="UTF-8"?>
::
:: true
:: false
::
:: 1
:: 0
::

Voici les résultats de xsl:sequence et xsl:copy-of sont radicalement différentes.

39
répondu David Carlisle 2016-12-19 02:13:02

le cas d'utilisation le plus courant pour XSL:sequence est de retourner un résultat de XSL:function.

<xsl:function name="f:get-customers">
  <xsl:sequence select="$input-doc//customer"/>
</xsl:function>

Mais il peut également être utile dans d'autres contextes, par exemple

<xsl:variable name="x" as="element()*">
  <xsl:choose>
    <xsl:when test="$something">
       <xsl:sequence select="//customer"/>
    </xsl:when>
    <xsl:otherwise>
       <xsl:sequence select="//supplier"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

la chose clé ici est qu'il renvoie des références aux noeuds originaux, il ne fait pas de nouvelles copies.

21
répondu Michael Kay 2013-01-16 18:13:09

bien retourner une valeur d'un certain type que vous utilisez xsl:sequencexsl:value-of malgré son nom crée toujours un noeud de texte (depuis XSLT 1.0). Donc dans un corps de fonction vous utilisez

  <xsl:sequence select="42"/>

retour xs:integer valeur, vous utiliseriez

<xsl:sequence select="'foo'"/>

retour xs:string valeur

<xsl:sequence select="xs:date('2013-01-16')"/>

retour xs:date valeur et ainsi de suite. Bien sûr, vous pouvez également retourner des séquences avec par exemple <xsl:sequence select="1, 2, 3"/>.

vous ne voudriez pas créer un noeud de texte ou même un noeud d'élément dans ces cas à mon avis comme il est inefficace.

donc c'est mon avis, avec le nouveau système de type basé sur le schéma de XSLT et XPath 2.0, Il faut trouver un moyen de retourner ou de transmettre les valeurs de ces types et une nouvelle construction était nécessaire.

[edit]Michael Kay dit dans son "XSLT 2.0 and XPath 2.0 programmer's reference" à propos de xsl:sequence: "cette instruction d'apparence innocente introduite dans XSLT 2.0 a des effets de grande portée sur la capacité du langage XSLT, parce que cela signifie que les instructions XSLT et les constructeurs de séquence (et donc les fonctions et les gabarits) deviennent capables de retourner n'importe quelle valeur permise par le modèle de données XPath. Sans elle, les instructions XSLT ne pourraient être utilisées que pour créer de nouveaux noeuds dans une arborescence de résultats, mais avec elle, elles peuvent aussi renvoyer des valeurs atomiques et des références aux noeuds existants.".

6
répondu Martin Honnen 2013-01-16 17:18:54

une Autre utilisation est de créer une balise uniquement si elle a un enfant. Un exemple est requis:

<a>
    <b>node b</b>
    <c>node c</c>
</a>

quelque part dans votre XSLT :

<xsl:variable name="foo">
    <xsl:if select="b"><d>Got a "b" node</d></xsl:if>
    <xsl:if select="c"><d>Got a "c" node</d></xsl:if>
</xsl:variable>
<xsl:if test="$foo/node()">
    <wrapper><xsl:sequence select="$foo"/></wrapper>
</xsl:if>

Vous pouvez voir la démo ici : http://xsltransform.net/eiZQaFz

C'est mieux que de tester chaque balise comme ceci :

<xsl:if test="a|b">...</xsl:if>

parce que vous finiriez par l'éditer en deux endroits. Aussi la vitesse de traitement dépend des balises dans votre imput. Si c'est le dernier de vos test, le moteur va tester la présence de tout le monde avant. Que $foo/node() est une des locutions pour "est-il un élément enfant ?", le moteur peut l'optimiser. Ce faisant, vous facilitez la vie de tout le monde.

0
répondu programaths 2015-04-17 09:07:38