ぽざうねっと

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  390  : 記事  0  : コメント  929  : トラックバック  67

ニュース

さて、今年の秋は何を漬けようか

書庫

日記カテゴリ

Accessory

Community

Private

http://bbs.wankuma.com/index.cgi?mode=al2&namber=575

ネタ元は上記のわんくま BBS です。
DataTable の行と列を入れ替えるのをわざわざ XSLT を利用してやってやろうという試み。
DataTable::WriteXml で出力した XML に XSLT をかませて変換し、変換後の XML を食わせて DataTable を作ってやる。
ちなみに、DataTable に名前が設定してなければ WriteXml ができないのでご注意。
なので、DataTable ではなく DataSet (Tables[0] に 対象の DataTable を持つ)を対象とする。
DataSet::WriteXml と DataTable::WriteXml で出力される XML に大きな違いはない。
(Tables.Count == 1 であれば)ルート要素の要素名が DataSet の名前になるか、DocumentElement 固定になるかの違いだけである。
DataTable より DataSet を使ったほうがいい理由は、XmlDataDocument が利用しやすいからである。
XmlDataDocument は作成時に DataSet を引数に取れる。
また XmlDataDocument は XmlDocument を継承しており、IXPathNavigatable を実装しているので XSLT 変換が容易にできる。

前置きはここまでにして、使用する XSLT は以下のものである。
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates mode="root"/>
    </xsl:template>
    
    <xsl:template match="*" mode="root">
        <NewDataSet>
            <xsl:apply-templates mode="controlRowRender"/>
        </NewDataSet>
    </xsl:template>
    
    <xsl:template match="*" mode="controlRowRender">
        <xsl:if test="position() = 1">
            <xsl:apply-templates mode="renderRow"/>
        </xsl:if>
    </xsl:template>
    
    <xsl:template match="*" mode="renderRow">
        <xsl:variable name="name" select="name(.)"/>
        <NewDataTable>
            <xsl:for-each select="../..//*[name(.) = $name]">
                <xsl:element name="{concat('col', position())}">
                    <xsl:value-of select="."/>
                </xsl:element>
            </xsl:for-each>
        </NewDataTable>
    </xsl:template>
</xsl:stylesheet>
列名もテーブル名も全くもってわからないので、このように汎用的にする必要がある。
逆に言えば、どんな DataTable もこの XSLT 一つで行と列を入れ替えることができる。
ポイントは、match を * にしておいて、mode 指定によって切り替えるということ。
要素名はわからないけれども、構成・階層が固定になるから使えるテクニックだ。
で、この XSLT で変換した結果の XML を DataSet に食わせて、Tables[0] を取得すれば、行と列が入れ替わった DataTable が取得できる。

はっきり言ってこんなものを使ってまで、行と列を入れ替える必要がない。
簡単な二重ループで事足りる。
しかしこれは、少し変えれば限定状況ながらも有効に利用できる。
もともとの用途では、GridView にバインドすることが想定されていた。
ここで、バインド後に GridView 固有の機能(イベントやら何やら)を使用しないという状況を考える。
そんな場合、Xml コントロールを使用し、先述した XmlDataDocument を使用し、下記のような XSLT を使用する。
要素名をテーブルに対応させただけのものである。
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates mode="root"/>
    </xsl:template>
    
    <xsl:template match="*" mode="root">
        <table border="0" cellpadding="0" cellspacing="1">
            <xsl:apply-templates mode="controlRowRender"/>
        </table>
    </xsl:template>
    
    <xsl:template match="*" mode="controlRowRender">
        <xsl:if test="position() = 1">
            <xsl:apply-templates mode="renderRow"/>
        </xsl:if>
    </xsl:template>
    
    <xsl:template match="*" mode="renderRow">
        <xsl:variable name="name" select="name(.)"/>
        <tr>
            <xsl:for-each select="../..//*[name(.) = $name]">
                <td>
                    <xsl:value-of select="."/>
                </td>
            </xsl:for-each>
        </tr>
    </xsl:template>
</xsl:stylesheet>
すると、DataTable には何の操作も行わずに、行と列を入れ替えたテーブルを表示することができる。
「表示だけ」という限定された状況なれど、利用する価値はあるのではなかろうか。
投稿日時 : 2007年2月1日 0:10

コメント

# re: XSLT を用いて DataTable の行と列を入れ替える 2007/02/01 16:56 刈歩 菜良
すご~い!!
すんばらしい!!
やっぱ、XMLがらみも勉強せないかんですなぁ。

# いまだに、VSさんにおんぶにだっこなわたくし...

ありがとうございました。

# re: XSLT を用いて DataTable の行と列を入れ替える 2007/02/02 1:26 THREE-ONE
XML はもはやそこら中にころがってますからねー。
XSLT が使えると何かと便利です。

Post Feedback

タイトル
名前
Url:
コメント: