2009-04-29 7 views
3

Comment puis-je limiter le nombre de mots d'une chaîne dans XSLT 1.0?Comment limiter le nombre de mots de chaîne dans XSLT 1.0?

+0

Pouvez-vous clarifier? Voulez-vous sortir les premiers "n" mots, par exemple? –

+0

J'ai posté une solution, qui fonctionne correctement avec un nombre variable de délimiteurs de mots (spécifiés) - contrairement à la solution de Mark Gravell qui traite seulement l'espace comme un délimiteur de mots. –

+0

Salut merci beaucoup pour vos réponses. Juste pour clarifier je ne peux pas lier aux extensions unfortunatley (nous sommes sur un réseau interne). Est-il possible de le faire sans utiliser d'extensions dans XSLT 1.0? Cordialement, Will –

Répondre

6

Que diriez-vous quelque chose comme:

<xsl:template match="data"> <!-- your data element or whatever --> 
    <xsl:call-template name="firstWords"> 
     <xsl:with-param name="value" select="."/> 
     <xsl:with-param name="count" select="4"/> 
    </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="firstWords"> 
    <xsl:param name="value"/> 
    <xsl:param name="count"/> 

    <xsl:if test="number($count) >= 1"> 
     <xsl:value-of select="concat(substring-before($value,' '),' ')"/> 
    </xsl:if> 
    <xsl:if test="number($count) > 1"> 
     <xsl:variable name="remaining" select="substring-after($value,' ')"/> 
     <xsl:if test="string-length($remaining) > 0"> 
     <xsl:call-template name="firstWords"> 
      <xsl:with-param name="value" select="$remaining"/> 
      <xsl:with-param name="count" select="number($count)-1"/> 
     </xsl:call-template> 
     </xsl:if> 
    </xsl:if> 
    </xsl:template> 
4

Ceci est une solution XSLT 1.0:

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

    <xsl:import href="strSplit-to-Words.xsl"/> 

    <xsl:output indent="yes" omit-xml-declaration="yes"/> 

    <xsl:template match="/"> 
     <xsl:variable name="vwordNodes"> 
     <xsl:call-template name="str-split-to-words"> 
      <xsl:with-param name="pStr" select="/"/> 
      <xsl:with-param name="pDelimiters" 
          select="', &#9;&#10;&#13;()-'"/> 
     </xsl:call-template> 
     </xsl:variable> 

     <xsl:call-template name="strTakeWords"> 
     <xsl:with-param name="pN" select="10"/> 
     <xsl:with-param name="pText" select="/*"/> 
     <xsl:with-param name="pWords" 
      select="ext:node-set($vwordNodes)/*"/> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template match="word" priority="10"> 
     <xsl:value-of select="concat(position(), ' ', ., '&#10;')"/> 
    </xsl:template> 

    <xsl:template name="strTakeWords"> 
     <xsl:param name="pN" select="10"/> 
     <xsl:param name="pText"/> 
     <xsl:param name="pWords"/> 
     <xsl:param name="pResult"/> 

     <xsl:choose> 
      <xsl:when test="not($pN > 0)"> 
      <xsl:value-of select="$pResult"/> 
      </xsl:when> 
      <xsl:otherwise> 
      <xsl:variable name="vWord" select="$pWords[1]"/> 
      <xsl:variable name="vprecDelims" select= 
       "substring-before($pText,$pWords[1])"/> 

      <xsl:variable name="vnewText" select= 
       "concat($vprecDelims, $vWord)"/> 

       <xsl:call-template name="strTakeWords"> 
       <xsl:with-param name="pN" select="$pN -1"/> 
       <xsl:with-param name="pText" select= 
         "substring-after($pText, $vnewText)"/> 
       <xsl:with-param name="pWords" select= 
        "$pWords[position() > 1]"/> 
       <xsl:with-param name="pResult" select= 
       "concat($pResult, $vnewText)"/> 
       </xsl:call-template> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

lorsque cette transformation est appliquée sur le document XML suivant:

<t> 
(CNN) -- Behind closed doors in recent days, 
senior White House aides have been saying that 
measuring President Obama's first 100 days 
is the journalistic equivalent of a Hallmark holiday. 
</t> 

le résultat recherché est retourné:

(CNN) -- Behind closed doors in recent days, senior White House

Prenez note:

  1. Lestr-split-to-words modèle deFXSLest l'utilisation d pour la segmentation.

  2. Ce modèle accepte un paramètre pDelimiters qui est une chaîne composée de tous les caractères devant être traités comme des délimiteurs. Ainsi, contrairement à d'autres solutions, il est possible de spécifier chaque délimiteur (et pas seulement un "espace") - dans ce cas 8 d'entre eux.

  3. Les appels modèle strTakeWords nommé lui-même récursive d'accumuler le texte avant et y compris tous les mots de la liste de mots produit par le tokenization, jusqu'à ce que le nombre spécifié de mots a été traitée.

+0

Salut merci beaucoup pour vos réponses. Juste pour clarifier je ne peux pas lier aux extensions unfortunatley (nous sommes sur un réseau interne). Y at-il un moyen de le faire sans utiliser d'extensions? Cordialement, Will –

+1

@Will Ma solution ne nécessite aucune fonction d'extension à l'exception de l'EXSLt node-set(), qui est implémentée en interne par la plupart des processeurs XSLT 1.0 (comme la classe .NET XslCompiledTransform). Tout modèle FXSL 1.x est écrit en XSLT pur et la seule fonction d'extension utilisée est la fonction EXSLT node-set() déjà mentionnée. Par conséquent, il n'y a absolument aucun obstacle à l'utilisation de cette solution dans un réseau interne - utilisez simplement un processeur XSLT 1.0, qui implémente la fonction EXSLT node-set() .NET XslCompiledTransform, Saxon 6, Xalan, JD, .. ., etc.) –

Questions connexes