特定の条件下でカウンターをインクリメントする際に問題があります。
入力:
<Users>
<User>
<id>1</id>
<username>jack</username>
</User>
<User>
<id>2</id>
<username>bob</username>
</User>
<User>
<id>3</id>
<username>bob</username>
</User>
<User>
<id>4</id>
<username>jack</username>
</User>
</Users>
必要な出力:
<Users>
<User>
<id>1</id>
<username>jack01</username>
</User>
<User>
<id>2</id>
<username>bob01</username>
</User>
<User>
<id>3</id>
<username>bob02</username>
</User>
<User>
<id>4</id>
<username>jack02</username>
</User>
</Users>
これを実現するには、次のアルゴリズムを使用できます。
- 入力をユーザー名でソート
- ユーザーごとに
- 以前のユーザー名が現在のユーザー名と等しい場合
- インクリメントカウンターと
- ユーザー名を「$username$counter」に設定します
- それ以外は
- カウンターを1に設定
- 以前のユーザー名が現在のユーザー名と等しい場合
- (再度 ID でソート - 実際には必要ありません)
だから私はこれをXSLTに変換しようとしました:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="Users">
<Users>
<xsl:apply-templates select="create_user">
<xsl:sort select="User/username"/>
</xsl:apply-templates>
</Users>
</xsl:template>
<xsl:template match="create_user">
<id><xsl:value-of select="id"/></id>
<xsl:choose>
<xsl:when test="username=(preceding-sibling::User[1]//username)">
<xsl:variable name="count">
<xsl:number format="01"/>
</xsl:variable>
<username><xsl:value-of select="concat(username, $count)"/></username>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="count">
<xsl:number value="1" format="01"/>
</xsl:variable>
<username><xsl:value-of select="concat(username, $count)"/></username>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
ただし、これを実行すると、次のエラーが発生します。
- ユーザー名がソートされない
- カウンターが増えない
- 代わりに、条件が一致する場合、counter が現在のノード位置になります。
- この例では、id = 3 のノードのユーザー名は bob03 になります。
- タグがありません
何かご意見は?