{
    "content": [
        {
            "type": "text",
            "text": "# MARC::Doc::Tutorial (perldoc)\n\n## NAME\n\nMARC::Doc::Tutorial - A documentation-only module for new users of MARC::Record\n\n## SYNOPSIS\n\nperldoc MARC::Doc::Tutorial\n\n## Sections\n\n- **NAME**\n- **SYNOPSIS**\n- **INTRODUCTION** (2 subsections)\n- **READING** (8 subsections)\n- **CREATING** (1 subsections)\n- **WRITING** (1 subsections)\n- **UPDATING** (9 subsections)\n- **VALIDATING** (2 subsections)\n- **SWOLLEN APPENDICES** (6 subsections)\n- **CONTRIBUTORS**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "MARC::Doc::Tutorial",
        "section": "",
        "mode": "perldoc",
        "summary": "MARC::Doc::Tutorial - A documentation-only module for new users of MARC::Record",
        "synopsis": "perldoc MARC::Doc::Tutorial",
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "SYNOPSIS",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "INTRODUCTION",
                "lines": 22,
                "subsections": [
                    {
                        "name": "History of MARC on CPAN",
                        "lines": 23
                    },
                    {
                        "name": "Brief Overview of MARC Classes",
                        "lines": 36
                    }
                ]
            },
            {
                "name": "READING",
                "lines": 1,
                "subsections": [
                    {
                        "name": "Reading a record from a file",
                        "lines": 20
                    },
                    {
                        "name": "Iterating through a batch file",
                        "lines": 29
                    },
                    {
                        "name": "Checking for errors",
                        "lines": 31
                    },
                    {
                        "name": "Recovering from errors",
                        "lines": 34
                    },
                    {
                        "name": "Looking at a field",
                        "lines": 31
                    },
                    {
                        "name": "Looking at repeatable fields",
                        "lines": 24
                    },
                    {
                        "name": "Looking at a set of related fields",
                        "lines": 25
                    },
                    {
                        "name": "Looking at all the fields in a record",
                        "lines": 35
                    }
                ]
            },
            {
                "name": "CREATING",
                "lines": 5,
                "subsections": [
                    {
                        "name": "Creating a record",
                        "lines": 34
                    }
                ]
            },
            {
                "name": "WRITING",
                "lines": 4,
                "subsections": [
                    {
                        "name": "Writing records to a file",
                        "lines": 97
                    }
                ]
            },
            {
                "name": "UPDATING",
                "lines": 15,
                "subsections": [
                    {
                        "name": "Adding a field",
                        "lines": 26
                    },
                    {
                        "name": "Preserving field order",
                        "lines": 32
                    },
                    {
                        "name": "Deleting a field",
                        "lines": 32
                    },
                    {
                        "name": "Changing existing fields",
                        "lines": 39
                    },
                    {
                        "name": "Updating subfields and indicators",
                        "lines": 38
                    },
                    {
                        "name": "Changing a record's leader",
                        "lines": 24
                    },
                    {
                        "name": "Modifying fields without indicators",
                        "lines": 33
                    },
                    {
                        "name": "Reordering subfields",
                        "lines": 49
                    },
                    {
                        "name": "Updating subject subfield x to subfield v",
                        "lines": 70
                    }
                ]
            },
            {
                "name": "VALIDATING",
                "lines": 4,
                "subsections": [
                    {
                        "name": "Using MARC::Lint",
                        "lines": 36
                    },
                    {
                        "name": "Customizing MARC::Lint",
                        "lines": 75
                    }
                ]
            },
            {
                "name": "SWOLLEN APPENDICES",
                "lines": 6,
                "subsections": [
                    {
                        "name": "Comparing Collections",
                        "lines": 1
                    },
                    {
                        "name": "Authority Records",
                        "lines": 2
                    },
                    {
                        "name": "Call numbers",
                        "lines": 1
                    },
                    {
                        "name": "Subject headings",
                        "lines": 133
                    },
                    {
                        "name": "Excel",
                        "lines": 63
                    },
                    {
                        "name": "Databases",
                        "lines": 117
                    }
                ]
            },
            {
                "name": "CONTRIBUTORS",
                "lines": 20,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "MARC::Doc::Tutorial - A documentation-only module for new users of MARC::Record\n",
                "subsections": []
            },
            "SYNOPSIS": {
                "content": "perldoc MARC::Doc::Tutorial\n",
                "subsections": []
            },
            "INTRODUCTION": {
                "content": "What is MARC?\nThe MAchine Readable Cataloging format was designed by the Library of Congress in the late 1960s\nin order to allow libraries to convert their card catalogs into a digital format. The advantages\nof having computerized card catalogs were soon realized, and now MARC is being used by all sorts\nof libraries around the world to provide computerized access to their collections. MARC data in\ntransmission format is optimized for processing by computers, so it's not very readable for the\nnormal human. For more about the MARC format, visit the Library of Congress at\nhttp://www.loc.gov/marc/\n\nWhat is this Tutorial?\nThe document you are reading is a beginners guide to using Perl to processing MARC data, written\nin the 'cookbook' style. Inside, you will find recipes on how to read, write, update and convert\nMARC data using the MARC::Record CPAN package. As with any cookbook, you should feel free to dip\nin at any section and use the recipe you find interesting. If you are new to Perl, you may want\nto read from the beginning.\n\nThe document you are reading is distributed with the MARC::Record package, however in case you\nare reading it somewhere else, you can find the latest version at CPAN:\nhttp://www.cpan.org/modules/by-module/MARC/. You'll notice that some sections aren't filled in\nyet, which is a result of this document being a work in progress. If you have ideas for new\nsections please make a suggestion to perl4lib: https://perl4lib.perl.org/.\n",
                "subsections": [
                    {
                        "name": "History of MARC on CPAN",
                        "content": "In 1999, a group of developers began working on MARC.pm to provide a Perl module for working\nwith MARC data. MARC.pm was quite successful since it grew to include many new options that were\nrequested by the Perl/library community. However, in adding these features the module swiftly\noutgrew its own clothes, and maintenance and addition of new features became extremely\ndifficult. In addition, as libraries began using MARC.pm to process large MARC data files (>1000\nrecords) they noticed that memory consumption would skyrocket. Memory consumption became an\nissue for large batches of records because MARC.pm's object model was based on the 'batch'\nrather than the record... so each record in the file would often be read into memory. There were\nways of getting around this, but they were not obvious. Some effort was made to reconcile the\ntwo approaches (batch and record), but with limited success.\n\nIn mid 2001, Andy Lester released MARC::Record and MARC::Field which provided a much simpler and\nmaintainable package for processing MARC data with Perl. As its name suggests, MARC::Record\ntreats an individual MARC record as the primary Perl object, rather than having the object\nrepresent a given set of records. Instead of forking the two projects, the developers agreed to\nencourage use of the MARC::Record framework, and to work on enhancing MARC::Record rather than\nextending MARC.pm further. Soon afterwards, MARC::Batch was added, which allows you to read in a\nlarge data file without having to worry about memory consumption.\n\nIn Dec., 2004, the MARC::Lint module, an extension to check the validity of MARC records, was\nremoved from the MARC::Record distribution, to become a separately distributed package. This\ntutorial contains examples for using MARC::Lint.\n"
                    },
                    {
                        "name": "Brief Overview of MARC Classes",
                        "content": "The MARC::Record package is made up of several separate packages. This can be somewhat confusing\nto people new to Perl, or Object Oriented Programming. However this framework allows easy\nextension, and is built to support new input/output formats as their need arises. For a good\nintroduction to using the object oriented features of Perl, see the perlboot documentation that\ncame with your version of Perl.\n\nHere are the packages that get installed with MARC::Record:\n\nMARC::Batch\nA convenience class for accessing MARC data contained in an external file.\n\nMARC::Field\nAn object for representing the indicators and subfields of a single MARC field.\n\nMARC::Record\nThis primary class represents a MARC record, being a container for multiple MARC::Field\nobjects.\n\nMARC::Doc::Tutorial\nThis document!\n\nMARC::File\nA superclass for representing files of MARC data.\n\nMARC::File::MicroLIF\nA subclass of MARC::File for working with data encoded in the MicroLIF format.\n\nMARC::File::USMARC\nA subclass of MARC::File for working with data encoded in the USMARC format.\n\nHelp Wanted!\nIt's already been mentioned but it's worth mentioning again: MARC::Doc::Tutorial is a work in\nprogress, and you are encouraged to submit any suggestions for additional recipes via the\nperl4lib mailing list at https://perl4lib.perl.org/. Also, patches and issue reports are welcome\nat https://github.com/perl4lib/marc-perl.\n"
                    }
                ]
            },
            "READING": {
                "content": "",
                "subsections": [
                    {
                        "name": "Reading a record from a file",
                        "content": "Let's say you have a USMARC record in 'file.dat' and you'd like to read in the record and print\nout its title.\n\n1   ## Example R1\n2\n3   ## create a MARC::Batch object.\n4   use MARC::Batch;\n5   my $batch = MARC::Batch->new('USMARC', 'file.dat');\n6\n7   ## get a MARC record from the MARC::Batch object.\n8   ## the $record will be a MARC::Record object.\n9   my $record = $batch->next();\n10\n11   ## print the title contained in the record.\n12   print $record->title(),\"\\n\";\n\nUsing the distribution's 't/camel.usmarc', your result should be:\n\nActivePerl with ASP and ADO / Tobias Martinsson.\n"
                    },
                    {
                        "name": "Iterating through a batch file",
                        "content": "Now imagine that 'file.dat' actually contains multiple records and we want to print the title\nfor each of them. Our program doesn't have to change very much at all: we just need to add a\nloop around our call to \"next()\".\n\n1   ## Example R2\n2\n3   ## create a MARC::Batch object.\n4   use MARC::Batch;\n5   my $batch = MARC::Batch->new('USMARC','file.dat');\n6\n7   while (my $record = $batch->next()) {\n8\n9     ## print the title contained in the record.\n10     print $record->title(),\"\\n\";\n11\n12   }\n\nThe call to the \"next()\" method at line 7 returns the next record from the file. \"next()\"\nreturns \"undef\" when there are no more records left in the file, which causes the \"while\" loop\nto end. This is a useful idiom for reading in all the records in a file. Your results with\n'camel.usmarc' should be:\n\nActivePerl with ASP and ADO / Tobias Martinsson.\nProgramming the Perl DBI / Alligator Descartes and Tim Bunce.\n.\n.\n.\nCross-platform Perl / Eric F. Johnson.\n"
                    },
                    {
                        "name": "Checking for errors",
                        "content": "It is a good idea to get in the habit of checking for errors. MARC/Perl has been designed to\nhelp you do this. Calls to \"next()\" when iterating through a batch file will return \"undef\" when\nthere are no more records to return... AND when an error was encountered (see the next recipe to\nsubvert this). You probably want to make sure that you didn't abruptly stop reading a batch file\nbecause of an error.\n\n1   ## Example R3\n2\n3   ## create a MARC::Batch object.\n4   use MARC::Batch;\n5   my $batch = MARC::Batch->new('USMARC','file.dat');\n6\n7   ## get a marc record from the MARC::Batch object.\n8   ## $record will be a MARC::Record object.\n9   while ( my $record = $batch->next() ) {\n10       print $record->title(),\"\\n\";\n11   }\n12\n13   ## make sure there weren't any problems.\n14   if ( my @warnings = $batch->warnings() ) {\n15       print \"\\nWarnings were detected!\\n\", @warnings;\n16   }\n\nThe call to \"warnings()\" at line 14 will retrieve any warning messages and store them in\n@warnings. This allows you to detect when \"next()\" has aborted prematurely (before the end of\nthe file has been reached). When a warning is detected, an explanation is sent to \"STDERR\". By\nintroducing an error into 'camel.usmarc', we'll receive the following output to \"STDOUT\":\n\nWarnings were detected!\nInvalid indicators \"a0\" forced to blanks in record 1 for tag 245\n"
                    },
                    {
                        "name": "Recovering from errors",
                        "content": "You may want to keep reading a batch file even after an error has been encountered. If so, you\nwill want to turn strict mode off using the \"strictoff()\" method. You can also prevent warnings\nfrom being printed to \"STDERR\" using the \"warningsoff()\" method. By default, strict is on as a\nsafety precaution to prevent you from using corrupt MARC data. Once off, you can turn both\nstrict and warnings back on again with the \"stricton()\" and \"warningson()\" methods.\n\n1   ## Example R4\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC', 'file.dat');\n5   $batch->strictoff();\n6\n7   while ( my $record = $batch->next() ) {\n8      print $record->title(),\"\\n\";\n9   }\n10\n11   ## make sure there weren't any problems.\n12   if ( my @warnings = $batch->warnings() ) {\n13       print \"\\nWarnings were detected!\\n\", @warnings;\n14   }\n\nIntroducing a second error to the 'camel.usmarc' file gives the following:\n\nActivePerl with ASP and ADO / Tobias Martinsson.\nProgramming the Perl DBI / Alligator Descartes and Tim Bunce.\n.\n.\n.\nCross-platform Perl / Eric F. Johnson.\n\nWarnings were detected!\nInvalid indicators \"a0\" forced to blanks in record 1 for tag 245\nInvalid indicators \"a0\" forced to blanks in record 5 for tag 245\n"
                    },
                    {
                        "name": "Looking at a field",
                        "content": "Our previous examples use MARC::Record's \"title()\" method to easily access the 245 field, but\nyou will probably want programs that access lots of other MARC fields. MARC::Record's \"field()\"\nmethod gives you complete access to the data found in any MARC field. The \"field()\" method\nreturns a MARC::Field object which can be used to access the data, indicators, and even the\nindividual subfields. Our next example shows how this is done.\n\n1   ## Example R5\n2\n3   ## open a file.\n4   use MARC::Batch;\n5   my $batch = MARC::Batch->new('USMARC','file.dat');\n6\n7   ## read a record.\n8   my $record = $batch->next();\n9\n10   ## get the 100 field as a MARC::Field object.\n11   my $field = $record->field('100');\n12   print \"The 100 field contains: \",$field->asstring(),\"\\n\";\n13   print \"The 1st indicator is \",$field->indicator(1),\"\\n\";\n14   print \"The 2nd indicator is \",$field->indicator(2),\"\\n\";\n15   print \"Subfield d contains: \",$field->subfield('d'),\"\\n\";\n\nWhich results in something like:\n\nThe 100 field contains: Martinsson, Tobias, 1976-\nThe 1st indicator is 1\nThe 2nd indicator is\nSubfield d contains: 1976-\n\nAs before, use a \"while\" loop to iterate through all the records in a batch.\n"
                    },
                    {
                        "name": "Looking at repeatable fields",
                        "content": "So how do you retrieve data from repeatable fields? The \"field()\" method can help you with this\nas well. In our previous example's line 11, the \"field()\" method was used in a *scalar* context,\nsince the result was being assigned to the variable $field. However in a *list* context,\n\"field()\" will return all the fields in the record of that particular type. For example:\n\n1   ## Example R6\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC','file.dat');\n5   my $record = $batch->next();\n6\n7   ## get all the 650 fields (list context).\n8   my @fields = $record->field('650');\n9\n10   ## examine each 650 field and print it out.\n11   foreach my $field (@fields) {\n12     print $field->asstring(),\"\\n\";\n13   }\n\nWhich prints out the following for the first record of 't/camel.usmarc':\n\nActive server pages.\nActiveX.\n"
                    },
                    {
                        "name": "Looking at a set of related fields",
                        "content": "\"field()\" also allows you to retrieve similar fields using '.' as a wildcard.\n\n1   ## Example R7\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC','file.dat');\n5   my $record = $batch->next();\n6\n7   # retrieve all title fields in one shot.\n8   foreach my $field ($record->field('2..')) {\n9     print $field->tag(),' contains ',$field->asstring(),\"\\n\";\n10   }\n\nNotice the shorthand in line 8 which compacts lines 7-13 of our previous example. Instead of\nstoring the fields in an array, the \"field()\" still returns a list in the \"for\" loop. Line 9\nuses the \"tag()\" method which returns the tag number for a particular MARC field, which is\nuseful when you aren't certain what tag you are currently dealing with. Sample output from this\nrecipe:\n\n245 contains ActivePerl with ASP and ADO / Tobias Martinsson.\n260 contains New York : John Wiley & Sons, 2000.\n\nYou can also return all tags for a specific record by using '...' in \"field\" (though, see the\nnext recipe).\n"
                    },
                    {
                        "name": "Looking at all the fields in a record",
                        "content": "The last example in this section illustrates how to retrieve *all* the fields in a record using\nthe \"fields()\" method. This method is similar to passing '...' as a wildcard (see our previous\nrecipe for alternative access).\n\n1   ## Example R8\n2\n3   use MARC::Batch;\n4   my $file = MARC::Batch->new('USMARC','file.dat');\n5   my $record = $batch->next();\n6\n7   ## get all of the fields using the fields() method.\n8   my @fields = $record->fields();\n9\n10   ## print out the tag, the indicators and the field contents.\n11   foreach my $field (@fields) {\n12     print\n13       $field->tag(), \" \",\n14       defined $field->indicator(1) ? $field->indicator(1) : \"\",\n15       defined $field->indicator(2) ? $field->indicator(2) : \"\",\n16       \" \", $field->asstring, \" \\n\";\n17   }\n\nThe above code would print the following for the first record of 't/camel.usmarc':\n\n001  fol05731351\n003  IMchF\n.\n.\n.\n300    xxi, 289 p. : ill. ; 23 cm. + 1 computer  laser disc (4 3/4 in.)\n500    \"Wiley Computer Publishing.\"\n650  0 Perl (Computer program language)\n630 00 Active server pages.\n630 00 ActiveX.\n"
                    }
                ]
            },
            "CREATING": {
                "content": "The examples in the Section 1 covered how to read in existing USMARC data in a file. Section 2\nwill show you how to create a MARC record from scratch. The techniques in this section would\nallow you to write programs which create MARC records that could then be loaded into an online\ncatalog, or sent to a third party.\n",
                "subsections": [
                    {
                        "name": "Creating a record",
                        "content": "To create a new MARC record, you'll need to first create a MARC::Record object, add a leader\n(though MARC::Record can create leaders automatically if you don't specifically define one), and\nthen create and add MARC::Field objects to your MARC::Record object. For example:\n\n1   ## Example C1\n2\n3   ## create a MARC::Record object.\n4   use MARC::Record;\n5   my $record = MARC::Record->new();\n6\n7   ## add the leader to the record. optional.\n8   $record->leader('00903pam  2200265 a 4500');\n9\n10   ## create an author field.\n11   my $author = MARC::Field->new(\n12     '100',1,'',\n13       a => 'Logan, Robert K.',\n14       d => '1939-'\n15     );\n16   $record->appendfields($author);\n17\n18   ## create a title field.\n19   my $title = MARC::Field->new(\n20     '245','1','4',\n21       a => 'The alphabet effect /',\n22       c => 'Robert K. Logan.'\n23     );\n24   $record->appendfields($title);\n\nThe key to creating records from scratch is to use \"appendfields()\", which adds a field to the\nend of the record. Since each field gets added at the end, it's up to you to order the fields\nthe way you want. \"insertfieldsbefore()\" and \"insertfieldsafter()\" are similar methods that\nallow you to define where the field gets added. These methods are covered in more detail below.\n"
                    }
                ]
            },
            "WRITING": {
                "content": "Sections 1 and 2 showed how to read and create USMARC data. Once you know how to read and\ncreate, it becomes important to know how to write the USMARC data to disk in order to save your\nwork. In these examples, we will create a new record and save it to a file called 'record.dat'.\n",
                "subsections": [
                    {
                        "name": "Writing records to a file",
                        "content": "1   ## Example W1\n2\n3   ## create a MARC::Record object.\n4   use MARC::Record;\n5   my $record = MARC::Record->new();\n6\n7   ## add the leader to the record. optional.\n8   $record->leader('00903pam  2200265 a 4500');\n9\n10   ## create an author field.\n11   my $author = MARC::Field->new(\n12     '100',1,'',\n13       a => 'Logan, Robert K.',\n14       d => '1939-'\n15     );\n16\n17   ## create a title field.\n18   my $title = MARC::Field->new(\n19     '245','1','4',\n20       a => 'The alphabet effect /',\n21       c => 'Robert K. Logan.'\n22     );\n23\n24   $record->appendfields($author, $title);\n25\n26   ## open a filehandle to write to 'record.dat'.\n27   open(OUTPUT, '> record.dat') or die $!;\n28   print OUTPUT $record->asusmarc();\n29   close(OUTPUT);\n\nThe \"asusmarc()\" method call at line 28 returns a scalar value which is the raw USMARC data for\n$record. The raw data is then promptly printed to the \"OUTPUT\" file handle. If you want to\noutput multiple records to a file, simply repeat the process at line 28 for the additional\nrecords. Also of note is the \"appendfields\" method: unlike recipe C1 which called the method\nonce for each field added, this recipe demonstrates that \"appendfields\" can accept multiple\narguments.\n\nNote to the curious: the \"asusmarc()\" method is actually an alias to the MARC::File::USMARC\n\"encode()\" method. Having separate \"encode()\" methods is a design feature of the MARC class\nhierarchy, since it allows extensions to be built that translate MARC::Record objects into\ndifferent data formats.\n\nDebugging with \"asformatted()\"\nSince raw USMARC data isn't very easy for humans to read, it is often useful to be able to see\nthe contents of your MARC::Record object represented in a 'pretty' way for debugging purposes.\nIf you have a MARC::Record object you'd like to pretty-print, use the \"asformatted()\" method.\n\n1   ## Example W2\n2\n3   ## create a MARC::Record object.\n4   use MARC::Record;\n5   my $record = MARC::Record->new();\n6\n7   $record->leader('00903pam  2200265 a 4500');\n8\n9   $record->appendfields(\n10    MARC::Field->new('100','1','', a=>'Logan, Robert K.', d=>'1939-'),\n11    MARC::Field->new('245','1','4', a=>'The alphabet effect /', c=>'Robert K. Logan.')\n12   );\n13\n14   ## pretty print the record.\n15   print $record->asformatted(), \"\\n\";\n\nThis code will pretty print the contents of the newly created record:\n\nLDR 00903pam  2200265 a 4500\n100 1  aLogan, Robert K.\nd1939-\n245 14 aThe alphabet effect /\ncRobert K. Logan.\n\nNotice on lines 9-12 how you can add a list of new fields by creating MARC::Field objects within\na call to \"appendfields()\". This is yet another shorthand method to those shown in recipes C1\nand W1. For more pretty-printing capabilities, try \"marcdump()\" in our next recipe.\n\nDebugging with marcdump()\nIf you have written USMARC data to a file (as in recipe W2) and you would like to verify that\nthe data is stored correctly you can use the \"marcdump\" command line utility that was installed\nwith the MARC::Record package:\n\n% marcdump record.dat\nrecord.dat\nLDR 00122pam  2200049 a 4500\n100 1  aLogan, Robert K.\nd1939-\n245 14 aThe alphabet effect /\ncRobert K. Logan.\n\nRecs  Errs Filename\n----- ----- --------\n1     0 record.dat\n\nAs you can see, this command results in the record being pretty printed to your screen\n(\"STDOUT\") similarly to the \"asformatted\" method from recipe W2. It is useful for verifying\nyour USMARC data after it has been stored on disk. More details about debugging are found later\nin VALIDATING.\n"
                    }
                ]
            },
            "UPDATING": {
                "content": "Now that you know how to read, write and create MARC data, you have the tools you need to update\nor edit exiting MARC data. Updating MARC data is a common task for library catalogers. Sometimes\nthere are huge amounts of records that need to be touched up... and while the touch ups are very\ndetail oriented, they are also highly repetitive. Luckily, computers are tireless, and not very\nprone to error (assuming the programmer isn't).\n\nWhen libraries receive large batches of MARC records for electronic text collections such as\nNetLibrary, Making of America, or microfiche sets like Early American Imprints, the records are\noften loaded into an online system and then the system is used to update the records.\nUnfortunately, not all these systems are created equal, and catalogers have to spend a great\ndeal of time touching up each individual record. An alternative would be to process the records\nprior to import and then, once in the system, the records would not need editing. This scenario\nwould save a great deal of time for the cataloger who would be liberated to spend their time\ndoing original cataloging... which computers are notably bad at!\n",
                "subsections": [
                    {
                        "name": "Adding a field",
                        "content": "Imagine a batch of records in 'file.dat' that you'd like to add local notes (590) to, then\nsaving your changes:\n\n1   ## Example U1\n2\n3   ## create our MARC::Batch object.\n4   use MARC::Batch;\n5   my $batch = MARC::Batch->new('USMARC','file.dat');\n6\n7   ## open a file handle to write to.\n8   open(OUT,'>new.dat') or die $!;\n9\n10   ## read each record, modify, then print.\n11   while ( my $record = $batch->next() ) {\n12\n13       ## add a 590 field.\n14       $record->appendfields(\n15          MARC::Field->new('590','','',a=>'Access provided by Enron.')\n16       );\n17\n18       print OUT $record->asusmarc();\n19\n20   }\n21\n22   close(OUT);\n"
                    },
                    {
                        "name": "Preserving field order",
                        "content": "As its name suggests, \"appendfields()\" will add the 590 field in recipe U1 to the end of the\nrecord. If you want to preserve a particular order, you can use the \"insertfieldsbefore()\" and\n\"insertfieldsafter()\" methods. In order to use these, you need to locate the field you want to\ninsert before or after. Here is an example (\"insertfieldsafter()\" works similarly):\n\n1   ## Example U2\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC','file.dat');\n5   open(OUT,'>new.dat') or die $!;\n6\n7   ## read in each record.\n8   while ( my $record = $batch->next() ) {\n9\n10       ## find the tag after 590.\n11       my $before;\n12       foreach ($record->fields()) {\n13           $before = $;\n14           last if $->tag() > 590;\n15       }\n16\n17       ## create the 590 field.\n18       my $new = MARC::Field->new('590','','',a=>'Access provided by Enron.');\n19\n20       ## insert our 590 field after the $before.\n21       $record->insertfieldsbefore($before,$new);\n22\n23       ## and print out the new record.\n24       print OUT $record->asusmarc();\n25\n26   }\n"
                    },
                    {
                        "name": "Deleting a field",
                        "content": "You can also delete fields that you don't want. But you will probably want to check that the\nfield contains what you expect before deleting it. Let's say Enron has gone out of business and\nthe 590 field needs to be deleted:\n\n1   ## Example U3\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC','new.dat');\n5   open(OUT,'>newer.dat') or die $1;\n6\n7   while ( my $record = $batch->next() ) {\n8\n9     ## get the 590 record.\n10     my $field = $record->field('590');\n11\n12     ## if there is a 590 AND it has the word \"Enron\"...\n13     if ($field and $field->asstring() =~ /Enron/i) {\n14\n15       ## delete it!\n16       $record->deletefield($field);\n17\n18     }\n19\n20     ## output possibly modified record.\n21     print OUT $record->asusmarc();\n22\n23   }\n\nThe 590 field is retrieved on line 10, but notice how we check that we actually received a valid\n$field, and that it then contains the word 'Enron' before we delete it. You need to pass\n\"deletefield()\" a MARC::Field object that can be retrieved with the \"field()\" method.\n"
                    },
                    {
                        "name": "Changing existing fields",
                        "content": "Perhaps rather than adding or deleting a field, you need to modify an existing field. This is\nachieved in several steps: first, read in the MARC record you want to update, and then the field\nyou're interested in. From there, call the field's \"update\" or \"replacewith\" methods to modify\nits contents, and then resave the record. Below is an example of updating existing 590 field's\ncontaining the word 'Enron' to indicate that access is now provided through Arthur Andersen:\n\n1   ## Example U4\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC','new.dat');\n5   open(OUT,'>newer.dat') or die $1;\n6\n7   while ( my $record = $batch->next() ) {\n8\n9     ## look for a 590 containing \"Enron\"...\n10     my $field = $record->field('590');\n11     if ($field and $field->asstring =~ /Enron/i) {\n12\n13       ## create a new 590 field.\n14       my $newfield = MARC::Field->new(\n15         '590','','', a => 'Access provided by Arthur Andersen.' );\n16\n17       ## replace existing with our new one.\n18       $field->replacewith($newfield);\n19\n20     }\n21\n22     ## output possibly modified record.\n23     print OUT $record->asusmarc();\n24\n25   }\n\nIn this example, we used MARC::Field's method \"replacewith()\" to replace an existing field in\nthe record with a new field that we created. To use \"replacewith()\", you need to retrieve the\nfield you want to replace from a MARC::Record object (line 10), create a new field to replace\nthe existing one with (lines 13-15), and then call the existing field's \"replacewith()\" method\npassing the new field as an argument (lines 18). You must pass \"replacewith()\" a valid\nMARC::Field object.\n"
                    },
                    {
                        "name": "Updating subfields and indicators",
                        "content": "If you'd rather not replace an existing field with a new one, you can also edit the contents of\nthe field itself using the \"update()\" method. Let's say you've got a batch of records and want\nto make sure that the 2nd indicator for the 245 field is properly set for titles that begin with\n'The' (where the indicator should be '4').\n\n1   ## Example U5\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC','file.dat');\n5   open(OUT,'>new.dat') or die $!;\n6\n7   while (my $record = $batch->next()) {\n8\n9     ## retrieve the 245 record.\n10     my $field245 = $record->field('245');\n11\n12     ## if we got 245 and it starts with 'The'...\n13     if ($field245 and $field245->asstring() =~ /^The /) {\n14\n15       ## if the 2nd indicator isn't 4, update\n16       if ($field245->indicator(2) != 4) {\n17         $field245->update( ind2 => 4 );\n18       }\n19\n20     }\n21\n22     print OUT $record->asusmarc();\n23\n24   }\n\nIn a similar fashion, you can update individual or multiple subfields:\n\n$field245->update( a => 'History of the World :', b => 'part 1' );\n\nBut beware, you can only update the first occurrence of a subfield using \"update()\". If you need\nto do more finer grained updates, you are advised to build a new field and replace the existing\nfield with \"replacewith()\".\n"
                    },
                    {
                        "name": "Changing a record's leader",
                        "content": "The above procedure works for fields, but editing the leader requires that you use the\n\"leader()\" method. When called with no arguments, \"leader()\" will return the current leader, and\nwhen you pass a scalar value as an argument, the leader will be set to this value. This example\nshows how you might want to update position 6 of a records leader to reflect a computer file.\n\n1   ## Example U6\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC','file.dat');\n5   open(OUT,'>new.dat') or die $!;\n6   my $record = $batch->next();\n7\n8   ## get the current leader.\n9   my $leader = $record->leader();\n10\n11   ## replace position 6 with 'm'\n12   substr($leader,6,1) = 'm';\n13\n14   ## update the leader\n15   $record->leader($leader);\n16\n17   ## save the record to a file\n18   print OUT $record->asusmarc();\n"
                    },
                    {
                        "name": "Modifying fields without indicators",
                        "content": "MARC::Record and MARC::Field are smart and know that you don't have field indicators with tags\nless than 010. Here's an example of updating/adding an 005 field to indicate a new transaction\ntime. For a little pizzazz, we use Perl's \"localtime()\" to generate the data we need for this\nfield.\n\n1   ## Example U7\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC','file.dat');\n5   open(OUT,'>new.dat') or die $!;\n6\n7   while (my $record = $batch->next() ) {\n8\n9     ## see if there is a 005 field.\n10     my $field005 = $record->field('005');\n11\n12     ## delete it if we find one.\n13     $record->deletefield($field005) if $field005;\n14\n15     ## figure out the contents of our new 005 field.\n16     my ($sec,$min,$hour,$mday,$mon,$year) = localtime();\n17     $year += 1900; $mon += 1; # catering to offsets.\n18     my $datetime = sprintf(\"%4d%02d%02d%02d%02d%02d.0\",\n19                             $year,$mon,$mday,$hour,$min,$sec);\n20\n21     ## create a new 005 field using our new datetime.\n22     $record->appendfields( MARC::Field->new('005',$datetime) );\n23\n24     ## save record to a file.\n25     print OUT $record->asusmarc();\n26\n27   }\n"
                    },
                    {
                        "name": "Reordering subfields",
                        "content": "You may find yourself in the situation where you would like to programmatically reorder, and\npossibly modify, subfields in a particular field. For example, imagine that you have a batch of\nrecords that have 856 fields which contain subfields z, u, and possibly 3... in any order! Now\nimagine that you'd like to standardize the subfield z, and reorder them so that subfield 3\nprecedes subfield z, which precedes subfield u. This is tricky but can be done in the following\nmanner: read in a record, extract the existing 856 field, build a new 856 field based on the\nexisting one, replace the existing field with your newly created version.\n\n1   ## Example U8\n2\n3   use MARC::Batch;\n4   my $batch = MARC::Batch->new('USMARC','856.dat');\n5   open(OUT,'>856new.dat') or die $!;\n6\n7   while (my $record = $batch->next()) {\n8\n9     my $existing = $record->field('856');\n10\n11     ## make sure 856 exists.\n12     if ($existing) {\n13\n14       ## our ordered subfields.\n15       my @subfields = ();\n16\n17       ## if we have a subfield 3, add it.\n18       if (defined($existing->subfield('3'))) {\n19         push(@subfields,'3',$existing->subfield('3'));\n20       }\n21\n22       ## now add subfields z and u.\n23       push(@subfields,'z','Access restricted',\n24         'u',$existing->subfield('u'));\n25\n26       ## create a new 856.\n27       my $new = MARC::Field->new(\n28          856', $existing->indicator(1),\n29          $existing->indicator(2), @subfields\n30       );\n31\n32       ## replace the existing subfield.\n33       $existing->replacewith($new);\n34\n35     }\n36\n37     ## write out the record\n38     print OUT $record->asusmarc();\n39\n40   }\n"
                    },
                    {
                        "name": "Updating subject subfield x to subfield v",
                        "content": "As a somewhat more complicated example, you may find yourself wanting to update the last\nsubfield x in a 650 field to be a subfield v instead. With the MARC::Field \"subfields()\" and\n\"replacewith()\" methods along with some fancy footwork this can be done relatively easily.\n\n1  ## Example U9\n2\n3  use MARC::Batch;\n4\n5  my $file = shift;\n6\n7  my $batch = MARC::Batch->new('USMARC', $file);\n8  while ( my $record = $batch->next() ) {\n9\n10    # go through all 6XX fields in the record.\n11    foreach my $subject ( $record->field( '6..' ) ) {\n12\n13      # extract subfields as an array of array refs.\n14      my @subfields = $subject->subfields();\n15\n16      # setup an array to store our new field.\n17      my @newSubfields = ();\n18\n19      # a flag to indicate that we found an subfield x.\n20      my $foundX = 0;\n21\n22      # use pop() to read the subfields backwards.\n23      while ( my $subfield = pop( @subfields ) ) {\n24\n25        # for convenience, pull out the subfield\n26        # code and data from  the array ref.\n27        my ($code,$data) = @$subfield;\n28\n29        # if the subfield code is 'x' and\n30        # we haven't already found one...\n31        if ( $code eq 'x' and ! $foundX ) {\n32\n33          # change to a v.\n34          $code = 'v';\n35\n36          # set flag so we know not to\n37          # translate any more subfield x.\n38          $foundX = 1;\n39\n40        }\n41\n42        # add our (potentially changed) subfield\n43        # data to our new subfield data array.\n44        unshift( @newSubfields, $code, $data );\n45\n46      }\n47\n48      # if we did find a subfield x, then create a new field using our\n49      # new subfield data, and replace the old one with the new one.\n50      if ( $foundX ) {\n51        my $newSubject = MARC::Field->new(\n52          $subject->tag(),\n53          $subject->indicator(1),\n54          $subject->indicator(2),\n55          @newSubfields\n56        );\n57        $subject->replacewith( $newSubject );\n58      }\n59\n60    }\n61\n62    # output the potentially changed record as MARC.\n63    print $record->asusmarc();\n64\n65  }\n"
                    }
                ]
            },
            "VALIDATING": {
                "content": "MARC::Lint, available on CPAN and in cvs on SourceForge, has some extra goodies to allow you to\nvalidate records. MARC::Lint provides an extensive battery of tests, and it also provides a\nframework for adding more.\n",
                "subsections": [
                    {
                        "name": "Using MARC::Lint",
                        "content": "Here is an example of using MARC::Lint to generate a list of errors present in a batch of\nrecords in a file named 'file.dat':\n\n1   ## Example V1\n2\n3   use MARC::Batch;\n4   use MARC::Lint;\n5\n6   my $batch = MARC::Batch->new('USMARC','file.dat');\n7   my $linter = MARC::Lint->new();\n8   my $counter = 0;\n9\n10   while (my $record = $batch->next() ) {\n11\n12     $counter++;\n13\n14     ## feed the record to our linter object.\n15     $linter->checkrecord($record);\n16\n17     ## get the warnings...\n18     my @warnings = $linter->warnings();\n19\n20     ## output any warnings.\n21     if (@warnings) {\n22\n23       print \"RECORD $counter\\n\";\n24       print join(\"\\n\",@warnings),\"\\n\";\n25\n26     }\n27\n28   }\n\nMARC::Lint is quite thorough, and will check the following when validating: presence of a 245\nfield, repeatability of fields and subfields, valid use of subfield within particular fields,\npresence of indicators and their values. All checks are based on MARC21 bibliographic format.\n"
                    },
                    {
                        "name": "Customizing MARC::Lint",
                        "content": "MARC::Lint makes no claim to check everything that might be wrong with a MARC record. In\npractice, individual libraries may have their own idea about what is valid or invalid. For\nexample, a library may mandate that all MARC records with an 856 field should have a subfield z\nthat reads \"Connect to this resource\".\n\nMARC::Lint does provide a framework for adding rules. It can be done using the object oriented\nprogramming technique of inheritance. In short, you can create your own subclass of MARC::Lint,\nand then use it to validate your records. Here's an example:\n\n1   ## Example V2\n2\n3   ## first, create our own subclass of MARC::Lint.\n4   ## should be saved in a file called MyLint.pm.\n5\n6   package MyLint;\n7   use base qw(MARC::Lint);\n8\n9   ## add a method to check that the 856\n10   ## fields contain a correct subfield z.\n11   sub check856 {\n12\n13     ## your method is passed the MARC::Lint\n14     ## and MARC::Field objects for the record.\n15     my ($self,$field) = @;\n16\n17     if ($field->subfield('z') ne 'Connect to this resource') {\n18\n19       ## add a warning to our lint object.\n20       $self->warn(\"856 subfield z must read 'Connect to this resource'.\");\n21\n22     }\n23\n24   }\n\nThen create a separate program that uses your subclass to validate your MARC records. You'll\nneed to make sure your program is able to find your module (in this case, MyLint.pm)... this can\nbe achieved by putting both MyLint.pm and the following program in the same directory:\n\n1   ## Example V3\n2\n3   use MARC::Batch;\n4   use MyLint;\n5\n6   my $linter = MyLint->new();\n7   my $batch = MARC::Batch->new('USMARC','file.marc');\n8   my $counter = 0;\n9\n10   while (my $record = $batch->next()) {\n11\n12     $counter++;\n13\n14     ## check the record\n15     $linter->checkrecord($record);\n16\n17     ## get the warnings, and print them out\n18     my @warnings = $linter->warnings();\n19     if (@warnings) {\n20       print \"RECORD $counter\\n\";\n21       print join(\"\\n\",@warnings),\"\\n\";\n22     }\n23\n24   }\n\nNotice how the call to \"checkrecord()\" at line 15 automatically calls the \"checkrecord\" in\nMARC::Lint. The property of inheritance is what makes this happen. $linter is an instance of the\nMyLint class, and MyLint inherits from the MARC::Lint class, which allows $linter to inherit all\nthe functionality of a normal MARC::Lint object plus the new functionality found in the\n\"check856\" method.\n\nNotice also that we don't have to call \"check856()\" directly. The call to \"checkrecord()\"\nautomatically looks for any \"checkXXX\" methods that it can call to verify the record. Pretty\nneat stuff. If you've added validation checks that you think could be of use to the general\npublic, please share them on the perl4lib mailing list, or become a developer and add them to\nthe source!\n"
                    }
                ]
            },
            "SWOLLEN APPENDICES": {
                "content": "Brian Eno fans might catch this reference to his autobiography which was comprised of a years\nworth of diary entries plus extra topics at the end, and was entitled \"A Year With Swollen\nAppendices\". The following section is a grab bag group of appendices. Many of them are not\nfilled in yet; this is because they are just ideas... so perhaps the appendices aren't that\nswollen yet. Feel free to suggest new ones, or to fill these in.\n",
                "subsections": [
                    {
                        "name": "Comparing Collections",
                        "content": ""
                    },
                    {
                        "name": "Authority Records",
                        "content": "URLs\nISBN/ISSNs"
                    },
                    {
                        "name": "Call numbers",
                        "content": ""
                    },
                    {
                        "name": "Subject headings",
                        "content": "Suppose you have a batch of MARC records and you want to extract all the subject headings,\ngenerating a report of how many times each subject heading appeared in the batch:\n\n1   use MARC::File::USMARC;\n2   use constant MAX => 20;\n3\n4   my %counts;\n5\n6   my $filename = shift or die \"Must specify filename\\n\";\n7   my $file = MARC::File::USMARC->in( $filename );\n8\n9   while ( my $marc = $file->next() ) {\n10       for my $field ( $marc->field(\"6..\") ) {\n11           my $heading = $field->subfield('a');\n12\n13           # trailing whitespace / punctuation.\n14           $heading =~ s/[.,]?\\s*$//;\n15\n16           # Now count it.\n17           ++$counts{$heading};\n18       }\n19   }\n20   $file->close();\n21\n22   # Sort the list of headings based on the count of each.\n23   my @headings = reverse sort { $counts{$a} <=> $counts{$b} } keys %counts;\n24\n25   # Take the top N hits...\n26   @headings = @headings[0..MAX-1];\n27\n28   # And print out the results.\n29   for my $heading ( @headings ) {\n30       printf( \"%5d %s\\n\", $counts{$heading}, $heading );\n31   }\n\nWhich will generate results like this:\n\n600 United States\n140 World War, 1939-1945\n78 Great Britain\n63 Afro-Americans\n61 Indians of North America\n58 American poetry\n55 France\n53 West (U.S.)\n53 Science fiction\n53 American literature\n50 Shakespeare, William\n48 Soviet Union\n46 Mystery and detective stories\n45 Presidents\n43 China\n40 Frontier and pioneer life\n38 English poetry\n37 Authors, American\n37 English language\n35 Japan\n\nHTML\nXML\nMARCMaker\nMARC::File::MARCMaker, available on CPAN and in cvs on SourceForge, is a subclass of MARC::File\nfor working with MARC 21 data encoded in the format used by the Library of Congress MARCMaker\nand MARCBreaker programs (<http://www.loc.gov/marc/makrbrkr.html>) and MarcEdit ().\n\nAn example of a brief record in this format:\n\n=LDR  00314nam  22001215a 4500\n=001  ctr00000123\\\n=003  XX-XxUND\n=005  20000613133448.0\n=008  051029s2005\\\\\\\\xxua\\\\\\\\\\\\\\\\\\\\001\\0\\eng\\\\\n=040  \\\\$aXX-XxUND$cXX-XxUND\n=245  00$aSample of MARCMaker record.\n=260  \\\\$a[United States] :$b[S.n.],$c2005.\n=300  \\\\$a1 p. ;$c28 cm.\n\nThe following example converts an ISO2709 format record into MARCMaker format.\n\n1    ## Example Maker1\n2\n3    use MARC::Batch;\n4    use MARC::File::MARCMaker;\n5\n6    #mrc indicates ISO2709 format\n7    my $mrcin = 'in.mrc';\n8    #mrk indicates MARCMaker format\n9    my $mrkout = 'out.mrk';\n10\n11   #initialize $batchmrc as new MARC::Batch object\n12   my $batchmrc = MARC::Batch->new('USMARC', $mrcin);\n13\n14   #open mrk (MARCMaker) format output file\n15   open (OUTMRK, \">$mrkout\") || die \"Cannot open $mrkout, $!\";\n16\n17   my $reccount = 0;\n18   while (my $record = $batchmrc->next()) {\n19      $reccount++;\n20\n21      print OUTMRK MARC::File::MARCMaker->encode($record);\n22\n23   } # while\n24\n25   print \"$reccount records processed\\n\";\n\nThe following example shows conversion from MARCMaker format to ISO2709 format.\n\n1    ## Example Maker2\n2\n3    use MARC::Batch;\n4    use MARC::File::MARCMaker;\n5\n6    #mrk indicates MARCMaker format\n7    my $mrkin = 'in.mrk';\n8    #mrc indicates ISO2709 format\n9    my $mrcout = 'out.mrc';\n10\n11   #initialize $batchmrk as new MARC::Batch object\n12   my $batchmrk = MARC::Batch->new( 'MARCMaker', $mrkin);\n13\n14   #open mrc (ISO2709) format output file\n15   open (OUTMRC, \">$mrcout\") || die \"Cannot open $mrcout, $!\";\n16\n17   my $reccount = 0;\n18   while (my $record = $batchmrk->next()) {\n19      $reccount++;\n20\n21      print OUTMRC $record->asusmarc();\n22\n23   } # while\n24\n25   print \"$reccount records processed\\n\";\n"
                    },
                    {
                        "name": "Excel",
                        "content": "Z39.50\nChris Biemesderfer was kind enough to contribute a short example of how to use MARC::Record in\ntandem with Net::Z3950. Net::Z3950 is a CPAN module which provides an easy to use interface to\nthe Z39.50 protocol so that you can write programs that retrieve records from bibliographic\ndatabase around the world.\n\nChris' program is a command line utility which you run like so:\n\n./zm.pl 0596000278\n\nwhere 0596000278 is an ISBN (for the 3rd edition of the Camel incidentally). The program will\nquery the Library of Congress Z39.50 server for the ISBN, and dump out the retrieved MARC record\non the screen. The program is designed to lookup multiple ISBNs if you separate them with a\nspace. This is just an example showing what is possible.\n\n1   #!/usr/bin/perl -w\n2\n3   # GET-MARC-ISBN -- Get MARC records by ISBN from a Z39.50 server\n4\n5   use strict;\n6   use Carp;\n7   use Net::Z3950;\n8   use MARC::Record;\n9\n10   exit if ($#ARGV < 0);\n11\n12   # We handle multiple ISBNs in the same query by assembling a\n13   # (potentially very large) search string with Prefix Query Notation\n14   # that ORs the ISBN-bearing attributes.\n15   #\n16   # For purposes of automation, we want to request batches of many MARC\n17   # records.  I am not a Z39.50 weenie, though, and I don't know\n18   # offhand if there is a limit on how big a PQN query can be...\n19\n20   my $zq = \"\\@attr 1=7 \". pop();\n21   while (@ARGV) { $zq = '@or @attr 1=7 '. pop() .\" $zq\" }\n22\n23   ## HERE IS THE CODE FOR Z3950 REC RETRIEVAL\n24   # Set up connection management structures, connect\n25   # to the server, and submit the Z39.50 query.\n26\n27   my $mgr = Net::Z3950::Manager->new( databaseName => 'voyager' );\n28   $mgr->option( elementSetName => \"f\" );\n29   $mgr->option( preferredRecordSyntax => Net::Z3950::RecordSyntax::USMARC );\n30\n31   my $conn = $mgr->connect('z3950.loc.gov', '7090');\n32   croak \"Unable to connect to server\" if !defined($conn);\n33\n34   my $rs = $conn->search($zq);\n35\n36   my $numrec = $rs->size();\n37   print STDERR \"$numrec record(s) found\\n\";\n38\n39   for (my $ii = 1; $ii <= $numrec; $ii++) {\n40\n41       # Extract MARC records from Z3950\n42       # result set, and load MARC::Record.\n43       my $zrec = $rs->record($ii);\n44       my $mrec = MARC::Record->newfromusmarc($zrec->rawdata());\n45       print $mrec->asformatted, \"\\n\\n\";\n46\n47   }\n"
                    },
                    {
                        "name": "Databases",
                        "content": "Here's a script that will do a Z39.50 query (using Chris Biemesderfer's zm.pl as a model), get a\nMARC record back, and store it as a binary blob in a MySQL table of this structure:\n\n+---------------+---------------+------+-----+---------+----------------+\n| Field         | Type          | Null | Key | Default | Extra          |\n+---------------+---------------+------+-----+---------+----------------+\n| TitleID       | int(7)        |      | PRI | NULL    | autoincrement |\n| RecLastMod    | timestamp(14) | YES  |     | NULL    |                |\n| ISSN          | text          | YES  |     | NULL    |                |\n| RawMARCRecord | blob          | YES  |     | NULL    |                |\n+---------------+---------------+------+-----+---------+----------------+\n\n1 #!/usr/bin/perl -w\n2\n3 # Script that reads in a file of ISSNs, queries a Z39.50 server,\n4 # and stores resulting records in a database. Limitations: Only\n5 # stores 1 records per ISSN.\n6 # Last updated 2004-09-08 Mark Jordan, mjordan@sfu.ca\n7\n8 use strict;\n9 use Carp;\n10 use Net::Z3950;\n11 use MARC::Record;\n12 use DBI;\n13\n14 # DB connection settings\n15 my $host = \"somehost\";\n16 my $user = \"someuser\";\n17 my $password = \"somepass\";\n18 my $database = \"somedb\";\n19\n20 # Input file (one ISSS/line)\n21 my $InputFile = $ARGV[0];\n22\n23 # Prepare list of ISSNs to search\n24 my @ISSNs;\n25 open (INPUT, \"< $InputFile\") or die \"Can't find input file\\n\";\n26 while (<INPUT>) { chomp $; push (@ISSNs, $); }\n27 close INPUT;\n28\n29\n30 # Set up connection management structures, connect to the server,\n31 # and submit the Z39.50 query.\n32 my $mgr = Net::Z3950::Manager->new( databaseName => 'voyager' );\n33 $mgr->option( elementSetName => \"f\" );\n34 $mgr->option( preferredRecordSyntax => Net::Z3950::RecordSyntax::USMARC );\n35 my $conn = $mgr->connect('z3950.loc.gov', '7090');\n36 croak \"Unable to connect to server\" if !defined($conn);\n37\n38\n39 my $handle = DBI->connect(\"DBI:mysql:$database:$host\",\"$user\",\"$password\")\n40         or die $DBI::errstr;\n41\n42 foreach my $ISSN (@ISSNs) {\n43         my $zq = \"\\@attr 1=8 \". $ISSN;\n44         my $rs = $conn->search($zq);\n45         my $numrec = $rs->size();\n46         if ($numrec == 0) {\n47             print \"Record for ISSN $ISSN not found, moving to next ISSN...\\n\";\n48             next;\n49         } else {\n50            # Extract MARC record from the result set, and invoke MARC::Record\n51            my $zrec = $rs->record(1);\n52            my $mrec = MARC::Record->newfromusmarc($zrec->rawdata());\n53            my $rawdata = $zrec->rawdata();\n54            $rawdata = $handle->quote ($rawdata);\n55            # Add to db\n56            my $SQL = \"insert into Titles values (NULL,NULL,'$ISSN',$rawdata)\";\n57            my $cursor = $handle->prepare($SQL);\n58            $cursor->execute;\n59            print \"Record for ISSN $ISSN added to database...\\n\";\n60            $cursor->finish;\n61         }\n62 }\n63 $handle->disconnect;\n64\n65 END\n\nIf you want to pull records out of the same database and do something with them, here's a\ntemplate script:\n\n1 #!/usr/bin/perl -w\n2\n3 # Script that gets MARC records (in blobs) from a database.\n4 # Last updated 2004-09-08 Mark Jordan, mjordan@sfu.ca\n5\n6 use strict;\n7 use MARC::Record;\n8 use DBI;\n9\n10 # DB connection settings\n11 my $mysqlhost = \"somehost\";\n12 my $mysqluser = \"someuser\";\n13 my $mysqlpassword = \"somepass*\";\n14 my $mysqldatabase = \"somedb\";\n15\n16\n17 my $handle = DBI->connect(\"DBI:mysql:$mysqldatabase:$mysqlhost\",\n18         \"$mysqluser\",\"$mysqlpassword\") or die $DBI::errstr;\n19\n20 my $SQL = \"select * from Titles\";\n21 my $cursor = $handle->prepare($SQL);\n22 $cursor->execute;\n23\n24 while (my @Records = $cursor->fetchrowarray) {\n25         my $RawMARC = $Records[3];\n26         my $mrec = MARC::Record->newfromusmarc($RawMARC);\n27         # Print out the title\n28         print $mrec->title , \"\\n\";\n29 }\n30\n31 $cursor->finish;\n32 $handle->disconnect;\n33\n34 END\n\nProcite/Endnote"
                    }
                ]
            },
            "CONTRIBUTORS": {
                "content": "Many thanks to all the contributors who have made this document possible.\n\n*   Bryan Baldus <eijabb@cpan.org>\n\n*   Chris Biemesderfer <chris@seagoat.com>\n\n*   Morbus Iff <morbus@disobey.com>\n\n*   Mark Jordan <mjordan@sfu.ca>\n\n*   Andy Lester <andy@petdance.com>\n\n*   Christopher Morgan <morgan@acm.org>\n\n*   Shashi Pinheiro <SPinheiro@utsa.edu>\n\n*   Jackie Shieh <jshieh@umich.edu>\n\n*   Ed Summers <ehs@pobox.com>\n",
                "subsections": []
            }
        }
    }
}