2012-10-29 3 views
7

Ich habe einen String und ich brauche den ersten Buchstaben jedes Wortes in Großbuchstaben umwandeln und Ruhe Fall mit xsl zu senken, zum Beispielerste Zeichen jedes Wortes in Großbuchstaben

Eingang String = Dinesh Sachdev Kapil Muk

gewünschter Ausgang String = Dinesh Sachdev Kapil Muk

Obwohl, ich weiß, ich habe übersetzen zur Funktion verwenden, aber wie kann ich den ersten Charter jeden Wort in Großbuchstaben übersetzen und ruhen alle in Kleinbuchstaben mit XSLT 1.0

Dank

Antwort

10

Hier finden Sie nicht „nett“, und ich bin sicher, dass jemand (vor allem Dimitri) mit etwas einfiel viel einfacher (vor allem in XSLT 2.0) ... aber ich habe 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> 

Die Grundidee ist, dass Sie CamelCase aufrufen, wenn es ein Leerzeichen findet, dann läuft es CamelCaseWord auf allem vor der Raum (dh das erste Wort) und ruft dann CamelCase wieder mit dem alles nach der Raum (d. h. der Rest des Satzes). Andernfalls, wenn kein Leerzeichen gefunden wird (weil es das letzte Wort im Satz hat), ruft es einfach CamelCaseWord auf.

Die Vorlage CamelCaseWord übersetzt einfach das erste Zeichen von unten nach oben (falls erforderlich) und alle verbleibenden Zeichen von oben nach unten (falls erforderlich).

So nennen es Sie haben würde ...

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

Zusätzlich:

Ich vermisste die 1,0 Bedarf in der Frage. Dies funktioniert nur ab Version 2.0.

Ursprüngliche Antwort unten hier.

Ich glaube, dass dieser für mich vor einer Weile gearbeitet hat. Deklarieren Sie eine Funktion:

<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> 

und es verwenden:

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

Kredit geht an samjudson =>http://p2p.wrox.com/xslt/80938-title-case-string.html

+0

OP hat die 'xslt-1.0' Tag ...' unteren case' und "Großbuchstaben" ist nicht verfügbar in 1.0 – freefaller

+0

@freefaller Ooh, verpasst das. Wil ändert die Antwort, um dies für zukünftige Referenz zu reflektieren. Vielen Dank! – Kris

3

Hier ist ein 8 Jahre alt FXSL 1.x (ein XSLT 1.0 Bibliothek geschrieben vollständig in XSLT 1.0) Lösung:

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> 

Wenn diese Transformation auf dem folgende XML-Dokument (Test-strsplit-to-Words10 angewandt wird.xml):

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

das Ergebnis ist:

004.Lightning Crashes (Live).mp3 

Wenn auf diese XML-Dokument angelegt (Ihre bereitgestellt Probe):

dInEsh sAchdeV kApil Muk 

das Ergebnis ist :

DInEsh SAchdeV KApil Muk 

Mit nur ein wenig tweek, bekommen wir diesen Code:

<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> 

die nun das gewünschte Ergebnis produziert:

Dinesh Sachdev Kapil Muk 

Erklärung:

Das str-split-word-del Vorlage FXSL kann für die Tokenisierung mit (möglicherweise mehr als einem) Trennzeichen als String-Parameter verwendet werden.

0

Diese gleiche Funktion auf XQUERY:

Funktion XQuery Kamel Fall.

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

Eine sehr kurze Lösung, EXSLT die Verwendung split() Funktion:

<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> 

Arbeits Demo: http://www.xmlplayground.com/CNmKdF

1

Hier ist eine andere kurze Lösung. Es verwendet reines XSL-T 2.0. Ich weiß, OP eine Voraussetzung für die XSL-T hatte 1,0, aber da diese Seite ist # 1 auf Google für ‚xsl-t Titel Fall Funktion‘ im Jahr 2015 auf Platz scheint dies mehr relevant:

<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> 

Wo ‚xx‘ ist dein eigener Namensraum.

2

Sie können auch versuchen, diese:

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> 

und rückwärts: 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>