2011-01-30 17 views
26

Voglio dividere un indirizzo sul punto e virgola (;) in righe separate da <br />:xsl: come dividere le stringhe?

ad es. se address = 123 Elm Street, voglio uscita 123 Elm Street,

ma se address = 123 Elm Street;PO Box 222, voglio uscita

123 Elm Street<br />PO Box 222 

e se address = 123 Elm Street;PO Box 222;c/o James Jones, voglio uscita

123 Elm Street<br />PO Box 222<br />c/o James Jones 

Is c'è un modo per farlo? (Probabilmente facile ma io non sono che la familiarità con XSLT)

Il selettore XSL pianura è

<xsl:value-of select="address"/> 

e vorrei modificare questo frammento XSLT per dividere il punto e virgola.


aggiornamento: A quanto pare la risposta implica l'uso di <xsl:call-template> e delle funzioni substring-before() e substring-after().

Ma io sono un principiante di XSLT e potrei davvero usare un po 'di aiuto su come farlo.

+0

possibile duplicato del [fa XSLT avere una funzione Split()?] (http://stackoverflow.com/questions/136500/does-xslt-have-a-split-function – porges

+0

forse è quasi un duplicato, ma non riesco a capire come applicare le risposte a questa domanda, al mio problema. –

+0

Vedere anche http://stackoverflow.com/questions/10750184/looping-through-multiple-sequences-from-strtokenize – Vadzim

risposta

52

I. Plain XSLT 1.0 soluzione:

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:template match="text()" name="split"> 
    <xsl:param name="pText" select="."/> 
    <xsl:if test="string-length($pText)"> 
    <xsl:if test="not($pText=.)"> 
    <br /> 
    </xsl:if> 
    <xsl:value-of select= 
    "substring-before(concat($pText,';'),';')"/> 
    <xsl:call-template name="split"> 
    <xsl:with-param name="pText" select= 
    "substring-after($pText, ';')"/> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

quando applicato su questo documento XML:

<t>123 Elm Street;PO Box 222;c/o James Jones</t> 

produce il desiderato, risultato corretto:

123 Elm Street<br />PO Box 222<br />c/o James Jones 

II. FXSL 1 (per XSLT 1.0):

Qui abbiamo appena utilizzare il modello str-mapFXSL (e non hanno di scrivere modello ricorsivo per il momento 999):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:f="http://fxsl.sf.net/" 
xmlns:testmap="testmap" 
exclude-result-prefixes="xsl f testmap" 
> 
    <xsl:import href="str-dvc-map.xsl"/> 

    <testmap:testmap/> 

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

    <xsl:template match="/"> 
    <xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/> 
    <xsl:call-template name="str-map"> 
     <xsl:with-param name="pFun" select="$vTestMap"/> 
     <xsl:with-param name="pStr" select= 
     "'123 Elm Street;PO Box 222;c/o James Jones'"/> 
    </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="replace" mode="f:FXSL" 
     match="*[namespace-uri() = 'testmap']"> 
     <xsl:param name="arg1"/> 

     <xsl:choose> 
     <xsl:when test="not($arg1=';')"> 
     <xsl:value-of select="$arg1"/> 
     </xsl:when> 
     <xsl:otherwise><br /></xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

quando questa trasformazione è applicato su qualsiasi documento XML (non utilizzato), lo stesso, ha voluto risultato corretto è prodotto:

123 Elm Street<br/>PO Box 222<br/>c/o James Jones 

III. Utilizzando XSLT 2.0

<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="text()"> 
    <xsl:for-each select="tokenize(.,';')"> 
    <xsl:sequence select="."/> 
    <xsl:if test="not(position() eq last())"><br /></xsl:if> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

quando questa trasformazione è applicata in questo documento XML:

<t>123 Elm Street;PO Box 222;c/o James Jones</t> 

The Wanted, risultato corretto è prodotta:

123 Elm Street<br />PO Box 222<br />c/o James Jones 
+0

potresti spiegare la sintassi 'not ($ pText =.)'? cosa sta facendo '''? –

+3

@ Jason-S: '.' in XSLT (e in XPath) indica il nodo corrente (nodo contesto). 'not ($ pText =.)' è 'true()' se il valore stringa del parametro '$ pText' non è uguale al valore stringa del nodo corrente - vogliamo output'
'solo in questo caso altrimenti il ​​nostro output inizierà con '
' –

+0

Posso passare una variabile già esistente al parametro nome = "pText"? – Perdomoff

1

Se il processore XSLT supporta EXSLT, è possibile utilizzare str:tokenize, altrimenti, il collegamento contiene un'implementazione utilizzando funzioni come sottostringa-prima.

+0

come trovarlo? Il mio processore XSLT è un browser web, Firefox 3.6 o Safari 5.0 –

+2

@Jason S: in questo caso, non è possibile dipendere da esso e è necessario fornire autonomamente la funzione; l'implementazione è disponibile sul link http://exslt.org/str/functions/tokenize/str.tokenize.template.xsl – Mormegil

+0

Ecco un esempio: http://stackoverflow.com/questions/10750184/looping-through- multiple-sequences-from-strtokenize – Vadzim

Problemi correlati