2012-12-20 9 views
14

La funzione normalize-space sostituisce le sequenze di spazi bianchi con un singolo spazio e taglia la stringa fornita. Come posso tagliare solo la stringa senza la sostituzione di spazi bianchi? Esistono soluzioni proprietarie come orcl:left-trim, ma sto cercando uno non proprietario.Come posso tagliare lo spazio in XSLT senza sostituire gli spazi bianchi di replicazione da quelli singoli?

Esempio:

<xsl:value-of select="trim(/Car/Description)"/> 

dovrebbe girare

<car> 
    <description> To get more information look at:  www.example.com </description> 
</car> 

in

"To get more information look at:  www.example.com" 

risposta

16

Una soluzione che utilizza solo xslt 1.0 modelli: codice

<xsl:variable name="whitespace" select="'&#09;&#10;&#13; '" /> 

<!-- Strips trailing whitespace characters from 'string' --> 
<xsl:template name="string-rtrim"> 
    <xsl:param name="string" /> 
    <xsl:param name="trim" select="$whitespace" /> 

    <xsl:variable name="length" select="string-length($string)" /> 

    <xsl:if test="$length &gt; 0"> 
     <xsl:choose> 
      <xsl:when test="contains($trim, substring($string, $length, 1))"> 
       <xsl:call-template name="string-rtrim"> 
        <xsl:with-param name="string" select="substring($string, 1, $length - 1)" /> 
        <xsl:with-param name="trim" select="$trim" /> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$string" /> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:if> 
</xsl:template> 

<!-- Strips leading whitespace characters from 'string' --> 
<xsl:template name="string-ltrim"> 
    <xsl:param name="string" /> 
    <xsl:param name="trim" select="$whitespace" /> 

    <xsl:if test="string-length($string) &gt; 0"> 
     <xsl:choose> 
      <xsl:when test="contains($trim, substring($string, 1, 1))"> 
       <xsl:call-template name="string-ltrim"> 
        <xsl:with-param name="string" select="substring($string, 2)" /> 
        <xsl:with-param name="trim" select="$trim" /> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$string" /> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:if> 
</xsl:template> 

<!-- Strips leading and trailing whitespace characters from 'string' --> 
<xsl:template name="string-trim"> 
    <xsl:param name="string" /> 
    <xsl:param name="trim" select="$whitespace" /> 
    <xsl:call-template name="string-rtrim"> 
     <xsl:with-param name="string"> 
      <xsl:call-template name="string-ltrim"> 
       <xsl:with-param name="string" select="$string" /> 
       <xsl:with-param name="trim" select="$trim" /> 
      </xsl:call-template> 
     </xsl:with-param> 
     <xsl:with-param name="trim" select="$trim" /> 
    </xsl:call-template> 
</xsl:template> 

prova:

<ltrim> 
    <xsl:call-template name="string-ltrim"> 
     <xsl:with-param name="string" select="' &#10; test '" /> 
    </xsl:call-template> 
</ltrim> 
<rtrim> 
    <xsl:call-template name="string-rtrim"> 
     <xsl:with-param name="string" select="' &#10; test &#10; '" /> 
    </xsl:call-template> 
</rtrim> 
<trim> 
    <xsl:call-template name="string-trim"> 
     <xsl:with-param name="string" select="' &#10; test &#10; '" /> 
    </xsl:call-template> 
</trim> 

uscita:

<test> 
    <ltrim>test </ltrim> 
    <rtrim> 
    test</rtrim> 
    <trim>test</trim> 
</test> 
+0

Mi piace la soluzione pulita di non dover aggiungere ulteriori librerie - grazie per questo! Dato che prima dovrei chiedere al project manager, se possiamo aggiungere librerie aggiuntive, questa soluzione è chiaramente preferibile per me. Immagino che non ci sia modo di mettere semplicemente un parametro all'inizio del file xsl per avere tutti i campi in pareggio, vero? Ho trovato '', ma questo viene applicato _after_ le altre trasformazioni come 'concat (...)', portando a risultati come 'Lastname, Firstname' invece di' Lastname, Firstname'. Sembra che non ci sia una soluzione così semplice ... –

+2

@MathiasBader: 'xsl: strip-space' opera sul documento di origine, prima di qualsiasi trasformazione e rimuove i nodi di testo che contengono solo spazi. Probabilmente non risolverà il tuo problema. La soluzione più semplice sarebbe probabilmente quella di creare una trasformazione separata che taglia solo gli spazi bianchi degli elementi selezionati e usa il risultato come input per la seconda trasformazione. Questo può essere fatto in un singolo foglio di stile usando le funzioni di estensione per un processore specifico o usando uno strumento/api esterni per richiamare le trasformazioni. –

+0

Usare una (pre) trasformazione separata con uno strumento esterno era qualcosa che avevo anche in mente. Ho solo pensato che il problema sembra essere così comune, che ho pensato che ci fosse una soluzione più semplice fornita da XSLT che non avevo ancora trovato. –

2

Utilizzando FXSL (libreria open source per XSLT programmazione funzionale, scritto interamente in XSL T) si scrive semplicemente:

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

    <xsl:output method="text"/> 
    <xsl:template match="/*/description"> 
    '<xsl:call-template name="trim"> 
     <xsl:with-param name="pStr" select="."/> 
    </xsl:call-template>' 
    </xsl:template> 
</xsl:stylesheet> 

Quando questa trasformazione viene applicata sul documento XML fornito:

<car> 
    <description> To get more information look at:  www.example.com </description> 
</car> 

The Wanted, risultato corretto è prodotto:

'To get more information look at:  www.example.com' 

Come funziona il modello trim?

Taglia gli spazi bianchi iniziali, quindi inverte la stringa risultante e taglia gli spazi bianchi iniziali, quindi inverte infine la stringa risultante.


II. XPath soluzione 2,0:

Uso:

replace(replace(/*/description, '^\s*(.+?)\s*$', '$1'), '^ .*$', '') 

Ecco un XSLT - 2.0 - verifica base:

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

<xsl:template match="/"> 
    "<xsl:sequence 
     select="replace(replace(/*/description, '^\s*(.+?)\s*$', '$1'), '^ .*$', '')"/>" 
</xsl:template> 
</xsl:stylesheet> 

Quando questa trasformazione viene applicata sul documento XML fornito (sopra), l'espressione XPath viene valutata e il risultato di questa valutazione viene copiato nell'output:

"To get more information look at:  www.example.com" 
+0

Grazie per la risposta, che suona come una buona soluzione. Ho ragione che non esiste una soluzione "nativa" che non richiederebbe una libreria aggiuntiva (che, ovviamente, sarebbe preferibile importare una libreria aggiuntiva)? –

+0

@MathiasBader, Prima di tutto, usare FXSL * è * una soluzione nativa - FXSL è un insieme di modelli XSLT. Nel caso in cui non si voglia utilizzare FXSL, si può scrivere una soluzione XSLT ricorsiva: non è consigliabile farlo quando si può semplicemente chiamare la soluzione FXSL già esistente (e testata). Se non vuoi risparmiare qualche ora o un giorno di lavoro aggiuntivo e assicurati che non ci siano errori nella soluzione, scrivi una trasformazione da zero. Lo scopo di FXSL è proprio quello di minimizzare lo sforzo di scrivere soluzioni ai problemi che sono molto difficili o "quasi impossibili". –

+0

@MathiasBader, per dirla in altre parole, con questa risposta voglio: 1. Per risparmiare un sacco di tempo e sforzi di sviluppo/verifica. 2. Per farti sapere che esiste uno strumento che può ridurre drasticamente il tempo di sviluppo XSLT per la maggior parte delle attività e rendere le attività che sono proibitive ("quasi impossibili") abbastanza naturali e dirette con XSLT. –

-2

Se non si dispone di eventuali spazi in mezzo, si può semplicemente utilizzare:

translate(/Car/Description,' ','') 
+0

Bella idea, ma come probabilmente avete già intuito, si tratta purtroppo di una semplificazione. –

2

normalize-space (actualSting) - Questo lo farà.

+0

Questo rimuoverà anche gli spazi bianchi ripetuti nel mezzo. Stavo cercando una soluzione che non lo faccia. –

3

A breve soluzione XSLT1:

<xsl:template name="trim"> 
      <xsl:param name="str"/> 

      <xsl:choose> 
       <xsl:when test="string-length($str) &gt; 0 and substring($str, 1, 1) = ' '"> 
        <xsl:call-template name="trim"><xsl:with-param name="str"><xsl:value-of select="substring($str, 2)"/></xsl:with-param></xsl:call-template></xsl:when> 
       <xsl:when test="string-length($str) &gt; 0 and substring($str, string-length($str)) = ' '"> 
        <xsl:call-template name="trim"><xsl:with-param name="str"><xsl:value-of select="substring($str, 1, string-length($str)-1)"/></xsl:with-param></xsl:call-template></xsl:when> 
       <xsl:otherwise><xsl:value-of select="$str"/></xsl:otherwise> 
      </xsl:choose> 
     </xsl:template> 
Problemi correlati