2012-10-29 18 views
7

ho una stringa e ho bisogno di convertire la prima lettera di ogni parola in maiuscolo e il resto in minuscolo utilizzando xsl, per esempio,Convertire primo carattere di ogni parola in maiuscolo

String input = Dinesh Sachdev Kapil Muk

String output desiderato = Dinesh Sachdev Kapil Muk

Anche se, so che devo usare la funzione di tradurre per lo scopo, ma come posso tradurre la prima carta di ogni parola per Maiuscolo e riposare il tutto in minuscolo con XSLT 1.0

Grazie

risposta

10

seguenti non è "bello", e sono sicuro che qualcuno (soprattutto Dimitri) potrebbe venire con qualcosa di molto più semplice (soprattutto in XSLT 2.0) ... ma ho tested this and it works

<xsl:template name="CamelCase"> 
    <xsl:param name="text"/> 
    <xsl:choose> 
    <xsl:when test="contains($text,' ')"> 
     <xsl:call-template name="CamelCaseWord"> 
     <xsl:with-param name="text" select="substring-before($text,' ')"/> 
     </xsl:call-template> 
     <xsl:text> </xsl:text> 
     <xsl:call-template name="CamelCase"> 
     <xsl:with-param name="text" select="substring-after($text,' ')"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:call-template name="CamelCaseWord"> 
     <xsl:with-param name="text" select="$text"/> 
     </xsl:call-template> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<xsl:template name="CamelCaseWord"> 
    <xsl:param name="text"/> 
    <xsl:value-of select="translate(substring($text,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')" /><xsl:value-of select="translate(substring($text,2,string-length($text)-1),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')" /> 
</xsl:template> 

L'idea di base è che tu chiami lo CamelCase, se trova uno spazio, quindi esegue CamelCaseWord su tutto prima dello dello spazio (es. la prima parola) e chiama di nuovo CamelCase di nuovo con il del tutto dopo lo lo spazio (ovvero il resto della frase). Altrimenti se non viene trovato spazio (perché è l'ultima parola nella frase), chiama semplicemente CamelCaseWord.

Il modello CamelCaseWord converte semplicemente il primo carattere dal basso verso l'alto (se necessario) e tutti i caratteri rimanenti dall'alto verso il basso (se necessario).

Quindi, per chiamare che avresti avuto ...

<xsl:call-template name="CamelCase"> 
    <xsl:with-param name="text">dInEsh sAchdeV kApil Muk</xsl:with-param> 
</xsl:call-template> 
3

aggiuntive:

ho perso il requisito 1.0 nella questione. Funzionerà solo dalla versione 2.0.

Risposta originale qui sotto.

Credo che questo abbia funzionato per me qualche tempo fa. Dichiarare una funzione:

<xsl:function name="my:titleCase" as="xs:string"> 
    <xsl:param name="s" as="xs:string"/> 
    <xsl:choose> 
     <xsl:when test="lower-case($s)=('and','or')"> 
      <xsl:value-of select="lower-case($s)"/> 
     </xsl:when> 
     <xsl:when test="$s=upper-case($s)"> 
      <xsl:value-of select="$s"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="concat(upper-case(substring($s, 1, 1)), lower-case(substring($s, 2)))"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:function> 

e usarlo:

<xsl:sequence select="string-join(for $x in tokenize($text,'\s') return my:titleCase($x),' ')"/> 

merito va a samjudson =>http://p2p.wrox.com/xslt/80938-title-case-string.html

+0

OP ha il tag 'xslt-1.0' ...' inferiore case' e 'maiuscole 'non è disponibile in 1.0 – freefaller

+0

@freefaller Ooh, mancato quello. Cambiare risposta per riflettere questo per riferimento futuro. Grazie! – Kris

3

Ecco un 8 anni FXSL 1.x (un XSLT 1.0 soluzione di libray scritta completamente in XSLT 1.0):

test-strSplit-to-Words 10.xsl:

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

    <!-- To be applied on: test-strSplit-to-Words10.xml --> 

    <xsl:output indent="yes" omit-xml-declaration="yes"/> 
    <xsl:variable name="vLower" 
     select="'abcdefgijklmnopqrstuvwxyz'"/> 
    <xsl:variable name="vUpper" 
     select="'ABCDEFGIJKLMNOPQRSTUVWXYZ'"/> 

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

     <xsl:apply-templates select="ext:node-set($vwordNodes)/*"/> 
    </xsl:template> 

    <xsl:template match="word"> 
     <xsl:choose> 
     <xsl:when test="not(position() = last())"> 
      <xsl:value-of 
      select="translate(substring(.,1,1),$vLower,$vUpper)"/> 
      <xsl:value-of select="substring(.,2)"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="."/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

    <xsl:template match="delim"> 
     <xsl:value-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

Quando questa trasformazione viene applicata sul seguente documento XML (test-strSplit-to-Words10.xml):

<t>004.lightning crashes (live).mp3</t> 

il risultato è:

004.Lightning Crashes (Live).mp3 

Quando applicata a questo documento XML (il campione in dotazione):

dInEsh sAchdeV kApil Muk 

il risultato è :

DInEsh SAchdeV KApil Muk 

Con un po Tweek, otteniamo questo codice:

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

    <!-- To be applied on: test-strSplit-to-Words10.xml --> 

    <xsl:output indent="yes" omit-xml-declaration="yes"/> 
    <xsl:variable name="vLower" 
     select="'abcdefgijklmnopqrstuvwxyz'"/> 
    <xsl:variable name="vUpper" 
     select="'ABCDEFGIJKLMNOPQRSTUVWXYZ'"/> 

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

     <xsl:apply-templates select="ext:node-set($vwordNodes)/*"/> 
    </xsl:template> 

    <xsl:template match="word"> 
      <xsl:value-of 
      select="translate(substring(.,1,1),$vLower,$vUpper)"/> 
      <xsl:value-of select="translate(substring(.,2), $vUpper, $vLower)"/> 
    </xsl:template> 

    <xsl:template match="delim"> 
     <xsl:value-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

che ora produce il risultato voluto:

Dinesh Sachdev Kapil Muk 

Spiegazione:

Il str-split-word-del modello di FXSL può essere utilizzato per la tokenizzazione con (possibilmente più di uno) delimitatori specificati come parametro stringa.

0

Questa stessa funzione su XQuery:

funzione XQuery per Camel Caso.

declare function xf:toCamelCase($text as xs:string?) as xs:string{ 
    if(contains($text,' ')) then 
     fn:concat(xf:CamelCaseWord(substring-before($text,' ')),' ', xf:toCamelCase(substring-after($text,' '))) 
    else 
     xf:CamelCaseWord($text) 
}; 

declare function xf:CamelCaseWord($text as xs:string?) as xs:string{ 
    fn:concat(translate(substring($text,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 
       translate(substring($text,2,string-length($text)-1),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')) 
}; 
0

A breve soluzione, utilizzando la funzione di EXSLT split():

<xsl:variable name='text' select='"dInEsh sAchdeV kApil Muk"' /> 
<xsl:variable name='lowers' select='"abcdefghijklmnopqrstuvwxyz"' /> 
<xsl:variable name='uppers' select='"ABCDEFGHIJKLMNOPQRSTUVWXYZ"' /> 

<xsl:template match="/"> 

    <xsl:for-each select='str:split($text, " ")'> 
     <xsl:value-of select='concat(
      translate(substring(., 1, 1), $lowers, $uppers), 
      translate(substring(., 2), $uppers, $lowers), 
      " " 
     )' /> 
    </xsl:for-each> 
</xsl:template> 

demo di lavoro: http://www.xmlplayground.com/CNmKdF

1

Ecco un altro breve soluzione. Usa puro XSL-T 2.0. So che OP ha avuto un requisito per XSL-T 1.0, ma dal momento che questa pagina è alla posizione # 1 su Google per 'funzione maiuscole xsl-t' nel 2015, questo sembra più pertinente:

<xsl:function name="xx:fixCase"> 
    <xsl:param name="text" /> 
    <xsl:for-each select="tokenize($text,' ')"> 
     <xsl:value-of select="upper-case(substring(.,1,1))" /> 
     <xsl:value-of select="lower-case(substring(.,2))" /> 
     <xsl:if test="position() ne last()"> 
      <xsl:text> </xsl:text> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:function> 

dove 'xx' è il tuo spazio dei nomi.

2

Si può anche provare questo:

http://www.xsltfunctions.com/xsl/functx_camel-case-to-words.html

<xsl:function name="functx:camel-case-to-words" as="xs:string" 
        xmlns:functx="http://www.functx.com"> 
     <xsl:param name="arg" as="xs:string?"/> 
     <xsl:param name="delim" as="xs:string"/> 

     <xsl:sequence select=" 
     concat(substring($arg,1,1), 
       replace(substring($arg,2),'(\p{Lu})', 
          concat($delim, '$1'))) 
    "/> 

</xsl:function> 

e indietro: http://www.xsltfunctions.com/xsl/functx_words-to-camel-case.html

<xsl:function name="functx:words-to-camel-case" as="xs:string" 
       xmlns:functx="http://www.functx.com"> 
    <xsl:param name="arg" as="xs:string?"/> 

    <xsl:sequence select=" 
    string-join((tokenize($arg,'\s+')[1], 
     for $word in tokenize($arg,'\s+')[position() > 1] 
     return functx:capitalize-first($word)) 
     ,'') 
"/> 

</xsl:function>