web-dev-qa-db-ja.com

xsl:文字列を分割する方法は?

セミコロン(_;_)のアドレスを_<br />_で区切られた行に分割したい:

例えばaddress = _123 Elm Street_の場合、_123 Elm Street_を出力したい

しかし、address = _123 Elm Street;PO Box 222_の場合、出力したい

_123 Elm Street<br />PO Box 222
_

address = _123 Elm Street;PO Box 222;c/o James Jones_の場合、出力したい

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

これを行う方法はありますか? (おそらく簡単ですが、私はXSLTにそれほど精通していません)

プレーンXSLセレクターは

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

そして、このXSLTフラグメントをセミコロンで分割するように修正したいと思います。


更新:どうやら、答えは_<xsl:call-template>_と関数substring-before()およびsubstring-after()の使用を含むようです。

しかし、私はXSLTの初心者であり、これを行う方法について実際にいくつかのヘルプを使用できます。

32
Jason S

I.プレーンXSLT 1.0ソリューション:

この変換

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

このXML文書に適用される場合

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

必要な修正結果を生成します

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

II。 FXSL 1(XSLT 1.0の場合):

ここでは、[〜#〜] fxsl [〜#〜]テンプレートstr-map(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>

この変換がXMLドキュメントに適用されると(使用されない)、同じ、必要な正しい結果が生成されます

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

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

この変換がこのXML文書に適用される場合

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

必要な正しい結果が生成されます

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

XSLTプロセッサが [〜#〜] exslt [〜#〜] をサポートしている場合、 str:tokenize を使用できます。それ以外の場合、リンクにはsubstring-前。

2
Mormegil