Class: MARC::Reader
- Inherits:
-
Object
- Object
- MARC::Reader
- Defined in:
- lib/enhanced_marc/reader.rb
Class Method Summary collapse
-
.decode(marc, params = {}) ⇒ Object
A static method for turning raw MARC data in transission format into a MARC::Record object.
Class Method Details
.decode(marc, params = {}) ⇒ Object
A static method for turning raw MARC data in transission format into a MARC::Record object.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/enhanced_marc/reader.rb', line 5 def self.decode(marc, params={}) leader = Leader.new(marc[0..LEADER_LENGTH-1]) begin record = case leader.get_type when 'BKS' then MARC::BookRecord.new when 'SER' then MARC::SerialRecord.new when 'VIS' then MARC::VisualRecord.new when 'MIX' then MARC::MixedRecord.new when 'MAP' then MARC::MapRecord.new when 'SCO' then MARC::ScoreRecord.new when 'REC' then MARC::SoundRecord.new when 'COM' then MARC::ComputerRecord.new else MARC::Record.new end rescue ArgumentError record = MARC::Record.new end record.leader = leader # where the field data starts base_address = record.leader[12..16].to_i # get the byte offsets from the record directory directory = marc[LEADER_LENGTH..base_address-1] throw "invalid directory in record" if directory == nil # the number of fields in the record corresponds to # how many directory entries there are num_fields = directory.length / DIRECTORY_ENTRY_LENGTH # when operating in forgiving mode we just split on end of # field instead of using calculated byte offsets from the # directory all_fields = marc[base_address..-1].split(END_OF_FIELD) 0.upto(num_fields-1) do |field_num| # pull the directory entry for a field out entry_start = field_num * DIRECTORY_ENTRY_LENGTH entry_end = entry_start + DIRECTORY_ENTRY_LENGTH entry = directory[entry_start..entry_end] # extract the tag tag = entry[0..2] # get the actual field data # if we were told to be forgiving we just use the # next available chuck of field data that we # split apart based on the END_OF_FIELD field_data = '' if params[:forgiving] field_data = all_fields.shift() # otherwise we actually use the byte offsets in # directory to figure out what field data to extract else length = entry[3..6].to_i offset = entry[7..11].to_i field_start = base_address + offset field_end = field_start + length - 1 field_data = marc[field_start..field_end] end # remove end of field field_data.delete!(END_OF_FIELD) # add a control field or data field if tag < '010' record.append(MARC::ControlField.new(tag,field_data)) else field = MARC::DataField.new(tag) # get all subfields subfields = field_data.split(SUBFIELD_INDICATOR) # must have at least 2 elements (indicators, and 1 subfield) # TODO some sort of logging? next if subfields.length() < 2 # get indicators indicators = subfields.shift() field.indicator1 = indicators[0,1] field.indicator2 = indicators[1,1] # add each subfield to the field subfields.each() do |data| subfield = MARC::Subfield.new(data[0,1],data[1..-1]) field.append(subfield) end # add the field to the record record.append(field) end end record.fields.reindex return record end |