Skip to content

Instantly share code, notes, and snippets.

@kir
Last active September 26, 2015 09:37
Show Gist options
  • Save kir/1076624 to your computer and use it in GitHub Desktop.
Save kir/1076624 to your computer and use it in GitHub Desktop.
XSL-based converter from OPML to CSV (created for Checkvist outliner), see http://checkvist.tumblr.com/post/7578054148
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/> <!-- We're generating text, not xml -->
<xsl:strip-space elements="*"/> <!-- Remove all spaces not inserted specifically by us -->
<!-- Separator for CSV file: if you use tags AND set this to ',' the tags will end up in separate columns -->
<xsl:variable name="separator" select="';'"/>
<xsl:template match="head"/>
<xsl:template match="/opml/body">
<!-- Header of the CSV file: -->
<xsl:text>Parent Path</xsl:text>
<xsl:value-of select="$separator"/>
<xsl:text>Text</xsl:text>
<xsl:value-of select="$separator"/>
<xsl:text>Status</xsl:text>
<xsl:value-of select="$separator"/>
<xsl:text>Last Modified</xsl:text>
<xsl:value-of select="$separator"/>
<xsl:text>Due</xsl:text>
<xsl:value-of select="$separator"/>
<xsl:text>Tags</xsl:text>
<xsl:value-of select="$separator"/>
<xsl:text>Priority/Color</xsl:text>
<xsl:value-of select="$separator"/>
<xsl:text>ID</xsl:text>
<xsl:text>&#13;&#10;</xsl:text>
<!-- Generate CSV lines: -->
<xsl:apply-templates select="//outline" />
</xsl:template>
<!-- Main template for CSV line: -->
<xsl:template match="outline">
<xsl:if test="(@status='closed')or(@status='invalid')or(@status='open')"> <!-- modify this line as needed -->
<!-- Output parent breadcrumbs: -->
<xsl:call-template name="parents">
<xsl:with-param name="parentList" select="ancestor::outline"/>
</xsl:call-template>
<xsl:value-of select="$separator"/>
<!-- We should quote text of item if it contains a separator: -->
<xsl:call-template name="quote_text">
<xsl:with-param name="text" select="@text"/>
</xsl:call-template>
<xsl:value-of select="$separator"/>
<xsl:value-of select="@status"/>
<xsl:value-of select="$separator"/>
<!-- Transform @dateModified so it is recognized as a date in Numbers/Excel: -->
<xsl:call-template name="format_date">
<xsl:with-param name="dm" select="@dateModified"/>
</xsl:call-template>
<xsl:value-of select="$separator"/>
<xsl:value-of select="@due"/>
<xsl:value-of select="$separator"/>
<xsl:call-template name="quote_text">
<xsl:with-param name="text" select="@tags"/>
</xsl:call-template>
<xsl:value-of select="$separator"/>
<!-- parse color and Bgcolor into priority literal strings USER NEEDS TO CUSTOMIZE -->
<xsl:choose>
<xsl:when test="contains(@color,'red')">
<xsl:text>1</xsl:text>
</xsl:when>
<xsl:when test="contains(@color,'blue')">
<xsl:text>2</xsl:text>
</xsl:when>
<xsl:when test="contains(@color,'green')">
<xsl:text>3</xsl:text>
</xsl:when>
<xsl:when test="contains(@bgColor,'red')">
<xsl:text>4</xsl:text>
</xsl:when>
<xsl:when test="contains(@bgColor,'blue')">
<xsl:text>5</xsl:text>
</xsl:when>
<xsl:when test="contains(@bgColor,'green')">
<xsl:text>6</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:value-of select="$separator"/>
<xsl:value-of select="@id"/>
<xsl:text>&#13;&#10;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template name="parents">
<xsl:param name="parentList"/>
<xsl:variable name="parentText">
<xsl:for-each select="$parentList">
<xsl:value-of select="@text"/>
<xsl:if test="position() != last()">
<xsl:text> > </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:call-template name="quote_text">
<xsl:with-param name="text" select="$parentText"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="quote_text">
<xsl:param name="text"/>
<!-- Replace newline in text to spaces: -->
<xsl:variable name="text" select="replace($text, '&#10;', ' ')"/>
<xsl:variable name="text" select="replace($text, '&#13;', ' ')"/>
<!-- Check for separator and wrap in quotes if needed -->
<xsl:choose>
<xsl:when test="contains($text, $separator)">
<xsl:text>"</xsl:text>
<xsl:value-of select="replace($text, '&quot;', '&quot;&quot;')"/>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="format_date">
<xsl:param name="dm"/>
<xsl:variable name="dm" select="replace($dm, '(Sun|Mon|Tue|Wed|Thu|Fri|Sat), ', '')"/> <!-- delimiter originally a period and changed to / for compatibility -->
<xsl:variable name="dm" select="replace($dm, ' Jan ', '/01/')"/>
<xsl:variable name="dm" select="replace($dm, ' Feb ', '/02/')"/>
<xsl:variable name="dm" select="replace($dm, ' Mar ', '/03/')"/>
<xsl:variable name="dm" select="replace($dm, ' Apr ', '/04/')"/>
<xsl:variable name="dm" select="replace($dm, ' May ', '/05/')"/>
<xsl:variable name="dm" select="replace($dm, ' Jun ', '/06/')"/>
<xsl:variable name="dm" select="replace($dm, ' Jul ', '/07/')"/>
<xsl:variable name="dm" select="replace($dm, ' Aug ', '/08/')"/>
<xsl:variable name="dm" select="replace($dm, ' Sep ', '/09/')"/>
<xsl:variable name="dm" select="replace($dm, ' Oct ', '/10/')"/>
<xsl:variable name="dm" select="replace($dm, ' Nov ', '/11/')"/>
<xsl:variable name="dm" select="replace($dm, ' Dec ', '/12/')"/>
<!-- rearrange date to be mm/dd/yyyy hh:mm (truncate seconds and rest of field) -->
<xsl:variable name="dm" select="concat(substring($dm,4,3),substring($dm,1,3),substring($dm,7,10))"/>
<xsl:value-of select="$dm"/>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment