Skip to content

Instantly share code, notes, and snippets.

@akafael
Created April 18, 2020 01:37
Show Gist options
  • Save akafael/93a9acb15e5cc57ca3478e961e5431eb to your computer and use it in GitHub Desktop.
Save akafael/93a9acb15e5cc57ca3478e961e5431eb to your computer and use it in GitHub Desktop.

Revisions

  1. akafael created this gist Apr 18, 2020.
    227 changes: 227 additions & 0 deletions mm2orgmode.xsl
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,227 @@
    <?xml version="1.0" encoding="UTF-8" ?>

    <!--
    MINDMAPEXPORTFILTER org;orgmode Orgmode
    v. 0.1
    This code released under the GPL. : (http://www.gnu.org/copyleft/gpl.html)
    Document : mm2orgmode.xsl
    Created on : 17 April, 2020
    Authors : Rafael Lima
    Description: Transforms freeplane mm to orgmode orgmode.
    * Nodes become headings and subheadings, Notes become paragraphs.
    * Attributes of root node become document metadata.
    * Details are not handled.
    * HTML tables are converted to Pandoc pipe table format.
    * Tested with Emacs.
    May not work:
    * Orgmode internal links
    Please test and suggest improvements to author, or feel free to customize
    while crediting previous authors.
    ******************************************************************************
    Based on mm2markdown.xsl and mm2text.xsl, original notice appears below
    ******************************************************************************
    This code released under the GPL. : (http://www.gnu.org/copyleft/gpl.html)
    Document : mm2markdown.xsl
    Created on : 20 November, 2013
    Authors : Lee Hachadoorian [email protected] and Peter Yates [email protected]
    Description: Transforms freeplane mm to markdown md.
    Document : mm2text.xsl
    Created on : 01 February 2004, 17:17
    Author : joerg feuerhake [email protected]
    Description: transforms freeplane mm
    format to html, handles crossrefs and adds numbering. feel free to
    customize it while leaving the ancient authors mentioned. thank you
    ChangeLog: See: http://freeplane.sourceforge.net/
    -->

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" indent="no"/>
    <xsl:strip-space elements="map node" />
    <xsl:key name="refid" match="node" use="@ID" />

    <xsl:template match="/">
    <xsl:apply-templates />
    </xsl:template>

    <!-- Create nodes as headlines in orgmode -->
    <xsl:template match="/map">
    <xsl:apply-templates select="node"/>
    </xsl:template>

    <!-- Create nodes as headlines in orgmode -->
    <xsl:template match="node">
    <xsl:variable name="thisid" select="@ID" />
    <xsl:variable name="target" select="arrowlink/@DESTINATION" />
    <xsl:choose>
    <!-- Root node attributes create ATRIBUTE block -->
    <xsl:when test="count(ancestor::*) = 1">
    <!-- Only create yaml block if there are attributes -->
    <xsl:if test="count(attribute) > 0">
    <xsl:text>&#xA;---&#xA;</xsl:text>
    <xsl:apply-templates select="attribute" />
    <xsl:text>---</xsl:text>
    </xsl:if>
    <!-- Use root node text as document TITLE key -->
    <xsl:text>#+TITLE: </xsl:text>
    </xsl:when>
    <!-- Create the headers from non-root node text using star signs -->
    <xsl:otherwise>
    <xsl:text>&#xA;</xsl:text>
    <xsl:call-template name="starSign">
    <xsl:with-param name="howMany" select="count(ancestor::*) - 1"/>
    </xsl:call-template>
    <xsl:text> </xsl:text>
    </xsl:otherwise>
    </xsl:choose>
    <!-- Node text -->
    <xsl:if test="@TEXT">
    <xsl:value-of select="normalize-space(@TEXT)" />
    <xsl:text>&#xA;</xsl:text>
    </xsl:if>

    <!-- Convert notes as paragraph -->
    <xsl:apply-templates select="richcontent[@TYPE='NODE']"/>
    <xsl:apply-templates select="richcontent[@TYPE='DETAILS']"/>
    <xsl:apply-templates select="richcontent[@TYPE='NOTE']"/>
    <!-- Convert arrow links between nodes to reference and internal doc link -->
    <xsl:if test="arrowlink/@DESTINATION != ''">
    <xsl:text> ref: </xsl:text>
    <xsl:for-each select="key('refid', $target)">
    <xsl:text>[[</xsl:text>
    <xsl:value-of select="@TEXT" />
    <xsl:text>]]</xsl:text>
    </xsl:for-each>
    <xsl:text>&#xA;</xsl:text>
    </xsl:if>
    <xsl:apply-templates select="node"/>
    </xsl:template>

    <!-- Attributes template -->
    <xsl:template match="attribute">
    <!-- Define Meta using key sintax -->
    <xsl:text>#+</xsl:text>
    <!-- Translate to Upcase -->
    <xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'" />
    <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
    <xsl:value-of select="translate(@NAME, $lowercase,$uppercase)" />: '<xsl:value-of select="@VALUE" />'
    </xsl:template>

    <!-- Template to print header *signs for each node-->
    <xsl:template name="starSign">
    <xsl:param name="howMany">1</xsl:param>
    <xsl:if test="$howMany &gt; 0">
    <!-- Add 1 star signs (*) to result tree. -->
    <xsl:text>*</xsl:text>
    <!-- Print remaining ($howMany - 1) star signs. -->
    <xsl:call-template name="starSign">
    <xsl:with-param name="howMany" select="$howMany - 1"/>
    </xsl:call-template>
    </xsl:if>
    </xsl:template>

    <!-- Create paragraph -->
    <xsl:template match="richcontent">
    <xsl:text>&#xA;</xsl:text>
    <xsl:apply-templates />
    <xsl:text>&#xA;</xsl:text>
    </xsl:template>

    <!-- Normalizer space -->
    <xsl:template match="child::text()">
    <xsl:value-of select="translate(normalize-space(.),'&#160;',' ')" />
    </xsl:template>

    <!-- Insert newline for html breaks, paras, etc. -->
    <xsl:template match="p|br|div|li|pre">
    <xsl:if test="preceding-sibling::*">
    <xsl:text>&#xA;</xsl:text>
    </xsl:if>
    <xsl:apply-templates/>
    </xsl:template>

    <!-- Convert Italics to orgmode syntax -->
    <xsl:template match="i|em">
    <xsl:text> /</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>/ </xsl:text>
    </xsl:template>

    <!-- Convert Bold to orgmode syntax -->
    <xsl:template match="b|strong">
    <xsl:text> **</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>** </xsl:text>
    </xsl:template>

    <!-- Strikethrough formatting -->
    <xsl:template match="strike">
    <xsl:text> ++</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>++ </xsl:text>
    </xsl:template>

    <!-- Subscript formatting -->
    <xsl:template match="sub">
    <xsl:text> _{</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>} </xsl:text>
    </xsl:template>

    <!-- Superscript formatting -->
    <xsl:template match="sup">
    <xsl:text> ^{</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>} </xsl:text>
    </xsl:template>

    <!-- Convert <hr> to orgmode horizontal rule -->
    <xsl:template match="hr">
    <xsl:text>&#xA;-----&#xA;</xsl:text>
    </xsl:template>

    <!-- Convert html table to pandoc pipe table -->
    <xsl:template match="table">
    <xsl:text>&#xA;</xsl:text>
    <xsl:apply-templates />
    </xsl:template>

    <!-- Template to print table header separator row -->
    <xsl:template name="tableHeaderDashes">
    <xsl:param name="howManyCols">1</xsl:param>
    <xsl:if test="$howManyCols &gt; 0">
    <!-- Add left pipe and dashes to result tree. -->
    <xsl:text>| ------ </xsl:text>
    <!-- Print remaining ($howManyCols - 1) pipe dashes. -->
    <xsl:call-template name="tableHeaderDashes">
    <xsl:with-param name="howManyCols" select="$howManyCols - 1"/>
    </xsl:call-template>
    </xsl:if>
    <xsl:if test="$howManyCols = 0">
    <xsl:text>|</xsl:text>
    <xsl:text>&#xA;</xsl:text>
    </xsl:if>
    </xsl:template>

    <!-- Template to print table rows -->
    <xsl:template match="tr">
    <xsl:if test="count(preceding-sibling::tr)=1">
    <xsl:call-template name="tableHeaderDashes">
    <xsl:with-param name="howManyCols" select="count(td)" />
    </xsl:call-template>
    </xsl:if>
    <xsl:apply-templates />
    <xsl:text> |&#xA;</xsl:text>
    </xsl:template>

    <xsl:template match="td|th">
    <xsl:text>| </xsl:text>
    <xsl:apply-templates />
    </xsl:template>
    </xsl:stylesheet>