OFC Parse and Build 1Overview
This document describes the parse and build code for handling the Open Financial Connectivity (OFC) file format. The OFC file format is a standard SGML (Standard Generalized Markup Language) format defined by an SGML DTD. To read an OFC file one could use a standard SGML parser that reads in the DTD and the file or write a specific parser that handles only the OFC DTD. We chose to provide one implementation of the OFC specific parser written in ANSI C for portability that could be used by providers on various platforms.
The code provided is complete parse and build code meaning it will fully handle both requests and responses. An OFC server should only have to handle parsing a request and building a response. We provide the code for parsing into a linked list of transaction structures and building from the same list of structures. The server side will use the parse and build code in the following manner:
The parser is a standard recursive descent parser that makes use of a token table for the rules of the DTD. This table describes the token tag, whether or not the tag is required and the data type of the data associated with that tag. There is an entry in the table for each tag, both begin and end tags.
The parser takes a pointer to an OFC file in memory and operates on it from there. We parse in memory because the lowest level the structure for a transaction or aggregate contains pointers to strings for the individual elements which are actually pointers into the OFC image in memory. In parsing, we thus, modify the OFC file image itself, replacing certain characters with NULL to create C character strings. Parsing in-situ like this allows us to save memory and time, otherwise we'd have to allocate space for each character string and copy it from the OFC data to the new storage.
The parser is also designed to work within a multithreaded environment so no global variables are used and the current token and state of the tokenizer are passed around in all functions. This is important in an environment like NT using the Internet Information Server because extensions to that server are multithreaded DLLs and need to be thread safe.
The parser only works on legal OFC files. Any time an unknown or out-of-order tag is encountered an OFC_ERROR error code is returned. In this version we do not make an attempt to recover from an invalid file error. If the server gets an OFC_ERROR back from parsing a request it should return an HTTP status of 400, Invalid Request. We assume that the driver will generate only valid OFC files and that any parse error encountered is due to transmission errors so returning an HTTP 400 from the server will cause Money to enter crash recovery and re-send the same request.
Memory errors could also be encountered, though unlikely. If the parse or build cannot allocate memory the function returns a NO_MEMORY. This error flags an Internal Server error and should return an HTTP status of 500 to inform the client of the error.
The transaction list built by Parse and read by Build is a simple list format of structures that match the OFC Transactions and Aggregates as defined in the DTD. The <ofcdtd.h> header file describes these in detail. There is a high level structure defined for the OFCDOC type and then a structure of OFC transactions (OFCTRN) that is the main node in the linked list. The OFCTRN structure contains the type of the transaction, a pointer to the transaction specific structure and a link to the next transaction in the list. A linked list of structures was used in place of a full parse tree for ease of traversal.
The linked list for a hypothetical OFC file looks something like:
The build routines do a 2-pass build. The first pass is a verification phase on the linked list which your bank specific code must build. This pass tries to insure proper ordering of transactions according to the DTD and that all required fields are filled in. This validation will not validate individual elements, for example, we won't validate that a date is "bad" which will be validated, hopefully, by your server and the XSOFC driver on the client side.
The second pass does the actual build of the OFC data into a memory buffer. The strings you pass in the structures are copied into a memory buffer with the proper tags around them. On build we only use tags when they are required by the DTD, all optional tags are left off to keep the data small for transfer over the phone connection.