2010-04-15 10 views
10

Sto provando a formattare stringhe in XSLT che devono essere in caso pascal per essere utilizzate in modo appropriato per l'applicazione con cui sto lavorando.Come formattare una stringa in caso Pascal in XSLT?

Ad esempio:

this_text sarebbe diventato thistext
this_long_text sarebbe diventato ThisLongText

E 'possibile impostare anche questa da dove posso inviare un input al formato quindi non devo ricreare il formato più volte?

+0

Buona domanda (+1). Vedi la mia risposta per una soluzione XSLT completa :) –

+0

Il processo ** reverse ** è anche disponibile. Vedi la mia risposta qui sotto. ;-) –

risposta

8

Questa trasformazione:

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

<xsl:variable name="vLower" select= 
    "'abcdefghijklmnopqrstuvwxyz'"/> 

<xsl:variable name="vUpper" select= 
    "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="text()"> 
    <xsl:call-template name="Pascalize"> 
    <xsl:with-param name="pText" select="concat(., '_')"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="Pascalize"> 
    <xsl:param name="pText"/> 

    <xsl:if test="$pText"> 
    <xsl:value-of select= 
    "translate(substring($pText,1,1), $vLower, $vUpper)"/> 

    <xsl:value-of select="substring-before(substring($pText,2), '_')"/> 

    <xsl:call-template name="Pascalize"> 
    <xsl:with-param name="pText" 
     select="substring-after(substring($pText,2), '_')"/> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

quando applicato su questo documento XML:

<t> 
    <a>this_text</a> 
    <b>this_long_text</b> 
</t> 

produce il risultato desiderato:

<t> 
    <a>ThisText</a> 
    <b>ThisLongText</b> 
</t> 

BTW, questo è camelCase e questo è PascalCase

+0

+1 Impressionante - ben fatto! –

+0

Grazie per la rapida risposta - stiamo lavorando per implementarlo ora. Sono d'accordo con Andrew - ben fatto! – OpenDataAlex

+0

Domanda di followup rapida: la trasformazione che sto creando sta convertendo un file XML in un file YAML. Ciò sembra influire su tutto il testo e non su intestazioni specifiche. C'è un modo per specificare quale testo voglio eseguire attraverso il modello Pascalize? Grazie ancora per avermi condotto lungo la strada giusta. – OpenDataAlex

0

Grazie a Dimitre, sono stato in grado di ottenere la maggior parte del tragitto. Quando si eseguono le stringhe tramite il modello Pascalize, il bit dopo l'ultimo '_' è stato interrotto. C'è probabilmente un modo più pulito di farlo, ma qui è il codice che ho usato:

<xsl:template name="Pascalize"> 
    <xsl:param name="pText"/> 

    <xsl:if test="$pText"> 
     <xsl:value-of select="translate(substring($pText,1,1), $vLower, $vUpper)"/> 

     <xsl:value-of select="substring-before(substring($pText,2), '_')"/> 

     <xsl:call-template name="Pascalize"> 
      <xsl:with-param name="pText" select="substring-after(substring($pText,2), '_')"/> 
     </xsl:call-template> 

     <xsl:call-template name="GrabLastPart"> 
      <xsl:with-param name="pText" select="$pText"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 

<xsl:template name="GrabLastPart"> 
    <xsl:param name="pText"/> 

    <xsl:choose> 
     <xsl:when test="contains($pText, '_')"> 
      <xsl:call-template name="GrabLastPart"> 
       <xsl:with-param name="pText" expr="substring-after($pText, '_')"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="substring($pText, 2)"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
4

Questa versione ha funzionato per me. Ho aggiunto una scelta che emette "il resto" della stringa quando non sono presenti più barre trasversali.

<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/> 
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/> 

<xsl:template name="Pascalize"> 
    <xsl:param name="pText" /> 
    <xsl:if test="$pText"> 
     <xsl:value-of select="translate(substring($pText,1,1), $vLower, $vUpper)" /> 
     <xsl:choose> 
      <xsl:when test="contains($pText, '_')"> 
       <xsl:value-of select="substring-before(substring($pText,2), '_')" /> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="substring($pText,2)" /> 
      </xsl:otherwise> 
     </xsl:choose> 
     <xsl:call-template name="Pascalize"> 
      <xsl:with-param name="pText" select="substring-after(substring($pText,2), '_')" /> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 

Inoltre, nel caso in cui qualcuno viene qui cercando il rovescio processo (che mi è capitato di richiedere anche oggi e non riuscivo a trovare un solo esempio di ovunque) ...

<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/> 
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/> 

<xsl:template name="TitleCase"> 
    <xsl:param name="pText" /> 
    <xsl:call-template name="TitleCase_recurse"> 
     <xsl:with-param name="pText" select="concat(translate(substring($pText,1,1), $vLower, $vUpper), substring($pText,2))" /> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="TitleCase_recurse"> 
    <xsl:param name="pText" /> 
    <xsl:if test="string-length($pText) &gt; 1"> 
     <xsl:if test="not(substring($pText,1,1) = ' ' and substring($pText,1,1) = ' ')"> 
      <xsl:value-of select="substring($pText,1,1)" /> 
     </xsl:if> 
     <xsl:if test="translate(substring($pText,1,1), $vLower, $vUpper) != substring($pText,1,1)"> 
      <xsl:if test="translate(substring($pText,2,1), $vLower, $vUpper) = substring($pText,2,1)"> 
       <xsl:text> </xsl:text> 
      </xsl:if> 
     </xsl:if> 
     <xsl:call-template name="TitleCase_recurse"> 
      <xsl:with-param name="pText" select="substring($pText,2)" /> 
     </xsl:call-template> 
    </xsl:if> 
    <xsl:if test="string-length($pText) = 1"> 
     <xsl:value-of select="$pText" /> 
    </xsl:if> 
</xsl:template> 

Mi piace quando il mio cervello subconscio si apre una risposta poche ore dopo che mi sono completamente arreso coscientemente. ;-)

+0

Ben fatto. Sempre un processo di apprendimento con queste cose, heh. – OpenDataAlex

1

stavo cercando di raggiungere il "pascalizing" con la seguente chiamata di funzione XLST:

<xsl:value-of select="fn:replace(@name,'_(\w{1})','\U$1')"/> 

Purtroppo il processore lancia il messaggio di errore "stringa di sostituzione non valido nel replace(): \ personaggio deve essere seguito da \ o $ "

il problema è il modificatore \ U che dovrebbe eseguire la conversione in maiuscolo del modello corrispondente.Se lo cambio a

<xsl:value-of select="fn:replace(@name,'_(\w{1})','\\U$1')"/> 

stringa di output contiene la sequenza '\ U' perché è ormai esacped - ma io non voglio scappare, io voglio fare ;-) essere efficace. Ho eseguito il test

<xsl:value-of select="fn:replace(@name,'_(\w{1})','$1')"/> 

(senza convertire la corrispondenza in maiuscolo) e che funziona correttamente. Ma naturalmente non fa maiuscole, rimuove solo i caratteri di sottolineatura e sostituisce la lettera dopo il trattino basso da solo invece di capitalizzarlo. Sto facendo qualcosa di sbagliato qui o il modificatore di \ U semplicemente non è supportato nell'implementazione regex del mio processore XSLT?

+0

Non sono un esperto di espressioni regolari di alcun tipo, ma non credo che \ U sia supportato. – OpenDataAlex

6

Qui, due anni dopo il fatto, è una soluzione XSLT 2.0:

<xsl:function name="fn:pascal-case"> 
    <xsl:param name="string"/> 
    <xsl:value-of select="string-join(for $s in tokenize($string,'\W+') return concat(upper-case(substring($s,1,1)),substring($s,2)),'')"/> 
</xsl:function> 

Sarà pascalize sia 'this_long_text' o 'questo a lungo-testo' a 'ThisLongText' perché rompe su qualsiasi non -word caratteri.

Nelle espressioni regex a me più familiari (perl, pcre, ecc.), Un underscore è considerato parte della classe di caratteri '\ w' (quindi non fa parte di \ W), ma per XSLT 2.0 l'XSD tipi di dati sono utilizzati (http://www.w3.org/TR/xmlschema-2/) e '\ w' è definito come:

[#x0000-#x10FFFF]-[\p{P}\p{Z}\p{C}] (all characters except the set of "punctuation", "separator" and "other" characters) 

così '\ W' comprende una sottolineatura.

Problemi correlati