XMind ファイルをタブインデントでテキストファイル変換する(XSLT)

## はじめに

XMind は非常に便利で、アウトラインプロセッサーとして重宝しています。
しかし、テキストファイルで出力すると、階層構造が失われてしまうのが私にとっての不満な点でした。(Plus, Proは未確認。)
そこで、XMind の .xmind 形式からタブでインデントされたテキストファイルを抽出する方式にしています。

## XSLT プロセッサーの準備

ここでは msxsl を使用します。 (http://www.microsoft.com/en-us/download/details.aspx?id=21714 )

## 手順

1) .xmind ファイルから content.xml を抽出

.xmind 形式のファイルは zip で圧縮されているため、任意の場所で展開し、content.xml を抽出する。

2) XSLT による変換

> msxsl content.xml content_sjis.xsl -o content.txt

```xml:content_sjis.xsl
<?xml version="1.0" encoding="UTF-8"?>

<!-- XMind Contents.xml to TSV -->

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xmind="urn:xmind:xmap:xmlns:content:2.0"
    xmlns:ns1="urn:xmind:xmap:xmlns:content:2.0"
    version="2.0">

    <xsl:output method="text" encoding="SHIFT_JIS" />
    <!--xsl:output method="text" encoding="UTF-8" /-->

    <xsl:template match="xmind:title"></xsl:template>

	<!-- 1st -->
    <xsl:template match="xmind:xmap-content" xmlns:ns1="urn:xmind:xmap:xmlns:content:2.0">
        <xsl:for-each select="xmind:sheet">
            <xsl:value-of select="xmind:topic/xmind:title"/>
            <xsl:apply-templates/>
        </xsl:for-each>
    </xsl:template>

    <!-- 2nd -->
        <xsl:template match="//xmind:topics[count(ancestor-or-self::xmind:topics)=1]">
        <xsl:for-each select="xmind:topic">
            <xsl:text>
    </xsl:text>
            <xsl:value-of select="xmind:title"/>
            <xsl:apply-templates/>
        </xsl:for-each>
    </xsl:template>

    <!-- 3rd -->
    <xsl:template match="//xmind:topics[count(ancestor-or-self::xmind:topics)=2]">
        <xsl:for-each select="xmind:topic">
            <xsl:text>
        </xsl:text>
            <xsl:value-of select="xmind:title"/>
            <xsl:apply-templates/>
        </xsl:for-each>
    </xsl:template>

    <!-- 4th	-->
    <xsl:template match="//xmind:topics[count(ancestor-or-self::xmind:topics)=3]">
        <xsl:for-each select="xmind:topic">
            <xsl:text>
            </xsl:text>
            <xsl:value-of select="xmind:title"/>
            <xsl:apply-templates/>
        </xsl:for-each>
    </xsl:template>

    <!-- 5th -->
    <xsl:template match="//xmind:topics[count(ancestor-or-self::xmind:topics)=4]">
        <xsl:for-each select="xmind:topic">
            <xsl:text>
                </xsl:text>
            <xsl:value-of select="xmind:title"/>
            <xsl:apply-templates/>
        </xsl:for-each>
    </xsl:template>

    <!-- 6th -->
    <xsl:template match="//xmind:topics[count(ancestor-or-self::xmind:topics)=5]">
        <xsl:for-each select="xmind:topic">
            <xsl:text>
                    </xsl:text>
            <xsl:value-of select="xmind:title"/>
            <xsl:apply-templates/>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>
```

## 制約事項

Shift-JIS で表現できない文字(例:✔)を使用すると、エラーがでます。

> Error occurred while executing stylesheet 'content_sjis.xsl'.
> 
> Code:   0x80004005
> 文字列を 'Shift_JIS' エンコードで保存できません。

これらの文字を使用しないか、UTF-8 でエンコーディングするようにしてください。

えっ、何で Shift-JIS なのかって? Excel 2007 が文字化けするからに決まってんだろ。けっ。

## 謝辞

@sky_y さんの、記事[XMinDoc: XMindのマインドマップをMarkdownなどに変換できるスクリプトをgem化した](http://qiita.com/sky_y/items/782cb656ce8b35bc2c9f)から、XSLT ほぼそのまま参考にしています。
この場を借りてお礼を述べさせていただきます。