ofx-0.4.2.0: Parser for OFX data

Safe HaskellSafe
LanguageHaskell2010

Data.OFX

Contents

Description

Parser for downloaded OFX files.

This parser was written based on the OFX version 1.03 specification, which is available at

http://www.ofx.net

It will probably work on earlier versions of OFX without incident. However, it may or may not not work on newer versions of OFX, which are XML based (this version of OFX is SGML based.)

It will also parse QFX files, which are OFX files with minor proprietary additions by Intuit, the maker of Quicken.

An OFX file consists of three parts: the HTTP headers (which this parser does NOT handle because typically they will not show up in files downloaded to disk), the OFX headers, and the OFX data. This parser handles the OFX headers and the OFX data.

The parser in this module simply parses the tags and data into a tree, which you can manipulate with other functions. Some functions are provided to find the transactions in the tree and place them into a Transaction type, which is the data you are most likely interested in. If you are interested in other data you can query the Tag tree for what you need.

For example, to read in the filename given on the command line and parse it and print it nicely:

The ofx package includes two executable files that you can use at the command line to test the library and see how it works. The renderTransactions executable reads an OFX file on standard input, runs it through the prettyRenderTransactions function, and prints the result to standard output. The renderOfx executable reads an OFX file on standard input, runs it through the prettyRenderOfxFile function, and prints the result to standard output.

Synopsis

Error handling

type Err = Either String Source #

Error handling. Errors are indicated with a Left String; successes with a Right.

The OFX data tree

type HeaderTag = String Source #

Headers consists of simple tag:value pairs; this represents the tag.

type HeaderValue = String Source #

The value in an OFX header.

data OFXHeader Source #

An OFX file starts with a number of headers, which take the form tag:value followed by a newline. These are followed by a blank line.

type TagName = String Source #

The name of an OFX tag

type TagData = String Source #

The data accompanying an OFX tag.

data Tag Source #

The main OFX data consists of a series of tags. OFX 1.03 is SGML, not XML. This means that opening tags need not have closing tags. In OFX, a tag either has data and no child elements, or it has no data and it has child elements.

Constructors

Tag TagName (Either TagData [Tag]) 

Instances

data OFXFile Source #

All the data from an OFX file.

Constructors

OFXFile 

Fields

Manipulating the OFX tag tree

find :: TagName -> Tag -> [Tag] Source #

Finds child tags with the given name. When a tag is found, that tag is not searched for further children with the same name.

findPath :: [TagName] -> Tag -> Maybe Tag Source #

Descends through a tree of tags to find a tag at a specific location in the tree. Fails if any part of the search fails. For example, to find the financial institution ORG tag, where t is the root OFX tag:

findPath ["SIGNONMSGSRSV1", "SONRS", "FI", "ORG"] t

tagData :: Tag -> Maybe TagData Source #

Gets the data from a tag, if it is a tag with data.

pathData :: [TagName] -> OFXFile -> Maybe TagData Source #

Goes to a certain path in the tag hierarchy and pulls the requested data, if the tag is present and it is a data tag. For example, to get the name of the financial institution:

pathData ["SIGNONMSGSRSV1", "SONRS", "FI", "ORG"] f

findData :: TagName -> Tag -> Maybe TagData Source #

Finds the first tag (either this tag or any children) that has the given name and that is a data tag (not an aggregate tag.) If no data tag with the given name is found, returns Nothing.

Extracting specific data

fiName :: OFXFile -> Maybe TagData Source #

Gets the name of the financial institution from the FI tag, if available. The OFX spec does not require this tag to be present.

creditCardNumber :: OFXFile -> Maybe TagData Source #

Gets the credit card number, if available. The OFX spec does not require this tag to be present.

bankAccountNumber :: OFXFile -> Maybe TagData Source #

Gets the bank account number, if available. The OFX spec does not require this tag to be present.

accountNumber :: OFXFile -> Maybe TagData Source #

Gets either the credit card or bank account number, if available.

Types to represent specific OFX data

data Transaction Source #

A single STMTTRN, see OFX spec section 11.4.2.3.1. This is most likely what you are interested in after downloading a statement from a bank.

Constructors

Transaction 

Fields

  • txTRNTYPE :: TrnType

    Transaction type

  • txDTPOSTED :: ZonedTime

    Date transaction was posted to account

  • txDTUSER :: Maybe ZonedTime

    Date user initiated transaction, if known

  • txDTAVAIL :: Maybe ZonedTime

    Date funds are available

  • txTRNAMT :: String

    Amount of transaction. This is left as the string that was originally in the download. That means the transaction may include a plus or minus sign (no sign is the same as a plus sign.) According to section 3.2.9.2, amounts are always signed from the perspective of the customer.

    Typically negative amounts:

    • Investment buy amount, investment sell quantity
    • Bank statement debit amounts, checks, fees
    • Credit card purchases
    • Margin balance (unless the institution owes the client money)

    Typically positive amounts:

    • Investment sell amount, investment buy quantity
    • Bank statement credits
    • Credit card payments
    • Ledger balance (unless the account is overdrawn)

    Formats for amounts are described in 3.2.9.1. If there is no decimal point, there is an implied decimal point at the end of the value. Trailing and leading spaces "should" be stripped. Positive or minus is indicated with a leading sign; a plus sign is assumed if there is no sign.

    An amount has a maximum of 32 alphanumeric characters, including digits and punctuation.

    The radix point is indicated with either a period or a comma. Amounts "should" not include any digit grouping characters.

  • txFITID :: String

    Transaction ID issued by financial institution. Used to detect duplicate downloads.

  • txCORRECTFITID :: Maybe String

    If present, this indicates the FITID of a previously sent transaction that is corrected by this record. This transaction replaces or deletes the transaction that it corrects, based on the value of CORRECTACTION below.

  • txCORRECTACTION :: Maybe CorrectAction
  • txSRVRTID :: Maybe String

    Server assigned transaction ID; used for transactions initiated by client, such as payment or funds transfer

  • txCHECKNUM :: Maybe String

    Check or other reference number

  • txREFNUM :: Maybe String

    Reference number that uniquely identifies the transaction. Can be used in addition to or instead of a CHECKNUM.

  • txSIC :: Maybe String

    Standard Industrial Code

  • txPAYEEID :: Maybe String

    Payee identifier if available

  • txPayeeInfo :: Maybe (Either String Payee)

    Information on the payee. The OFX spec seems to be saying that every transaction must have either NAME, wich is "name of payee or description of transaction", or the Payee aggregate. The former is indicated with a Left, the latter with a Right.

  • txAccountTo :: Maybe (Either BankAcctTo CCAcctTo)

    Information on a transfer. If this transaction wa sa transfer, this may contain information about the account being transferred to.

  • txMEMO :: Maybe String

    Extra information not in NAME

  • txCurrency :: Maybe (Either Currency OrigCurrency)

    Currency option. OFX spec says to choose either CURRENCY or ORIGCURRENCY.

transaction :: Tag -> Err Transaction Source #

Gets a single Transaction from a tag. The tag should be the one named STMTTRN. Fails with an error message if any required field was not present.

transactions :: OFXFile -> Err [Transaction] Source #

Pulls all Transactions from a file. Might fail if the OFX file does not conform to the specification (or if there are bugs in this library.) In case of the former, you can manually parse the transaction information yourself using functions like pathData. In case of the latter, please send bugreports :-)

data TrnType Source #

OFX transaction types. These are used in STMTTRN aggregates, see OFX spec section 11.4.2.3.1.1.

Constructors

TCREDIT 
TDEBIT 
TINT

Interest earned or paid (which it is depends on sign of amount)

TDIV

Dividend

TFEE 
TSRVCHG 
TDEP

Deposit

TATM

ATM debit or credit (which it is depends on sign of amount)

TPOS

Point of sale debit or credit (which it is depends on sign of amount)

TXFER

Transfer

TCHECK 
TPAYMENT

Electronic payment

TCASH

Cash withdrawal

TDIRECTDEP

Direct deposit

TDIRECTDEBIT

Merchant initiated debit

TREPEATPMT

Repeating payment / standing order

TOTHER 

payee Source #

Arguments

:: Tag

The tag which contains the PAYEE tag, if there is one. This would typically be a STMTTRN tag.

-> Maybe (Err Payee)

Nothing if there is no PAYEE tag. Just if a PAYEE tag is found, with a Left if the tag is lacking a required element, or a Right if the tag is successfully parsed.

If there is more than one PAYEE tag, only the first one is considered.

Parses a Payee record from its parent tag.

data CorrectAction Source #

Can be either REPLACE or DELETE.

Constructors

REPLACE

Replaces the transaction referenced by the CORRECTFITID

DELETE

Deletes the transaction referenced by the CORRECTFITID

data BankAcctTo Source #

Constructors

BankAcctTo 

Fields

data CCAcctTo Source #

Constructors

CCAcctTo 

Fields

data CurrencyData Source #

Holds all data both for CURRENCY and for ORIGCURRENCY.

Constructors

CurrencyData 

Fields

currencyData Source #

Arguments

:: Tag

The tag that contains the data, e.g. CURRENCY or ORIGCURRENCY.

-> Err CurrencyData 

Parses currency data.

Running parsers

parseOfxFile :: String -> Err OFXFile Source #

Parses an input file. Returns either an error message or the resulting OFXFile.

parseTransactions :: String -> Err [Transaction] Source #

Parses an OFX file and gets the list of Tranasction.

prettyRenderOfxFile Source #

Arguments

:: String

File contents to parse

-> String

Pretty printed result of rending the result of the parse, which is either an error message or an OFXFile.

Parses an input file to an OfxFile. Returns a pretty-printed string with the results of the parse.

prettyRenderTransactions Source #

Arguments

:: String

File contents to parse

-> String

Pretty printed result of rendering the result of the parse, which is either an error message or a list of Transaction.

Parses an input file to an OfxFile, and then to a list of Transaction. Returns a pretty-printed string with the results.

Parsec parsers

ofxFile :: Parser OFXFile Source #

Parses an entire OFX file, including headers.

newline :: Parser () Source #

Parses either a UNIX or an MS-DOS newline. According to 1.2.2, OFX does not contain any white space between tags. However, since I have seen OFX files that do have whitespace between tags, the parser makes allowance for this.

escChar :: Parser Char Source #

Parses a character, possibly with an escape sequence. The greater-than sign, less-than sign, and ampersand must be entered with escape sequences.

According to OFX spec section 2.3.2.1, ampersands, less-than signs, and greater-than signs must appear as entities. However some banks deliver broken OFX files that do not use entities for ampersands (and possibly for less-than or greater-than signs too, although I have not yet observed such behavior.) There is now an error message that reflects this problem. Client code can filter the OFX data for known offenders before passing it to this library.

openingTag :: Parser TagName Source #

Parses any opening tag. Returns the name of the tag.

closingTag :: TagName -> Parser () Source #

Parses a closing tag with the given name.

tag :: Parser Tag Source #

Parses any tag. The tag itself must be followed by at least one character: either the next tag if this is an aggregate tag, or the data if this is a data tag. OFX does not allow empty tags.

The OFX spec seems to say that OFX files do not include trailing newlines after tags or data, but I have seen these newlines in QFX files, so this parses optional trailing newlines and spaces.

date :: Parser ZonedTime Source #

Parses an OFX date. Fails if the date is not valid or if there is no date to be parsed.

time :: Parser (TimeOfDay, TimeZone) Source #

Parses an OFX time. Fails if the time is not valid or if there is no time to parse. Fails if there is no time to parse; however, if there is a time but no zone, returns the time and UTC for the zone.

tzOffset :: Parser TimeZone Source #

Parses a time zone offset. Fails if there is no time zone offset to parse.

Pretty printers

pEither :: (a -> Doc) -> (b -> Doc) -> Either a b -> Doc Source #

pMaybe :: (a -> Doc) -> Maybe a -> Doc Source #

pList :: [Doc] -> Doc Source #

pExceptional :: (e -> Doc) -> (a -> Doc) -> Either e a -> Doc Source #