Created
August 14, 2018 21:47
-
-
Save rhowe/a62c03ba2756dadbf6e442ee343600ab to your computer and use it in GitHub Desktop.
Convert a gnucash save file into a postgres database
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" ?> | |
<xsl:stylesheet | |
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | |
xmlns:cd="http://www.gnucash.org/XML/cd" | |
xmlns:book="http://www.gnucash.org/XML/book" | |
xmlns:gnc="http://www.gnucash.org/XML/gnc" | |
xmlns:cmdty="http://www.gnucash.org/XML/cmdty" | |
xmlns:trn="http://www.gnucash.org/XML/trn" | |
xmlns:split="http://www.gnucash.org/XML/split" | |
xmlns:act="http://www.gnucash.org/XML/act" | |
xmlns:price="http://www.gnucash.org/XML/price" | |
xmlns:ts="http://www.gnucash.org/XML/ts" | |
xmlns:slot="http://www.gnucash.org/XML/slot" | |
xmlns:cust="http://www.gnucash.org/XML/cust" | |
xmlns:entry="http://www.gnucash.org/XML/entry" | |
xmlns:lot="http://www.gnucash.org/XML/lot" | |
xmlns:invoice="http://www.gnucash.org/XML/invoice" | |
xmlns:owner="http://www.gnucash.org/XML/owner" | |
xmlns:job="http://www.gnucash.org/XML/job" | |
xmlns:billterm="http://www.gnucash.org/XML/billterm" | |
xmlns:bt-days="http://www.gnucash.org/XML/bt-days" | |
xmlns:sx="http://www.gnucash.org/XML/sx" | |
xmlns:fs="http://www.gnucash.org/XML/fs" | |
xmlns:addr="http://www.gnucash.org/XML/custaddr" | |
xmlns:str="http://exslt.org/strings" | |
version="1.0"> | |
<xsl:output method="text"/> | |
<xsl:template match="/gnc-v2"> | |
\set VERBOSITY terse | |
create table account_id_to_guid ( | |
account int4 references accounts(id), | |
guid varchar(32) unique not null | |
); | |
<xsl:apply-templates select="gnc:book"/> | |
drop table account_id_to_guid; | |
</xsl:template> | |
<xsl:template match="gnc:book"> | |
<xsl:apply-templates select="gnc:account"/> | |
<xsl:apply-templates select="gnc:transaction"/> | |
</xsl:template> | |
<xsl:template match="gnc:account[act:type='ROOT']"> | |
-- Root account | |
-- name=<xsl:value-of select="act:name" /> | |
-- guid=<xsl:value-of select="act:id" /> | |
insert into account_id_to_guid (account, guid) values | |
(null, '<xsl:value-of select="act:id"/>'); | |
</xsl:template> | |
<xsl:template match="gnc:account[act:type != 'ROOT']"> | |
-- name=<xsl:value-of select="act:name" /> | |
-- currency=<xsl:value-of select="act:commodity/cmdty:id" /> | |
-- guid=<xsl:value-of select="act:id" /> | |
-- parentguid=<xsl:value-of select="act:parent" /> | |
-- <xsl:choose> | |
<xsl:when test='act:slots/slot[slot:key = "placeholder"]/slot:value = "true"'>transactions not allowed</xsl:when> | |
<xsl:otherwise>transactions allowed</xsl:otherwise> | |
</xsl:choose> | |
insert into accounts (name, type, currency, parent, transactions_allowed) | |
values (<xsl:apply-templates select="act:name"/>, | |
(select id from accounttypes where name = <xsl:apply-templates select="act:type"/>), | |
(select id from currencies where symbol = <xsl:apply-templates select="act:commodity"/>), | |
(select account from account_id_to_guid where guid='<xsl:value-of select="act:parent"/>'), | |
<xsl:choose> | |
<xsl:when test='act:slots/slot[slot:key = "placeholder"]/slot:value = "true"'>FALSE</xsl:when> | |
<xsl:otherwise>TRUE</xsl:otherwise> | |
</xsl:choose>); | |
insert into account_id_to_guid (account, guid) values | |
((SELECT currval('accounts_id_seq')), '<xsl:value-of select="act:id"/>'); | |
</xsl:template> | |
<xsl:template match="act:type"> | |
<xsl:choose> | |
<xsl:when test=".='INCOME'">'Income'</xsl:when> | |
<xsl:when test=".='ASSET'">'Asset'</xsl:when> | |
<xsl:when test=".='BANK'">'Asset'</xsl:when> | |
<xsl:when test=".='CASH'">'Asset'</xsl:when> | |
<xsl:when test=".='STOCK'">'Asset'</xsl:when> | |
<xsl:when test=".='RECEIVABLE'">'Asset'</xsl:when> | |
<xsl:when test=".='EXPENSE'">'Expense'</xsl:when> | |
<xsl:when test=".='CREDIT'">'Liability'</xsl:when> | |
<xsl:when test=".='LIABILITY'">'Liability'</xsl:when> | |
<xsl:when test=".='PAYABLE'">'Liability'</xsl:when> | |
<xsl:when test=".='EQUITY'">'Equity'</xsl:when> | |
</xsl:choose> | |
</xsl:template> | |
<xsl:template match="act:commodity">'<xsl:value-of select="cmdty:id" />'</xsl:template> | |
<xsl:template match="cmdty:id">'<xsl:value-of select="." />'</xsl:template> | |
<xsl:template match="act:name">'<xsl:value-of select="str:replace(., "'", "''")" />'</xsl:template> | |
<xsl:template match="act:parent"> | |
<xsl:variable name="parentguid" select="."/><!-- [act:id/text()=$parentguid]/act:name/text() --> | |
<!--(select id from accounts where name='<xsl:value-of select='//gnc:account[1]/act:name' />' | |
and type=(select id from accounttypes where name=<xsl:apply-templates select="//gnc:account[1]/act:type" />)) | |
-->'<xsl:value-of select="$parentguid" />'</xsl:template> | |
<xsl:template match="gnc:transaction"> | |
insert into journals (reference, date, description, currency) | |
values ( | |
<xsl:choose> | |
<xsl:when test="trn:num"><xsl:apply-templates select="trn:num" /></xsl:when> | |
<xsl:otherwise>null</xsl:otherwise> | |
</xsl:choose>, | |
cast('<xsl:value-of select="trn:date-posted/ts:date" />' as date), | |
'<xsl:value-of select="str:replace(trn:description, "'", "''")" />', | |
(select id from currencies where symbol = '<xsl:value-of select="trn:currency/cmdty:id" />')); | |
<xsl:apply-templates select="trn:splits/trn:split"/> | |
</xsl:template> | |
<xsl:template match="trn:num">'<xsl:value-of select="str:replace(., "'", "''")" />'</xsl:template> | |
<xsl:template match="trn:split"><xsl:variable name="qty" select="split:quantity" /> | |
<xsl:variable name="quantity" select='substring-before($qty, "/") div substring-after($qty, "/")' /> | |
insert into transactions (journal, description, account, amount, exchange_rate, is_debit) | |
values (currval('journals_id_seq'), | |
<xsl:choose> | |
<xsl:when test="count(split:memo) > 0"><xsl:apply-templates select="split:memo" /></xsl:when> | |
<xsl:otherwise>null</xsl:otherwise> | |
</xsl:choose>, | |
(select account from account_id_to_guid where guid='<xsl:value-of select="split:account"/>'), | |
abs(<xsl:value-of select="$quantity" />), | |
<xsl:choose> | |
<xsl:when test="$quantity = 0">abs(<xsl:value-of select="split:value" />.0),</xsl:when> | |
<xsl:otherwise>abs((<xsl:value-of select="split:value" />.0)/<xsl:value-of select="$quantity" />),</xsl:otherwise> | |
</xsl:choose> | |
case when <xsl:value-of select="$quantity"/> < 0.0 then FALSE else TRUE end); | |
</xsl:template> | |
<xsl:template match="split:memo">'<xsl:value-of select="str:replace(., "'", "''")" />'</xsl:template> | |
</xsl:stylesheet> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment