Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert KeePass XML (2.x) format to keeper.txt format.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- convert KeePass XML (2.x) format to 7-column keeper.txt format -->
<xsl:output method="text" encoding="utf-8" />
<xsl:template match="/">
<xsl:apply-templates select="/KeePassFile/Root/Group" />
</xsl:template>
<xsl:template match="Group">
<xsl:param name="parent" select="'/'" />
<xsl:variable name="current" select="concat($parent, Name)" />
<!-- list password entries -->
<xsl:apply-templates select="Entry">
<xsl:with-param name="group" select="$current" />
</xsl:apply-templates>
<!-- list entries of subgroups recursively -->
<xsl:apply-templates select="Group">
<xsl:with-param name="parent" select="concat($current, '/')" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Entry">
<xsl:param name="group" />
<!-- pack Notes and multi-line custom fields into notes field -->
<xsl:variable name="notes">
<xsl:if test="String[Key='Notes']/Value!=''">
<xsl:call-template name="escape-ml">
<xsl:with-param name="value" select="String[Key='Notes']/Value" />
</xsl:call-template>
<xsl:text>\n\n</xsl:text>
</xsl:if>
<xsl:for-each select="String[contains(Value, '&#xA;') and
not(Key='Title' or Key='UserName' or Key='Password' or Key='Notes' or Key='URL')]">
<xsl:value-of select="concat('# ', Key, '\n')" />
<xsl:call-template name="escape-ml">
<xsl:with-param name="value" select="Value" />
</xsl:call-template>
<xsl:text>\n\n</xsl:text>
</xsl:for-each>
</xsl:variable>
<!-- pack single-line custom fields as JSON objects -->
<xsl:variable name="json">
<xsl:text>[</xsl:text>
<xsl:for-each select="String[not(contains(Value, '&#xA;')) and
not(Key='Title' or Key='UserName' or Key='Password' or Key='Notes' or Key='URL')]">
<xsl:if test="position()!=1">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:text>{"type":"text","name":</xsl:text>
<xsl:call-template name="to-json-str">
<xsl:with-param name="value" select="Key" />
</xsl:call-template>
<xsl:text>,"value":</xsl:text>
<xsl:call-template name="to-json-str">
<xsl:with-param name="value" select="Value" />
</xsl:call-template>
<xsl:text>}</xsl:text>
</xsl:for-each>
<xsl:text>]</xsl:text>
</xsl:variable>
<!-- put tab-separated fields: Title, UserName, Password, Notes, Group, URL, JSON -->
<xsl:value-of select="translate(String[Key='Title']/Value, '&#x9;&#xA;', ' ')" />
<xsl:text>&#x9;</xsl:text>
<xsl:value-of select="translate(String[Key='UserName']/Value, '&#x9;&#xA;', ' ')" />
<xsl:text>&#x9;</xsl:text>
<xsl:value-of select="translate(String[Key='Password']/Value, '&#x9;&#xA;', ' ')" />
<xsl:text>&#x9;</xsl:text>
<xsl:value-of select="translate($notes, '&#x9;&#xA;', ' ')" />
<xsl:text>&#x9;</xsl:text>
<xsl:value-of select="translate($group, '&#x9;&#xA;', ' ')" />
<xsl:text>&#x9;</xsl:text>
<xsl:value-of select="translate(String[Key='URL']/Value, '&#x9;&#xA;', ' ')" />
<xsl:text>&#x9;</xsl:text>
<xsl:value-of select="translate($json, '&#x9;&#xA;', ' ')" />
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<!-- escape multi-line text -->
<xsl:template name="escape-ml">
<xsl:param name="value" />
<xsl:call-template name="replace">
<xsl:with-param name="subject" select="$value" />
<xsl:with-param name="pattern" select="'&#xA;'" />
<xsl:with-param name="replace" select="'\n'" />
</xsl:call-template>
</xsl:template>
<!-- convert text to JSON string -->
<xsl:template name="to-json-str">
<xsl:param name="value" />
<xsl:text>"</xsl:text>
<xsl:call-template name="replace">
<xsl:with-param name="subject">
<xsl:call-template name="replace">
<xsl:with-param name="subject">
<xsl:call-template name="replace">
<xsl:with-param name="subject" select="$value" />
<xsl:with-param name="pattern" select="'\'" />
<xsl:with-param name="replace" select="'\\'" />
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="pattern" select="'&#x9;'" />
<xsl:with-param name="replace" select="'\t'" />
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="pattern" select="'&quot;'" />
<xsl:with-param name="replace" select="'\&quot;'" />
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:template>
<!-- replace $pattern in $subject with $replace -->
<xsl:template name="replace">
<xsl:param name="subject" />
<xsl:param name="pattern" />
<xsl:param name="replace" />
<xsl:choose>
<xsl:when test="contains($subject, $pattern)">
<xsl:value-of select="concat(substring-before($subject, $pattern), $replace)" />
<xsl:call-template name="replace">
<xsl:with-param name="subject" select="substring-after($subject, $pattern)" />
<xsl:with-param name="pattern" select="$pattern" />
<xsl:with-param name="replace" select="$replace" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$subject" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
@LiosK

This comment has been minimized.

Show comment
Hide comment
Owner

LiosK commented May 4, 2010

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment