1

非常に簡単な XSLT 変換に問題があります。これが入力 XML ドキュメントであると仮定しましょう。

<root>
  <myString>ABBCD</myString>
</root>

出力 XML は次のようになります。

<root>
    <myCharacters>
        <character>
            <id>1</id>
            <value>A</value>
        </character>
        <character>
            <id>2</id>
            <value>B</value>
        </character>
        <character>
            <id>3</id>
            <value>B</value>
        </character>
        <character>
            <id>4</id>
            <value>C</value>
        </character>
        <character>
            <id>5</id>
            <value>D</value>
        </character>
    </myCharacters>
</root>

そのような文字列を分割してインデックスをインクリメントする簡単な方法はありますか?

4

2 に答える 2

3

XSLT 2.0 ではかなり簡単です...

XML 入力

<root>
    <myString>ABBCD</myString>
</root>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="myString">
        <myCharacters>
            <xsl:analyze-string select="." regex=".">
            <xsl:matching-substring>
                <character>
                    <id><xsl:value-of select="position()"/></id>
                    <value><xsl:value-of select="."/></value>
                </character>
            </xsl:matching-substring>
        </xsl:analyze-string>
        </myCharacters>
    </xsl:template>

</xsl:stylesheet>

XML 出力

<root>
   <myCharacters>
      <character>
         <id>1</id>
         <value>A</value>
      </character>
      <character>
         <id>2</id>
         <value>B</value>
      </character>
      <character>
         <id>3</id>
         <value>B</value>
      </character>
      <character>
         <id>4</id>
         <value>C</value>
      </character>
      <character>
         <id>5</id>
         <value>D</value>
      </character>
   </myCharacters>
</root>

1.0でも悪くない。再帰テンプレートを使用できます。以下は同じ出力を生成します。

XSLT1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="myString">
        <myCharacters>
            <xsl:call-template name="analyzeString">
                <xsl:with-param name="string" select="."/>
            </xsl:call-template>
        </myCharacters>
    </xsl:template>

    <xsl:template name="analyzeString">
        <xsl:param name="pos" select="1"/>
        <xsl:param name="string"/>
        <character>
            <id><xsl:value-of select="$pos"/></id>
            <value><xsl:value-of select="substring($string,1,1)"/></value>
        </character>
        <xsl:if test="string-length($string)>=2">
            <xsl:call-template name="analyzeString">
                <xsl:with-param name="pos" select="$pos+1"/>
                <xsl:with-param name="string" select="substring($string,2)"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>
于 2013-03-17T18:35:19.263 に答える
1

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:variable name="vStyle" select="document('')"/>

 <xsl:template match="myString">
  <xsl:variable name="vStr" select="."/>
  <root>
    <myCharacters>
      <xsl:for-each select=
      "($vStyle//node()|$vStyle//@*|$vStyle//namespace::*)
                      [not(position() > string-length($vStr))]">

        <character>
            <id><xsl:value-of select="position()"/></id>
            <value><xsl:value-of select="substring($vStr,position(),1)"/></value>
        </character>
      </xsl:for-each>
    </myCharacters>
  </root>
 </xsl:template>
</xsl:stylesheet>

この変換が提供された XML ドキュメントに適用されると、次のようになります。

<root>
  <myString>ABBCD</myString>
</root>

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

  <root>
   <myCharacters>
      <character>
         <id>1</id>
         <value>A</value>
      </character>
      <character>
         <id>2</id>
         <value>B</value>
      </character>
      <character>
         <id>3</id>
         <value>B</value>
      </character>
      <character>
         <id>4</id>
         <value>C</value>
      </character>
      <character>
         <id>5</id>
         <value>D</value>
      </character>
   </myCharacters>
</root>

または、FXSL を使用すると、次のstr-mapようにテンプレートを使用できます。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:testmap="testmap" xmlns:f="http://fxsl.sf.net/"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="xsl f ext testmap">
   <xsl:import href="str-dvc-map.xsl"/>
   <testmap:testmap/>
   <xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/>

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

   <xsl:template match="myString">
    <xsl:variable name="vrtfChars">
     <xsl:call-template name="str-map">
       <xsl:with-param name="pFun" select="$vTestMap"/>
       <xsl:with-param name="pStr" select="."/>
     </xsl:call-template>
    </xsl:variable>

    <myCharacters>
      <xsl:apply-templates select="ext:node-set($vrtfChars)/*"/>
    </myCharacters>
   </xsl:template>

    <xsl:template name="enumChars" match="*[namespace-uri() = 'testmap']"
    mode="f:FXSL">
      <xsl:param name="arg1"/>
        <character>
            <value><xsl:value-of select="$arg1"/></value>
        </character>
    </xsl:template>

    <xsl:template match="character">
     <character>
       <id><xsl:value-of select="position()"/></id>
       <xsl:copy-of select="*"/>
     </character>
    </xsl:template>
</xsl:stylesheet>

同じ正しい結果を生成するには:

  <myCharacters>
   <character>
      <id>1</id>
      <value>A</value>
   </character>
   <character>
      <id>2</id>
      <value>B</value>
   </character>
   <character>
      <id>3</id>
      <value>B</value>
   </character>
   <character>
      <id>4</id>
      <value>C</value>
   </character>
   <character>
      <id>5</id>
      <value>D</value>
   </character>
</myCharacters>

Ⅱ.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="myString">
  <root>
    <myCharacters>
      <xsl:for-each select="string-to-codepoints(.)">
        <character>
            <id><xsl:value-of select="position()"/></id>
            <value><xsl:value-of select="codepoints-to-string(.)"/></value>
        </character>
      </xsl:for-each>
    </myCharacters>
  </root>
 </xsl:template>
</xsl:stylesheet>

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

  <root>
   <myCharacters>
      <character>
         <id>1</id>
         <value>A</value>
      </character>
      <character>
         <id>2</id>
         <value>B</value>
      </character>
      <character>
         <id>3</id>
         <value>B</value>
      </character>
      <character>
         <id>4</id>
         <value>C</value>
      </character>
      <character>
         <id>5</id>
         <value>D</value>
      </character>
   </myCharacters>
</root>
于 2013-03-17T18:50:35.467 に答える