2011-02-09 11 views
1

XML文書があります:単純なXSLTテンプレート

私はそれを行うことができますどのように
<manydata> 
    <onedata>how</onedata> 
    <onedata>many</onedata> 
    <onedata>i</onedata> 
    <onedata>can</onedata> 
    <onedata>tell</onedata> 
    <onedata>you</onedata> 
    </manydata> 

<data>how;many;i;can;tell;you</data> 

は、XSLTのバージョン1を使用してXML を取得する必要がありますか?

更新日: 出力形式はです。です。

+0

良い質問、+1を。他の人が提供しているものよりも簡単な、これまでの最短のソリューションについては私の答えを見てください。 :) –

+0

これはXSLTに関するほとんどの回答のFAQです。いくつかの重複:http://stackoverflow.com/questions/136500/does-xslt-have-a-split-function http://stackoverflow.com/questions/3336424/does-xslt-have-split-function –

答えて

2

この再帰的な解決策は、おそらく最短の一つである:この変換が提供されるXML文書に適用され

<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="data"> 
    <manydata><xsl:apply-templates/></manydata> 
</xsl:template> 

<xsl:template match="text()" name="tokenize"> 
    <xsl:param name="pText" select="."/> 
    <xsl:if test="string-length($pText)"> 
     <onedata> 
     <xsl:value-of select= 
     "substring-before(concat($pText,';'),';')"/> 
     </onedata> 
     <xsl:call-template name="tokenize"> 
     <xsl:with-param name="pText" select= 
     "substring-after($pText,';')"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

<data>how;many;i;can;tell;you</data> 

指名手配、正しい結果が生成されます。

<manydata> 
    <onedata>how</onedata> 
    <onedata>many</onedata> 
    <onedata>i</onedata> 
    <onedata>can</onedata> 
    <onedata>tell</onedata> 
    <onedata>you</onedata> 
</manydata> 
+0

XSLT 1.0ですか? XSLT 1.0には "tokenize()関数"はありません! –

+0

指定されたテンプレートは 'tokenize'と呼ばれます。これは 'tokenize'関数と同じではありません。これはXSLT 1.0でうまくいくでしょう。 – Flynn1179

+0

@Grienders:はい、これは* XSLT 1.0です。また、テンプレートの名前は、(標準または非標準の)XPath関数の名前とは関係ありません。 –

1

はこれを試してみてください:

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

    <xsl:template match="data"> 
    <xsl:element name="manydata"> 
     <xsl:call-template name="splitsemicolons"> 
     <xsl:with-param name="text" select="text()" /> 
     </xsl:call-template> 
    </xsl:element> 
    </xsl:template> 

    <xsl:template name="splitsemicolons"> 
    <xsl:param name="text" /> 
    <xsl:choose> 
     <xsl:when test="contains($text,';')"> 
     <xsl:element name="onedata"> 
      <xsl:value-of select="substring-before($text,';')" /> 
     </xsl:element> 
     <xsl:call-template name="splitsemicolons"> 
      <xsl:with-param name="text" select="substring-after($text,';')" /> 
     </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:element name="onedata"> 
      <xsl:value-of select="$text" /> 
     </xsl:element> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

これは、それぞれの時間が第1 ;前に何を出力し、第1 ;後にすべてを自分自身を呼び出して、再帰的に呼び出されるという名前のテンプレートを使用しています。 ;がない場合は、そのままの状態で出力されます。

0

XSLT extension libraryを使用してtokenize関数を取得できます。あなたが使用してあなたのXSLTに拡張ライブラリをインポートする必要がありますのでご注意ください

<xsl:template match="/"> 
<manydata> 
<xsl:for-each select="str:tokenize(data, ';')"> 
     <xsl:value-of select="." /> 
    </xsl:for-each> 
</manydata> 
</xsl:template> 
</xsl:stylesheet> 

<xsl:import href="path/str.xsl" /> 

あなたはライブラリ関数を使用する前に、ここで最終的なコードは次のようになります方法です。

+0

私はXSLT拡張ライブラリを使用することはできません。 XSLTバージョン1のみを使用できます。 –

+0

私が間違っていると私を修正します..拡張ライブラリはバージョン1.0と互換性があります –

2
<xsl:template match="data"> 
    <manydata> 
     <!-- 
      empty <manydata/> will be generated, 
      if <data/> without child text() 
     --> 
     <xsl:apply-templates select="text()"/> 
    </manydata> 
</xsl:template> 

<xsl:template match="data/text()"> 
    <!-- start point for recursion --> 
    <xsl:call-template name="tokenize-string"> 
     <xsl:with-param name="separator" select="';'"/> 
     <xsl:with-param name="string" select="text()"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="tokenize-string"> 
    <xsl:param name="separator"/> 
    <xsl:param name="string"/> 
    <xsl:variable name="string-before-separator" 
     select="substring-before($string, $separator)"/> 
    <onedata> 
     <xsl:choose> 
      <!-- if $separator presents in $string take first piece --> 
      <xsl:when test="$string-before-separator"> 
       <xsl:value-of select="$string-before-separator"/> 
      </xsl:when> 
      <!-- take whole $string, if no $separator in the $string --> 
      <xsl:otherwise> 
       <xsl:value-of select="$string"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </onedata> 
    <!-- recursive call, if separator was found --> 
    <xsl:if test="$string-before-separator"> 
     <xsl:call-template name="tokenize-string"> 
      <xsl:with-param name="separator" select="$separator"/> 
      <xsl:with-param name="string" 
       select="substring-after($string, $separator)"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
+0

+1 for XSLTスタイル。 – Flack

関連する問題