# Copyright © 2007 Chris Guidry # # This file is part of OFX for Ruby. # # OFX for Ruby is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # OFX for Ruby is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . class OFX::OFX102::Parser rule target : | ofx_body ofx_body : tag_from contents tag_to tag_from : tag_in element tag_out { start_tag(val[1]) } tag_to : etag_in element tag_out { end_tag(val[1]) } contents : /* none */ | contents content content : text | aggregate | value aggregate : tag_from contents tag_to value : tag_from text { data_value(val[1]) } end ---- header ---- # # generated by racc # require File.dirname(__FILE__) + '/lexer' ---- inner ---- attr :documents attr :ofx_hashes def initialize @documents = [] @ofx_hashes = [] @tags_stack = [] end private def start_tag(tag_name) # push an empty aggregate/value tag @tags_stack.push({ tag_name => {} }) end def data_value(value) # pop the most recent tag, and use it's name as the key in the next higher tag's hash tag = @tags_stack.pop @tags_stack.last[@tags_stack.last.keys[0]][tag.keys[0]] = CGI::unescapeHTML(value) end def end_tag(tag_name) # pop the most recent tag, stop and recognize this as a full document if this is the last tag; otherwise, # use this tag's naem as the key in the next higher tag's hash tag = @tags_stack.pop if (@tags_stack.empty?) @ofx_hashes << tag @documents << OFX::Document.from_ofx_102_hash(tag) else previous = @tags_stack.last[@tags_stack.last.keys[0]][tag.keys[0]] if previous == nil @tags_stack.last[@tags_stack.last.keys[0]][tag.keys[0]] = tag[tag.keys[0]] elsif previous.kind_of?(Array) previous << tag[tag.keys[0]] else @tags_stack.last[@tags_stack.last.keys[0]][tag.keys[0]] = [previous, tag[tag.keys[0]]] end end end ---- footer ----