2009年12月5日土曜日

XSLT で左外部結合

関係データベースで、こんな表の組み合わせ方を外部結合という。右表に結合するレコードが無いときでも、左表のデータは結合表に入る。
左表
100a
101b
102c
+
右表
1100X
2100Y
3101Z
結合表
100a1X
100a2Y
101b3Z
102c


関係データベースで、テーブルとクエリを使ってやっていることを、XML データと XSLT で模してみたい。上の図表と等価な、以下のような XML データから HTMLテーブルへの変換をゴールとしてみる。
<?xml version="1.0" encoding="UTF-8"?>
<left-right>
<left>
<l><l-id>100</l-id><name>a</name></l>
<l><l-id>101</l-id><name>b</name></l>
<l><l-id>102</l-id><name>c</name></l>
</left>
<right>
<r><r-id>1</r-id><l-id>100</l-id><name>X</name></r>
<r><r-id>2</r-id><l-id>100</l-id><name>Y</name></r>
<r><r-id>3</r-id><l-id>101</l-id><name>Z</name></r>
</right>
</left-right>
↓↓↓
<table>
<tr>
<td>100</td>
<td>a</td>
<td>1</td>
<td>X</td>
</tr>
・・・ 略
<tr>
<td>102</td>
<td>c</td>
<td />
<td />
</tr>
</table>

以下のような解にしてみた。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/left-right">
<table>
<xsl:apply-templates select="left" />
</table>
</xsl:template>

<xsl:template match="left">
<xsl:for-each select="l">
<xsl:apply-templates select="//right">
<xsl:with-param name="l-id" select="l-id" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>

<xsl:template match="right">
<xsl:param name="l-id" />
<xsl:choose>
<xsl:when test="r[l-id=$l-id]">
<xsl:for-each select="r[l-id=$l-id]">
<xsl:call-template name="create-row">
<xsl:with-param name="l-id" select="$l-id"/>
<xsl:with-param name="r-id" select="r-id"/>
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="create-row">
<xsl:with-param name="l-id" select="$l-id"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template name="create-row">
<xsl:param name="l-id"/>
<xsl:param name="r-id"/>
<tr>
<td><xsl:value-of select="$l-id" /></td>
<td><xsl:value-of select="//left/l[l-id=$l-id]/name" /></td>
<td><xsl:value-of select="$r-id" /></td>
<td><xsl:value-of select="//right/r[r-id=$r-id]/name" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>

0 件のコメント:

コメントを投稿