mysql / mysqldump と XSLT

mysql / mysqldump には --xml というオプションがありますが、みんな使ってますか?

dump もしくは sql を実行して、結果を直接ブラウザやエクセルに貼付けるようなとき、たとえばデータにタブや改行が入ってたりして、クエリの最後に \G つけてもつけなくてもなんかキモイなー、となっちゃいますよね。

そんなとき便利なのが xml 出力 + XSLT です。てきとうな mysqldump.xsl 書いて、出力された xml の先頭に1行を追加するだけ。

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="mysqldump.xsl"?> ←これを追加
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...

ただし XSLT でがんばりすぎるくらいなら、 xml をちゃんと扱える言語とか、そもそも xml で出力すること自体をやめた方が早かったりするので難しいところ。

せっかくなんでずいぶん前に作った mysqldump --no-create-info --xml 用のスタイルシートをさらしておきます。みんな使ってるなら、きっと xsl をもっと表立ってサポートしてくれるかも??

mysqldump.xsl

table_structureのところはすごいいい加減です。あくまで --no-create-info 用。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="no"
    encoding="utf-8" method="xml" version="1.0"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    indent="yes" />

<xsl:template match="mysqldump">
<html>
<body>
    <xsl:for-each select="database">
        <h1><xsl:value-of select="@name" /></h1>
        <xsl:apply-templates select="table_structure" />
        <xsl:apply-templates select="table_data" />
    </xsl:for-each>
</body>
</html>
</xsl:template>

<xsl:template match="table_structure">
<h2><xsl:value-of select="@name" /></h2>
<table border="1px">
<thead>
    <tr>
        <th>name</th>
        <th>value</th>
    </tr>
</thead>
<tbody>
    <xsl:for-each select="field">
    <tr>
        <td><xsl:value-of select="@Field" /></td>
        <td><xsl:value-of select="@Type" /></td>
    </tr>
    </xsl:for-each>
</tbody>
</table>
</xsl:template>

<xsl:template match="table_data">
<h2><xsl:value-of select="@name" /></h2>
<table border="1px">
<thead>
    <tr>
    <xsl:for-each select="row[1]/field[@name]">
        <th>
            <xsl:value-of select="@name" />
        </th>
    </xsl:for-each>
    </tr>
</thead>
<tbody>
    <xsl:for-each select="row">
    <tr>
    <xsl:for-each select="field">
        <td>
            <!-- <xsl:value-of select="." /> -->
            <xsl:call-template name="convert_nl">
                <xsl:with-param name="value" select="." />
            </xsl:call-template>
        </td>
    </xsl:for-each>
    </tr>
    </xsl:for-each>
</tbody>
</table>
</xsl:template>

<xsl:template name="convert_nl">
    <xsl:param name="value"/>
    <xsl:choose>
        <xsl:when test="contains($value, '&#x0a;')">
            <xsl:value-of select="substring-before($value, '&#x0a;')"/>
            <br />
            <xsl:call-template name="convert_nl">
                <xsl:with-param name="value" select="substring-after($value, '&#x0a;')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$value"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

これ書いたの自体が半年くらい前だけど、 xsl を勉強したのはもっと前で http://d.hatena.ne.jp/ichii386/20060619/1150740995 のときですね。もう3年以上前か。こういうのちょっとやらないとすぐ忘れますねぇ。

追記

一瞬でパッチがあがりましたw さすがすぎです > @nippondanji さま

http://bugs.mysql.com/bug.php?id=48855