2011-01-30 15 views
26

Chcę podzielić adres średników (;) na wiersze oddzielone przez <br />:xsl: jak podzielić łańcuchy?

np. jeśli address = 123 Elm Street chcę wyjście 123 Elm Street,

ale jeśli address = 123 Elm Street;PO Box 222 chcę wyjście

123 Elm Street<br />PO Box 222 

a jeśli address = 123 Elm Street;PO Box 222;c/o James Jones chcę wyjście

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

Czy Czy istnieje sposób, aby to zrobić? (Zapewne łatwe, ale nie jestem zaznajomiony z XSLT)

Równina selektor XSL jest

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

i chciałbym zmodyfikować ten fragment XSLT do podzielony na średnikiem.


aktualizacja: Najwyraźniej odpowiedź wiąże się z wykorzystaniem <xsl:call-template> i funkcje substring-before() i substring-after().

Ale jestem początkujący dla XSLT i naprawdę mogłem skorzystać z pomocy, jak to zrobić.

+0

możliwym duplikatu [Does XSLT mieć funkcję Split()?] (http://stackoverflow.com/questions/136500/does-xslt-have-a-split-function) – porges

+0

może to prawie duplikat, ale nie mogę wymyślić, jak zastosować odpowiedzi na to pytanie, na mój problem. –

+0

Zobacz także http://stackoverflow.com/questions/10750184/looping-through-multiple-sequences-f-ttrtkenize – Vadzim

Odpowiedz

52

I. Zwykły XSLT 1.0 Rozwiązanie:

Ta przemiana:

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

po nałożeniu na tego dokumentu XML:

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

produkuje Wanted, skorygowany wynik:

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

II. FXSL 1 (dla XSLT 1.0):

Tu wystarczy użyć FXSL szablon str-map (i nie trzeba pisać rekurencyjną szablon po raz 999th):

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

kiedy ta przemiana jest stosowana na dowolnym dokumencie XML (nie używany), ten sam, chciał poprawnym wynikiem jest produkowany:

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

III. Korzystanie z 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> 

kiedy ta transformacja jest stosowane na tym dokumencie XML:

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

poszukiwany, poprawny wynik jest produkowany:

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

Czy mógłbyś wyjaśnić składnię 'not ($ pText =.)'? co robi '.'? –

+3

@ Jason-S: '.' w XSLT (i XPath) oznacza bieżący węzeł (węzeł kontekstu). 'not ($ pText =.)' jest 'true()' jeśli wartość ciągu parametru '$ pText' nie jest równa wartości ciągu bieżącego węzła - chcemy wyprowadzić'
'tylko w tym przypadku , w przeciwnym razie nasze wyjście rozpocznie się od '
' –

+0

Czy mogę przekazać istniejącą zmienną do nazwy param = "pText"? – Perdomoff

1

Jeśli twój procesor XSLT obsługuje EXSLT, możesz użyć str:tokenize, w przeciwnym razie link zawiera implementację wykorzystującą funkcje takie jak substring-before.

+0

jak się dowiem? Mój procesor XSLT to przeglądarka internetowa: Firefox 3.6 lub Safari 5.0 –

+2

@Jason S - w takim przypadku nie możesz na tym polegać i musisz samemu dostarczyć tę funkcję; implementacja jest dostępna pod adresem http://exslt.org/str/functions/tokenize/str.tokenize.template.xsl – Mormegil

+0

Oto przykład: http://stackoverflow.com/questions/10750184/looping-through- multiple-sequence-from-strtokenize – Vadzim