Blame bibutils/modsout.c

Packit 89ede9
/*
Packit 89ede9
 * modsout.c
Packit 89ede9
 *
Packit 89ede9
 * Copyright (c) Chris Putnam 2003-2018
Packit 89ede9
 *
Packit 89ede9
 * Source code released under the GPL version 2
Packit 89ede9
 *
Packit 89ede9
 */
Packit 89ede9
#include <stdio.h>
Packit 89ede9
#include <stdlib.h>
Packit 89ede9
#include <stdarg.h>
Packit 89ede9
#include <string.h>
Packit 89ede9
#include "is_ws.h"
Packit 89ede9
#include "str.h"
Packit 89ede9
#include "charsets.h"
Packit 89ede9
#include "str_conv.h"
Packit 89ede9
#include "fields.h"
Packit 89ede9
#include "iso639_2.h"
Packit 89ede9
#include "utf8.h"
Packit 89ede9
#include "modstypes.h"
Packit 89ede9
#include "bu_auth.h"
Packit 89ede9
#include "marc_auth.h"
Packit 89ede9
#include "bibformats.h"
Packit 89ede9
Packit 89ede9
static void modsout_writeheader( FILE *outptr, param *p );
Packit 89ede9
static void modsout_writefooter( FILE *outptr );
Packit 89ede9
static int  modsout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs );
Packit 89ede9
Packit 89ede9
void
Packit 89ede9
modsout_initparams( param *p, const char *progname )
Packit 89ede9
{
Packit 89ede9
	p->writeformat      = BIBL_MODSOUT;
Packit 89ede9
	p->format_opts      = 0;
Packit 89ede9
	p->charsetout       = BIBL_CHARSET_UNICODE;
Packit 89ede9
	p->charsetout_src   = BIBL_SRC_DEFAULT;
Packit 89ede9
	p->latexout         = 0;
Packit 89ede9
	p->utf8out          = 1;
Packit 89ede9
	p->utf8bom          = 1;
Packit 89ede9
	p->xmlout           = BIBL_XMLOUT_TRUE;
Packit 89ede9
	p->nosplittitle     = 0;
Packit 89ede9
	p->verbose          = 0;
Packit 89ede9
	p->addcount         = 0;
Packit 89ede9
	p->singlerefperfile = 0;
Packit 89ede9
Packit 89ede9
	p->headerf = modsout_writeheader;
Packit 89ede9
	p->footerf = modsout_writefooter;
Packit 89ede9
	p->writef  = modsout_write;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* output_tag()
Packit 89ede9
 *
Packit 89ede9
 * mode = TAG_OPEN,         "<tag>"
Packit 89ede9
 * mode = TAG_CLOSE,        "</tag>"
Packit 89ede9
 * mode = TAG_OPENCLOSE,    "<tag>data</tag>"
Packit 89ede9
 * mode = TAG_SELFCLOSE,    "<tag/>"
Packit 89ede9
 *
Packit 89ede9
 * newline = TAG_NONEWLINE, "<tag>"
Packit 89ede9
 * newline = TAG_NEWLINE,   "<tag>\n"
Packit 89ede9
 *
Packit 89ede9
 */
Packit 89ede9
#define TAG_OPEN      (0)
Packit 89ede9
#define TAG_CLOSE     (1)
Packit 89ede9
#define TAG_OPENCLOSE (2)
Packit 89ede9
#define TAG_SELFCLOSE (3)
Packit 89ede9
Packit 89ede9
#define TAG_NONEWLINE (0)
Packit 89ede9
#define TAG_NEWLINE   (1)
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_tag_core( FILE *outptr, int nindents, char *tag, char *data, unsigned char mode, unsigned char newline, va_list *attrs )
Packit 89ede9
{
Packit 89ede9
	char *attr, *val;
Packit 89ede9
	int i;
Packit 89ede9
Packit 89ede9
	for ( i=0; i
Packit 89ede9
Packit 89ede9
	if ( mode!=TAG_CLOSE )
Packit 89ede9
		fprintf( outptr, "<" );
Packit 89ede9
	else
Packit 89ede9
		fprintf( outptr, "</" );
Packit 89ede9
Packit 89ede9
	fprintf( outptr, "%s", tag );
Packit 89ede9
Packit 89ede9
	do {
Packit 89ede9
		attr = va_arg( *attrs, char * );
Packit 89ede9
		if ( attr ) val  = va_arg( *attrs, char * );
Packit 89ede9
		if ( attr && val )
Packit 89ede9
			fprintf( outptr, " %s=\"%s\"", attr, val );
Packit 89ede9
	} while ( attr && val );
Packit 89ede9
Packit 89ede9
	if ( mode!=TAG_SELFCLOSE )
Packit 89ede9
		fprintf( outptr, ">" );
Packit 89ede9
	else
Packit 89ede9
		fprintf( outptr, "/>" );
Packit 89ede9
Packit 89ede9
	if ( mode==TAG_OPENCLOSE ) {
Packit 89ede9
		fprintf( outptr, "%s</%s>", data, tag );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( newline==TAG_NEWLINE )
Packit 89ede9
		fprintf( outptr, "\n" );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* output_tag()
Packit 89ede9
 *
Packit 89ede9
 *     output XML tag
Packit 89ede9
 *
Packit 89ede9
 * mode     = [ TAG_OPEN | TAG_CLOSE | TAG_OPENCLOSE | TAG_SELFCLOSE ]
Packit 89ede9
 * newline  = [ TAG_NEWLINE | TAG_NONEWLINE ]
Packit 89ede9
 *
Packit 89ede9
 * for mode TAG_OPENCLOSE, ensure that value is non-NULL, as string pointed to by value
Packit 89ede9
 * will be output in the tag
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
output_tag( FILE *outptr, int nindents, char *tag, char *value, unsigned char mode, unsigned char newline, ... )
Packit 89ede9
{
Packit 89ede9
	va_list attrs;
Packit 89ede9
Packit 89ede9
	va_start( attrs, newline );
Packit 89ede9
	output_tag_core( outptr, nindents, tag, value, mode, newline, &attrs );
Packit 89ede9
	va_end( attrs );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* output_fil()
Packit 89ede9
 *
Packit 89ede9
 *     output XML tag, but lookup data in fields struct
Packit 89ede9
 *
Packit 89ede9
 * mode     = [ TAG_OPEN | TAG_CLOSE | TAG_OPENCLOSE | TAG_SELFCLOSE ]
Packit 89ede9
 * newline  = [ TAG_NEWLINE | TAG_NONEWLINE ]
Packit 89ede9
 *
Packit 89ede9
 * value looked up in fields will only be used in mode TAG_OPENCLOSE
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
output_fil( FILE *outptr, int nindents, char *tag, fields *f, int n, unsigned char mode, unsigned char newline, ... )
Packit 89ede9
{
Packit 89ede9
	va_list attrs;
Packit 89ede9
	char *value;
Packit 89ede9
Packit 89ede9
	if ( n!=-1 ) {
Packit 89ede9
		value = (char *) fields_value( f, n, FIELDS_CHRP );
Packit 89ede9
		va_start( attrs, newline );
Packit 89ede9
		output_tag_core( outptr, nindents, tag, value, mode, newline, &attrs );
Packit 89ede9
		va_end( attrs );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static inline int
Packit 89ede9
lvl2indent( int level )
Packit 89ede9
{
Packit 89ede9
	if ( level < -1 ) return -level + 1;
Packit 89ede9
	else return level + 1;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static inline int
Packit 89ede9
incr_level( int level, int amt )
Packit 89ede9
{
Packit 89ede9
	if ( level > -1 ) return level+amt;
Packit 89ede9
	else return level-amt;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* convert_findallfields()
Packit 89ede9
 *
Packit 89ede9
 *       Find the positions of all convert.internal tags in the fields
Packit 89ede9
 *       structure and store the locations in convert.pos element.
Packit 89ede9
 *
Packit 89ede9
 *       Return number of the tags found.
Packit 89ede9
 */
Packit 89ede9
static int
Packit 89ede9
convert_findallfields( fields *f, convert *parts, int nparts, int level )
Packit 89ede9
{
Packit 89ede9
	int i, n = 0;
Packit 89ede9
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		parts[i].pos = fields_find( f, parts[i].internal, level );
Packit 89ede9
		n += ( parts[i].pos!=FIELDS_NOTFOUND );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	return n;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_title( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	int ttl    = fields_find( f, "TITLE", level );
Packit 89ede9
	int subttl = fields_find( f, "SUBTITLE", level );
Packit 89ede9
	int shrttl = fields_find( f, "SHORTTITLE", level );
Packit 89ede9
	int parttl = fields_find( f, "PARTTITLE", level );
Packit 89ede9
	char *val;
Packit 89ede9
Packit 89ede9
	output_tag( outptr, lvl2indent(level),               "titleInfo", NULL,      TAG_OPEN,      TAG_NEWLINE, NULL );
Packit 89ede9
	output_fil( outptr, lvl2indent(incr_level(level,1)), "title",     f, ttl,    TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	output_fil( outptr, lvl2indent(incr_level(level,1)), "subTitle",  f, subttl, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	output_fil( outptr, lvl2indent(incr_level(level,1)), "partName",  f, parttl, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	/* MODS output doesn't verify if we don't at least have a <title/> element */
Packit 89ede9
	if ( ttl==-1 && subttl==-1 )
Packit 89ede9
		output_tag( outptr, lvl2indent(incr_level(level,1)), "title", NULL,  TAG_SELFCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	output_tag( outptr, lvl2indent(level),               "titleInfo", NULL,      TAG_CLOSE,     TAG_NEWLINE, NULL );
Packit 89ede9
Packit 89ede9
	/* output shorttitle if it's different from normal title */
Packit 89ede9
	if ( shrttl!=FIELDS_NOTFOUND ) {
Packit 89ede9
		val = (char *) fields_value( f, shrttl, FIELDS_CHRP );
Packit 89ede9
		if ( ttl==FIELDS_NOTFOUND || subttl!=FIELDS_NOTFOUND || strcmp(f->data[ttl].data,val) ) {
Packit 89ede9
			output_tag( outptr, lvl2indent(level),               "titleInfo", NULL, TAG_OPEN,      TAG_NEWLINE, "type", "abbreviated", NULL );
Packit 89ede9
			output_tag( outptr, lvl2indent(incr_level(level,1)), "title",     val,  TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
			output_tag( outptr, lvl2indent(level),               "titleInfo", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
Packit 89ede9
		}
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_name( FILE *outptr, char *p, int level )
Packit 89ede9
{
Packit 89ede9
	str family, part, suffix;
Packit 89ede9
	int n=0;
Packit 89ede9
Packit 89ede9
	strs_init( &family, &part, &suffix, NULL );
Packit 89ede9
Packit 89ede9
	while ( *p && *p!='|' ) str_addchar( &family, *p++ );
Packit 89ede9
	if ( *p=='|' ) p++;
Packit 89ede9
Packit 89ede9
	while ( *p ) {
Packit 89ede9
		while ( *p && *p!='|' ) str_addchar( &part, *p++ );
Packit 89ede9
		/* truncate periods from "A. B. Jones" names */
Packit 89ede9
		if ( part.len ) {
Packit 89ede9
			if ( part.len==2 && part.data[1]=='.' ) {
Packit 89ede9
				part.len=1;
Packit 89ede9
				part.data[1]='\0';
Packit 89ede9
			}
Packit 89ede9
			if ( n==0 )
Packit 89ede9
				output_tag( outptr, lvl2indent(level), "name", NULL, TAG_OPEN, TAG_NEWLINE, "type", "personal", NULL );
Packit 89ede9
			output_tag( outptr, lvl2indent(incr_level(level,1)), "namePart", part.data, TAG_OPENCLOSE, TAG_NEWLINE, "type", "given", NULL );
Packit 89ede9
			n++;
Packit 89ede9
		}
Packit 89ede9
		if ( *p=='|' ) {
Packit 89ede9
			p++;
Packit 89ede9
			if ( *p=='|' ) {
Packit 89ede9
				p++;
Packit 89ede9
				while ( *p && *p!='|' ) str_addchar( &suffix, *p++ );
Packit 89ede9
			}
Packit 89ede9
			str_empty( &part );
Packit 89ede9
		}
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( family.len ) {
Packit 89ede9
		if ( n==0 )
Packit 89ede9
			output_tag( outptr, lvl2indent(level), "name", NULL, TAG_OPEN, TAG_NEWLINE, "type", "personal", NULL );
Packit 89ede9
		output_tag( outptr, lvl2indent(incr_level(level,1)), "namePart", family.data, TAG_OPENCLOSE, TAG_NEWLINE, "type", "family", NULL );
Packit 89ede9
		n++;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( suffix.len ) {
Packit 89ede9
		if ( n==0 )
Packit 89ede9
			output_tag( outptr, lvl2indent(level), "name", NULL, TAG_OPEN, TAG_NEWLINE, "type", "personal", NULL );
Packit 89ede9
		output_tag( outptr, lvl2indent(incr_level(level,1)), "namePart", suffix.data, TAG_OPENCLOSE, TAG_NEWLINE, "type", "suffix", NULL );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	strs_free( &part, &family, &suffix, NULL );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
Packit 89ede9
/* MODS v 3.4
Packit 89ede9
 *
Packit 89ede9
 * <name [type="corporation"/type="conference"]>
Packit 89ede9
 *    <namePart></namePart>
Packit 89ede9
 *    <displayForm></displayForm>
Packit 89ede9
 *    <affiliation></affiliation>
Packit 89ede9
 *    <role>
Packit 89ede9
 *        <roleTerm [authority="marcrealtor"] type="text"></roleTerm>
Packit 89ede9
 *    </role>
Packit 89ede9
 *    <description></description>
Packit 89ede9
 * </name>
Packit 89ede9
 */
Packit 89ede9
Packit 89ede9
#define NO_AUTHORITY (0)
Packit 89ede9
#define MARC_AUTHORITY (1)
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_names( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	convert   names[] = {
Packit 89ede9
	  { "author",                              "AUTHOR",          0, MARC_AUTHORITY },
Packit 89ede9
	  { "editor",                              "EDITOR",          0, MARC_AUTHORITY },
Packit 89ede9
	  { "annotator",                           "ANNOTATOR",       0, MARC_AUTHORITY },
Packit 89ede9
	  { "artist",                              "ARTIST",          0, MARC_AUTHORITY },
Packit 89ede9
	  { "author",                              "2ND_AUTHOR",      0, MARC_AUTHORITY },
Packit 89ede9
	  { "author",                              "3RD_AUTHOR",      0, MARC_AUTHORITY },
Packit 89ede9
	  { "author",                              "SUB_AUTHOR",      0, MARC_AUTHORITY },
Packit 89ede9
	  { "author",                              "COMMITTEE",       0, MARC_AUTHORITY },
Packit 89ede9
	  { "author",                              "COURT",           0, MARC_AUTHORITY },
Packit 89ede9
	  { "author",                              "LEGISLATIVEBODY", 0, MARC_AUTHORITY },
Packit 89ede9
	  { "author of afterword, colophon, etc.", "AFTERAUTHOR",     0, MARC_AUTHORITY },
Packit 89ede9
	  { "author of introduction, etc.",        "INTROAUTHOR",     0, MARC_AUTHORITY },
Packit 89ede9
	  { "cartographer",                        "CARTOGRAPHER",    0, MARC_AUTHORITY },
Packit 89ede9
	  { "collaborator",                        "COLLABORATOR",    0, MARC_AUTHORITY },
Packit 89ede9
	  { "commentator",                         "COMMENTATOR",     0, MARC_AUTHORITY },
Packit 89ede9
	  { "compiler",                            "COMPILER",        0, MARC_AUTHORITY },
Packit 89ede9
	  { "degree grantor",                      "DEGREEGRANTOR",   0, MARC_AUTHORITY },
Packit 89ede9
	  { "director",                            "DIRECTOR",        0, MARC_AUTHORITY },
Packit 89ede9
	  { "event",                               "EVENT",           0, NO_AUTHORITY   },
Packit 89ede9
	  { "inventor",                            "INVENTOR",        0, MARC_AUTHORITY },
Packit 89ede9
	  { "organizer of meeting",                "ORGANIZER",       0, MARC_AUTHORITY },
Packit 89ede9
	  { "patent holder",                       "ASSIGNEE",        0, MARC_AUTHORITY },
Packit 89ede9
	  { "performer",                           "PERFORMER",       0, MARC_AUTHORITY },
Packit 89ede9
	  { "producer",                            "PRODUCER",        0, MARC_AUTHORITY },
Packit 89ede9
	  { "addressee",                           "ADDRESSEE",       0, MARC_AUTHORITY },
Packit 89ede9
	  { "redactor",                            "REDACTOR",        0, MARC_AUTHORITY },
Packit 89ede9
	  { "reporter",                            "REPORTER",        0, MARC_AUTHORITY },
Packit 89ede9
	  { "sponsor",                             "SPONSOR",         0, MARC_AUTHORITY },
Packit 89ede9
	  { "translator",                          "TRANSLATOR",      0, MARC_AUTHORITY },
Packit 89ede9
	  { "writer",                              "WRITER",          0, MARC_AUTHORITY },
Packit 89ede9
	};
Packit 89ede9
	int i, n, nfields, ntypes = sizeof( names ) / sizeof( convert );
Packit 89ede9
	int f_asis, f_corp, f_conf;
Packit 89ede9
	str role;
Packit 89ede9
Packit 89ede9
	str_init( &role );
Packit 89ede9
	nfields = fields_num( f );
Packit 89ede9
	for ( n=0; n
Packit 89ede9
		for ( i=0; i
Packit 89ede9
			if ( fields_level( f, i )!=level ) continue;
Packit 89ede9
			if ( f->data[i].len==0 ) continue;
Packit 89ede9
			f_asis = f_corp = f_conf = 0;
Packit 89ede9
			str_strcpyc( &role, f->tag[i].data );
Packit 89ede9
			if ( str_findreplace( &role, ":ASIS", "" )) f_asis=1;
Packit 89ede9
			if ( str_findreplace( &role, ":CORP", "" )) f_corp=1;
Packit 89ede9
			if ( str_findreplace( &role, ":CONF", "" )) f_conf=1;
Packit 89ede9
			if ( strcasecmp( role.data, names[n].internal ) )
Packit 89ede9
				continue;
Packit 89ede9
			if ( f_asis ) {
Packit 89ede9
				output_tag( outptr, lvl2indent(level),               "name",     NULL, TAG_OPEN,      TAG_NEWLINE, NULL );
Packit 89ede9
				output_fil( outptr, lvl2indent(incr_level(level,1)), "namePart", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
			} else if ( f_corp ) {
Packit 89ede9
				output_tag( outptr, lvl2indent(level),               "name",     NULL, TAG_OPEN,      TAG_NEWLINE, "type", "corporate", NULL );
Packit 89ede9
				output_fil( outptr, lvl2indent(incr_level(level,1)), "namePart", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
			} else if ( f_conf ) {
Packit 89ede9
				output_tag( outptr, lvl2indent(level),               "name",     NULL, TAG_OPEN,      TAG_NEWLINE, "type", "conference", NULL );
Packit 89ede9
				output_fil( outptr, lvl2indent(incr_level(level,1)), "namePart", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
			} else {
Packit 89ede9
				output_name(outptr, f->data[i].data, level);
Packit 89ede9
			}
Packit 89ede9
			output_tag( outptr, lvl2indent(incr_level(level,1)), "role", NULL, TAG_OPEN, TAG_NEWLINE, NULL );
Packit 89ede9
			if ( names[n].code & MARC_AUTHORITY )
Packit 89ede9
				output_tag( outptr, lvl2indent(incr_level(level,2)), "roleTerm", names[n].mods, TAG_OPENCLOSE, TAG_NEWLINE, "authority", "marcrelator", "type", "text", NULL );
Packit 89ede9
			else
Packit 89ede9
				output_tag( outptr, lvl2indent(incr_level(level,2)), "roleTerm", names[n].mods, TAG_OPENCLOSE, TAG_NEWLINE, "type", "text", NULL );
Packit 89ede9
			output_tag( outptr, lvl2indent(incr_level(level,1)), "role", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
			output_tag( outptr, lvl2indent(level),               "name", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
			fields_setused( f, i );
Packit 89ede9
		}
Packit 89ede9
	}
Packit 89ede9
	str_free( &role );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* datepos[ NUM_DATE_TYPES ]
Packit 89ede9
 *     use define to ensure that the array and loops don't get out of sync
Packit 89ede9
 *     datepos[0] -> DATE:YEAR/PARTDATE:YEAR
Packit 89ede9
 *     datepos[1] -> DATE:MONTH/PARTDATE:MONTH
Packit 89ede9
 *     datepos[2] -> DATE:DAY/PARTDATE:DAY
Packit 89ede9
 *     datepos[3] -> DATE/PARTDATE
Packit 89ede9
 */
Packit 89ede9
#define DATE_YEAR      (0)
Packit 89ede9
#define DATE_MONTH     (1)
Packit 89ede9
#define DATE_DAY       (2)
Packit 89ede9
#define DATE_ALL       (3)
Packit 89ede9
#define NUM_DATE_TYPES (4)
Packit 89ede9
Packit 89ede9
static int
Packit 89ede9
find_datepos( fields *f, int level, unsigned char use_altnames, int datepos[NUM_DATE_TYPES] )
Packit 89ede9
{
Packit 89ede9
	char      *src_names[] = { "DATE:YEAR", "DATE:MONTH", "DATE:DAY", "DATE" };
Packit 89ede9
	char      *alt_names[] = { "PARTDATE:YEAR", "PARTDATE:MONTH", "PARTDATE:DAY", "PARTDATE" };
Packit 89ede9
	int       found = 0;
Packit 89ede9
	int       i;
Packit 89ede9
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( !use_altnames )
Packit 89ede9
			datepos[i] = fields_find( f, src_names[i], level );
Packit 89ede9
		else
Packit 89ede9
			datepos[i] = fields_find( f, alt_names[i], level );
Packit 89ede9
		if ( datepos[i]!=FIELDS_NOTFOUND ) found = 1;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	return found;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* find_dateinfo()
Packit 89ede9
 *
Packit 89ede9
 *      fill datepos[] array with position indexes to date information in fields *f
Packit 89ede9
 *
Packit 89ede9
 *      when generating dates for LEVEL_MAIN, first look at level=LEVEL_MAIN, but if that
Packit 89ede9
 *      fails, use LEVEL_ANY (-1)
Packit 89ede9
 *
Packit 89ede9
 *      returns 1 if date information found, 0 otherwise
Packit 89ede9
 */
Packit 89ede9
static int
Packit 89ede9
find_dateinfo( fields *f, int level, int datepos[ NUM_DATE_TYPES ] )
Packit 89ede9
{
Packit 89ede9
	int found;
Packit 89ede9
Packit 89ede9
	/* default to finding date information for the current level */
Packit 89ede9
	found = find_datepos( f, level, 0, datepos );
Packit 89ede9
Packit 89ede9
	/* for LEVEL_MAIN, do whatever it takes to find a date */
Packit 89ede9
	if ( !found && level == LEVEL_MAIN ) {
Packit 89ede9
		found = find_datepos( f, -1, 0, datepos );
Packit 89ede9
	}
Packit 89ede9
	if ( !found && level == LEVEL_MAIN ) {
Packit 89ede9
		found = find_datepos( f, -1, 1, datepos );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	return found;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_datepieces( fields *f, FILE *outptr, int pos[ NUM_DATE_TYPES ] )
Packit 89ede9
{
Packit 89ede9
	str *s;
Packit 89ede9
	int i;
Packit 89ede9
Packit 89ede9
	for ( i=0; i<3 && pos[i]!=-1; ++i ) {
Packit 89ede9
		if ( i>0 ) fprintf( outptr, "-" );
Packit 89ede9
		/* zero pad month or days written as "1", "2", "3" ... */
Packit 89ede9
		if ( i==DATE_MONTH || i==DATE_DAY ) {
Packit 89ede9
			s = fields_value( f, pos[i], FIELDS_STRP_NOUSE );
Packit 89ede9
			if ( s->len==1 ) {
Packit 89ede9
				fprintf( outptr, "0" );
Packit 89ede9
			}
Packit 89ede9
		}
Packit 89ede9
		fprintf( outptr, "%s", (char *) fields_value( f, pos[i], FIELDS_CHRP ) );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_dateissued( fields *f, FILE *outptr, int level, int pos[ NUM_DATE_TYPES ] )
Packit 89ede9
{
Packit 89ede9
	output_tag( outptr, lvl2indent(incr_level(level,1)), "dateIssued", NULL, TAG_OPEN, TAG_NONEWLINE, NULL );
Packit 89ede9
	if ( pos[ DATE_YEAR ]!=-1 || pos[ DATE_MONTH ]!=-1 || pos[ DATE_DAY ]!=-1 ) {
Packit 89ede9
		output_datepieces( f, outptr, pos );
Packit 89ede9
	} else {
Packit 89ede9
		fprintf( outptr, "%s", (char *) fields_value( f, pos[ DATE_ALL ], FIELDS_CHRP ) );
Packit 89ede9
	}
Packit 89ede9
	fprintf( outptr, "</dateIssued>\n" );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_origin( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	convert parts[] = {
Packit 89ede9
		{ "issuance",	  "ISSUANCE",      0, 0 },
Packit 89ede9
		{ "publisher",	  "PUBLISHER",     0, 0 },
Packit 89ede9
		{ "place",	  "ADDRESS",       0, 1 },
Packit 89ede9
		{ "place",	  "AUTHORADDRESS", 0, 0 },
Packit 89ede9
		{ "edition",	  "EDITION",       0, 0 },
Packit 89ede9
		{ "dateCaptured", "URLDATE",       0, 0 }
Packit 89ede9
	};
Packit 89ede9
	int nparts = sizeof( parts ) / sizeof( parts[0] );
Packit 89ede9
	int i, found, datefound, datepos[ NUM_DATE_TYPES ];
Packit 89ede9
Packit 89ede9
	found     = convert_findallfields( f, parts, nparts, level );
Packit 89ede9
	datefound = find_dateinfo( f, level, datepos );
Packit 89ede9
	if ( !found && !datefound ) return;
Packit 89ede9
Packit 89ede9
Packit 89ede9
	output_tag( outptr, lvl2indent(level), "originInfo", NULL, TAG_OPEN, TAG_NEWLINE, NULL );
Packit 89ede9
Packit 89ede9
	/* issuance must precede date */
Packit 89ede9
	if ( parts[0].pos!=-1 )
Packit 89ede9
		output_fil( outptr, lvl2indent(incr_level(level,1)), "issuance", f, parts[0].pos, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
Packit 89ede9
	/* date */
Packit 89ede9
	if ( datefound )
Packit 89ede9
		output_dateissued( f, outptr, level, datepos );
Packit 89ede9
Packit 89ede9
	/* rest of the originInfo elements */
Packit 89ede9
	for ( i=1; i
Packit 89ede9
Packit 89ede9
		/* skip missing originInfo elements */
Packit 89ede9
		if ( parts[i].pos==-1 ) continue;
Packit 89ede9
Packit 89ede9
		/* normal originInfo element */
Packit 89ede9
		if ( parts[i].code==0 ) {
Packit 89ede9
			output_fil( outptr, lvl2indent(incr_level(level,1)), parts[i].mods, f, parts[i].pos, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
		}
Packit 89ede9
Packit 89ede9
		/* originInfo with placeTerm info */
Packit 89ede9
		else {
Packit 89ede9
			output_tag( outptr, lvl2indent(incr_level(level,1)), parts[i].mods, NULL,            TAG_OPEN,      TAG_NEWLINE, NULL );
Packit 89ede9
			output_fil( outptr, lvl2indent(incr_level(level,2)), "placeTerm",   f, parts[i].pos, TAG_OPENCLOSE, TAG_NEWLINE, "type", "text", NULL );
Packit 89ede9
			output_tag( outptr, lvl2indent(incr_level(level,1)), parts[i].mods, NULL,            TAG_CLOSE,     TAG_NEWLINE, NULL );
Packit 89ede9
		}
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	output_tag( outptr, lvl2indent(level), "originInfo", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* output_language_core()
Packit 89ede9
 *
Packit 89ede9
 *      generates language output for tag="langauge" or tag="languageOfCataloging"
Packit 89ede9
 *      if possible, outputs iso639-2b code for the language
Packit 89ede9
 *
Packit 89ede9
 * <language>
Packit 89ede9
 *     <languageTerm type="text">xxx</languageTerm>
Packit 89ede9
 * </language>
Packit 89ede9
 *
Packit 89ede9
 * <language>
Packit 89ede9
 *     <languageTerm type="text">xxx</languageTerm>
Packit 89ede9
 *     <languageTerm type="code" authority="iso639-2b">xxx</languageTerm>
Packit 89ede9
 * </language>
Packit 89ede9
 *
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
output_language_core( fields *f, int n, FILE *outptr, char *tag, int level )
Packit 89ede9
{
Packit 89ede9
	char *lang, *code;
Packit 89ede9
Packit 89ede9
	lang = (char *) fields_value( f, n, FIELDS_CHRP );
Packit 89ede9
	code = iso639_2_from_language( lang );
Packit 89ede9
Packit 89ede9
	output_tag( outptr, lvl2indent(level),               tag,            NULL, TAG_OPEN,      TAG_NEWLINE, NULL );
Packit 89ede9
	output_tag( outptr, lvl2indent(incr_level(level,1)), "languageTerm", lang, TAG_OPENCLOSE, TAG_NEWLINE, "type", "text", NULL );
Packit 89ede9
	if ( code ) {
Packit 89ede9
		output_tag( outptr, lvl2indent(incr_level(level,1)), "languageTerm", code, TAG_OPENCLOSE, TAG_NEWLINE, "type", "code", "authority", "iso639-2b", NULL );
Packit 89ede9
	}
Packit 89ede9
	output_tag( outptr, lvl2indent(level),               tag,            NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_language( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	int n;
Packit 89ede9
	n = fields_find( f, "LANGUAGE", level );
Packit 89ede9
	if ( n!=FIELDS_NOTFOUND )
Packit 89ede9
		output_language_core( f, n, outptr, "language", level );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_description( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	char *val;
Packit 89ede9
	int n;
Packit 89ede9
Packit 89ede9
	n = fields_find( f, "DESCRIPTION", level );
Packit 89ede9
	if ( n!=FIELDS_NOTFOUND ) {
Packit 89ede9
		val = ( char * ) fields_value( f, n, FIELDS_CHRP );
Packit 89ede9
		output_tag( outptr, lvl2indent(level),               "physicalDescription", NULL, TAG_OPEN,      TAG_NEWLINE, NULL );
Packit 89ede9
		output_tag( outptr, lvl2indent(incr_level(level,1)), "note",                val,  TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
		output_tag( outptr, lvl2indent(level),               "physicalDescription", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_toc( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	char *val;
Packit 89ede9
	int n;
Packit 89ede9
Packit 89ede9
	n = fields_find( f, "CONTENTS", level );
Packit 89ede9
	if ( n!=FIELDS_NOTFOUND ) {
Packit 89ede9
		val = (char *) fields_value( f, n, FIELDS_CHRP );
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "tableOfContents", val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* detail output
Packit 89ede9
 *
Packit 89ede9
 * for example:
Packit 89ede9
 *
Packit 89ede9
 * <detail type="volume"><number>xxx</number>
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
mods_output_detail( fields *f, FILE *outptr, int n, char *item_name, int level )
Packit 89ede9
{
Packit 89ede9
	if ( n!=-1 ) {
Packit 89ede9
		output_tag( outptr, lvl2indent(incr_level(level,1)), "detail", NULL,  TAG_OPEN,      TAG_NONEWLINE, "type", item_name, NULL );
Packit 89ede9
		output_fil( outptr, 0,                                "number", f, n,  TAG_OPENCLOSE, TAG_NONEWLINE, NULL );
Packit 89ede9
		output_tag( outptr, 0,                                "detail", NULL,  TAG_CLOSE,     TAG_NEWLINE,   NULL );                       
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
Packit 89ede9
/* extents output
Packit 89ede9
 *
Packit 89ede9
 * <extent unit="page">
Packit 89ede9
 * 	<start>xxx</start>
Packit 89ede9
 * 	<end>xxx</end>
Packit 89ede9
 * </extent>
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
mods_output_extents( fields *f, FILE *outptr, int start, int end, int total, char *extype, int level )
Packit 89ede9
{
Packit 89ede9
	char *val;
Packit 89ede9
Packit 89ede9
	output_tag( outptr, lvl2indent(incr_level(level,1)), "extent", NULL, TAG_OPEN, TAG_NEWLINE, "unit", extype, NULL );
Packit 89ede9
	if ( start!=-1 ) {
Packit 89ede9
		val = (char *) fields_value( f, start, FIELDS_CHRP );
Packit 89ede9
		output_tag( outptr, lvl2indent(incr_level(level,2)), "start", val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
	if ( end!=-1 ) {
Packit 89ede9
		val = (char *) fields_value( f, end, FIELDS_CHRP );
Packit 89ede9
		output_tag( outptr, lvl2indent(incr_level(level,2)), "end",   val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
	if ( total!=-1 ) {
Packit 89ede9
		val = (char *) fields_value( f, total, FIELDS_CHRP );
Packit 89ede9
		output_tag( outptr, lvl2indent(incr_level(level,2)), "total", val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
	output_tag( outptr, lvl2indent(incr_level(level,1)), "extent", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
try_output_partheader( FILE *outptr, int wrote_header, int level )
Packit 89ede9
{
Packit 89ede9
	if ( !wrote_header )
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "part", NULL, TAG_OPEN, TAG_NEWLINE, NULL );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
try_output_partfooter( FILE *outptr, int wrote_header, int level )
Packit 89ede9
{
Packit 89ede9
	if ( wrote_header )
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "part", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* part date output
Packit 89ede9
 *
Packit 89ede9
 * <date>xxxx-xx-xx</date>
Packit 89ede9
 *
Packit 89ede9
 */
Packit 89ede9
static int
Packit 89ede9
output_partdate( fields *f, FILE *outptr, int level, int wrote_header )
Packit 89ede9
{
Packit 89ede9
	convert parts[] = {
Packit 89ede9
		{ "",	"PARTDATE:YEAR",           0, 0 },
Packit 89ede9
		{ "",	"PARTDATE:MONTH",          0, 0 },
Packit 89ede9
		{ "",	"PARTDATE:DAY",            0, 0 },
Packit 89ede9
	};
Packit 89ede9
	int nparts = sizeof(parts)/sizeof(parts[0]);
Packit 89ede9
Packit 89ede9
	if ( !convert_findallfields( f, parts, nparts, level ) ) return 0;
Packit 89ede9
Packit 89ede9
	try_output_partheader( outptr, wrote_header, level );
Packit 89ede9
Packit 89ede9
	output_tag( outptr, lvl2indent(incr_level(level,1)), "date", NULL, TAG_OPEN, TAG_NONEWLINE, NULL );
Packit 89ede9
Packit 89ede9
	if ( parts[0].pos!=-1 ) {
Packit 89ede9
		fprintf( outptr, "%s", (char *) fields_value( f, parts[0].pos, FIELDS_CHRP ) );
Packit 89ede9
	} else fprintf( outptr, "XXXX" );
Packit 89ede9
Packit 89ede9
	if ( parts[1].pos!=-1 ) {
Packit 89ede9
		fprintf( outptr, "-%s", (char *) fields_value( f, parts[1].pos, FIELDS_CHRP ) );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( parts[2].pos!=-1 ) {
Packit 89ede9
		if ( parts[1].pos==-1 )
Packit 89ede9
			fprintf( outptr, "-XX" );
Packit 89ede9
		fprintf( outptr, "-%s", (char *) fields_value( f, parts[2].pos, FIELDS_CHRP ) );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	fprintf( outptr,"</date>\n");
Packit 89ede9
Packit 89ede9
	return 1;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static int
Packit 89ede9
output_partpages( fields *f, FILE *outptr, int level, int wrote_header )
Packit 89ede9
{
Packit 89ede9
	convert parts[] = {
Packit 89ede9
		{ "",  "PAGES:START",              0, 0 },
Packit 89ede9
		{ "",  "PAGES:STOP",               0, 0 },
Packit 89ede9
		{ "",  "PAGES",                    0, 0 },
Packit 89ede9
		{ "",  "PAGES:TOTAL",              0, 0 }
Packit 89ede9
	};
Packit 89ede9
	int nparts = sizeof(parts)/sizeof(parts[0]);
Packit 89ede9
Packit 89ede9
	if ( !convert_findallfields( f, parts, nparts, level ) ) return 0;
Packit 89ede9
Packit 89ede9
	try_output_partheader( outptr, wrote_header, level );
Packit 89ede9
Packit 89ede9
	/* If PAGES:START or PAGES:STOP are undefined */
Packit 89ede9
	if ( parts[0].pos==-1 || parts[1].pos==-1 ) {
Packit 89ede9
		if ( parts[0].pos!=-1 )
Packit 89ede9
			mods_output_detail( f, outptr, parts[0].pos, "page", level );
Packit 89ede9
		if ( parts[1].pos!=-1 )
Packit 89ede9
			mods_output_detail( f, outptr, parts[1].pos, "page", level );
Packit 89ede9
		if ( parts[2].pos!=-1 )
Packit 89ede9
			mods_output_detail( f, outptr, parts[2].pos, "page", level );
Packit 89ede9
		if ( parts[3].pos!=-1 )
Packit 89ede9
			mods_output_extents( f, outptr, -1, -1, parts[3].pos, "page", level );
Packit 89ede9
	}
Packit 89ede9
	/* If both PAGES:START and PAGES:STOP are defined */
Packit 89ede9
	else {
Packit 89ede9
		mods_output_extents( f, outptr, parts[0].pos, parts[1].pos, parts[3].pos, "page", level );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	return 1;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static int
Packit 89ede9
output_partelement( fields *f, FILE *outptr, int level, int wrote_header )
Packit 89ede9
{
Packit 89ede9
	convert parts[] = {
Packit 89ede9
		{ "",                "NUMVOLUMES",      0, 0 },
Packit 89ede9
		{ "volume",          "VOLUME",          0, 0 },
Packit 89ede9
		{ "section",         "SECTION",         0, 0 },
Packit 89ede9
		{ "issue",           "ISSUE",           0, 0 },
Packit 89ede9
		{ "number",          "NUMBER",          0, 0 },
Packit 89ede9
		{ "publiclawnumber", "PUBLICLAWNUMBER", 0, 0 },
Packit 89ede9
		{ "session",         "SESSION",         0, 0 },
Packit 89ede9
		{ "articlenumber",   "ARTICLENUMBER",   0, 0 },
Packit 89ede9
		{ "part",            "PART",            0, 0 },
Packit 89ede9
		{ "chapter",         "CHAPTER",         0, 0 },
Packit 89ede9
		{ "report number",   "REPORTNUMBER",    0, 0 },
Packit 89ede9
	};
Packit 89ede9
	int i, nparts = sizeof( parts ) / sizeof( convert );
Packit 89ede9
Packit 89ede9
	if ( !convert_findallfields( f, parts, nparts, level ) ) return 0;
Packit 89ede9
Packit 89ede9
	try_output_partheader( outptr, wrote_header, level );
Packit 89ede9
Packit 89ede9
	/* start loop at 1 to skip NUMVOLUMES */
Packit 89ede9
	for ( i=1; i
Packit 89ede9
		if ( parts[i].pos==-1 ) continue;
Packit 89ede9
		mods_output_detail( f, outptr, parts[i].pos, parts[i].mods, level );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( parts[0].pos!=-1 )
Packit 89ede9
		mods_output_extents( f, outptr, -1, -1, parts[0].pos, "volumes", level );
Packit 89ede9
Packit 89ede9
	return 1;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_part( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	int wrote_hdr;
Packit 89ede9
	wrote_hdr  = output_partdate( f, outptr, level, 0 );
Packit 89ede9
	wrote_hdr += output_partelement( f, outptr, level, wrote_hdr );
Packit 89ede9
	wrote_hdr += output_partpages( f, outptr, level, wrote_hdr );
Packit 89ede9
	try_output_partfooter( outptr, wrote_hdr, level );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_recordInfo( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	int n;
Packit 89ede9
	n = fields_find( f, "LANGCATALOG", level );
Packit 89ede9
	if ( n!=FIELDS_NOTFOUND ) {
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "recordInfo", NULL, TAG_OPEN, TAG_NEWLINE, NULL );
Packit 89ede9
		output_language_core( f, n, outptr, "languageOfCataloging", incr_level(level,1) );
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "recordInfo", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* output_genre()
Packit 89ede9
 *
Packit 89ede9
 * <genre authority="marcgt">thesis</genre>
Packit 89ede9
 * <genre authority="bibutilsgt">Diploma thesis</genre>
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
output_genre( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	char *value, *attr = NULL, *attrvalue = NULL;
Packit 89ede9
	int i, n;
Packit 89ede9
Packit 89ede9
	n = fields_num( f );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( fields_level( f, i ) != level ) continue;
Packit 89ede9
		if ( !fields_match_tag( f, i, "GENRE:MARC" ) && !fields_match_tag( f, i, "GENRE:BIBUTILS" ) && !fields_match_tag( f, i, "GENRE:UNKNOWN" ) ) continue;
Packit 89ede9
		value = fields_value( f, i, FIELDS_CHRP );
Packit 89ede9
		if ( is_marc_genre( value ) ) {
Packit 89ede9
			attr      = "authority";
Packit 89ede9
			attrvalue = "marcgt";
Packit 89ede9
		}
Packit 89ede9
		else if ( is_bu_genre( value ) ) {
Packit 89ede9
			attr      = "authority";
Packit 89ede9
			attrvalue = "bibutilsgt";
Packit 89ede9
		}
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "genre", value, TAG_OPENCLOSE, TAG_NEWLINE, attr, attrvalue, NULL );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* output_resource()
Packit 89ede9
 *
Packit 89ede9
 * <typeOfResource>text</typeOfResource>
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
output_resource( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	char *value;
Packit 89ede9
	int n;
Packit 89ede9
Packit 89ede9
	n = fields_find( f, "RESOURCE", level );
Packit 89ede9
	if ( n!=FIELDS_NOTFOUND ) {
Packit 89ede9
		value = fields_value( f, n, FIELDS_CHRP );
Packit 89ede9
		if ( is_marc_resource( value ) ) {
Packit 89ede9
			output_fil( outptr, lvl2indent(level), "typeOfResource", f, n, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
		} else {
Packit 89ede9
			fprintf( stderr, "Illegal typeofResource = '%s'\n", value );
Packit 89ede9
		}
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_type( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	int n;
Packit 89ede9
Packit 89ede9
	/* silence warnings about INTERNAL_TYPE being unused */
Packit 89ede9
	n = fields_find( f, "INTERNAL_TYPE", LEVEL_MAIN );
Packit 89ede9
	if ( n!=FIELDS_NOTFOUND ) fields_setused( f, n );
Packit 89ede9
Packit 89ede9
	output_resource( f, outptr, level );
Packit 89ede9
	output_genre( f, outptr, level );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* output_abs()
Packit 89ede9
 *
Packit 89ede9
 * <abstract>xxxx</abstract>
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
output_abs( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	int n;
Packit 89ede9
Packit 89ede9
	n = fields_find( f, "ABSTRACT", level );
Packit 89ede9
	output_fil( outptr, lvl2indent(level), "abstract", f, n, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_notes( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	int i, n;
Packit 89ede9
	char *t;
Packit 89ede9
Packit 89ede9
	n = fields_num( f );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( fields_level( f, i ) != level ) continue;
Packit 89ede9
		t = fields_tag( f, i, FIELDS_CHRP_NOUSE );
Packit 89ede9
		if ( !strcasecmp( t, "NOTES" ) )
Packit 89ede9
			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
		else if ( !strcasecmp( t, "PUBSTATE" ) )
Packit 89ede9
			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "publication status", NULL );
Packit 89ede9
		else if ( !strcasecmp( t, "ANNOTE" ) )
Packit 89ede9
			output_fil( outptr, lvl2indent(level), "bibtex-annote", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
		else if ( !strcasecmp( t, "TIMESCITED" ) )
Packit 89ede9
			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "times cited", NULL );
Packit 89ede9
		else if ( !strcasecmp( t, "ANNOTATION" ) )
Packit 89ede9
			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "annotation", NULL );
Packit 89ede9
		else if ( !strcasecmp( t, "ADDENDUM" ) )
Packit 89ede9
			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "addendum", NULL );
Packit 89ede9
		else if ( !strcasecmp( t, "BIBKEY" ) )
Packit 89ede9
			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "bibliography key", NULL );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* output_key()
Packit 89ede9
 *
Packit 89ede9
 * <subject>
Packit 89ede9
 *    <topic>xxxx</topic>
Packit 89ede9
 * </subject>
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
output_key( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	int i, n;
Packit 89ede9
Packit 89ede9
	n = fields_num( f );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( fields_level( f, i ) != level ) continue;
Packit 89ede9
		if ( !strcasecmp( f->tag[i].data, "KEYWORD" ) ) {
Packit 89ede9
			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_OPEN,      TAG_NEWLINE, NULL );
Packit 89ede9
			output_fil( outptr, lvl2indent(incr_level(level,1)), "topic",   f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
Packit 89ede9
		}
Packit 89ede9
		else if ( !strcasecmp( f->tag[i].data, "EPRINTCLASS" ) ) {
Packit 89ede9
			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_OPEN,      TAG_NEWLINE, NULL );
Packit 89ede9
			output_fil( outptr, lvl2indent(incr_level(level,1)), "topic",   f, i, TAG_OPENCLOSE, TAG_NEWLINE, "class", "primary", NULL );
Packit 89ede9
			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );
Packit 89ede9
		}
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_sn( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	convert sn_types[] = {
Packit 89ede9
		{ "isbn",      "ISBN",      0, 0 },
Packit 89ede9
		{ "isbn",      "ISBN13",    0, 0 },
Packit 89ede9
		{ "lccn",      "LCCN",      0, 0 },
Packit 89ede9
		{ "issn",      "ISSN",      0, 0 },
Packit 89ede9
		{ "coden",     "CODEN",     0, 0 },
Packit 89ede9
		{ "citekey",   "REFNUM",    0, 0 },
Packit 89ede9
		{ "doi",       "DOI",       0, 0 },
Packit 89ede9
		{ "eid",       "EID",       0, 0 },
Packit 89ede9
		{ "eprint",    "EPRINT",    0, 0 },
Packit 89ede9
		{ "eprinttype","EPRINTTYPE",0, 0 },
Packit 89ede9
		{ "pubmed",    "PMID",      0, 0 },
Packit 89ede9
		{ "MRnumber",  "MRNUMBER",  0, 0 },
Packit 89ede9
		{ "medline",   "MEDLINE",   0, 0 },
Packit 89ede9
		{ "pii",       "PII",       0, 0 },
Packit 89ede9
		{ "pmc",       "PMC",       0, 0 },
Packit 89ede9
		{ "arXiv",     "ARXIV",     0, 0 },
Packit 89ede9
		{ "isi",       "ISIREFNUM", 0, 0 },
Packit 89ede9
		{ "accessnum", "ACCESSNUM", 0, 0 },
Packit 89ede9
		{ "jstor",     "JSTOR",     0, 0 },
Packit 89ede9
		{ "isrn",      "ISRN",      0, 0 },
Packit 89ede9
	};
Packit 89ede9
	int ntypes = sizeof( sn_types ) / sizeof( sn_types[0] );
Packit 89ede9
	int i, n;
Packit 89ede9
Packit 89ede9
	/* output call number */
Packit 89ede9
	n = fields_find( f, "CALLNUMBER", level );
Packit 89ede9
	output_fil( outptr, lvl2indent(level), "classification", f, n, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
Packit 89ede9
	/* output specialized serialnumber */
Packit 89ede9
	convert_findallfields( f, sn_types, ntypes, level );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( sn_types[i].pos==-1 ) continue;
Packit 89ede9
		output_fil( outptr, lvl2indent(level), "identifier", f, sn_types[i].pos, TAG_OPENCLOSE, TAG_NEWLINE, "type", sn_types[i].mods, NULL );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	/* output _all_ elements of type SERIALNUMBER */
Packit 89ede9
	n = fields_num( f );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( f->level[i]!=level ) continue;
Packit 89ede9
		if ( strcasecmp( f->tag[i].data, "SERIALNUMBER" ) ) continue;
Packit 89ede9
		output_fil( outptr, lvl2indent(level), "identifier", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "serial number", NULL );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* output_url()
Packit 89ede9
 *
Packit 89ede9
 * <location>
Packit 89ede9
 *     <url>URL</url>
Packit 89ede9
 *     <url urlType="pdf">PDFLINK</url>
Packit 89ede9
 *     <url displayLabel="Electronic full text" access="raw object">PDFLINK</url>
Packit 89ede9
 *     <physicalLocation>LOCATION</physicalLocation>
Packit 89ede9
 * </location>
Packit 89ede9
 */
Packit 89ede9
static void
Packit 89ede9
output_url( fields *f, FILE *outptr, int level )
Packit 89ede9
{
Packit 89ede9
	int location   = fields_find( f, "LOCATION",   level );
Packit 89ede9
	int url        = fields_find( f, "URL",        level );
Packit 89ede9
	int fileattach = fields_find( f, "FILEATTACH", level );
Packit 89ede9
	int pdflink    = fields_find( f, "PDFLINK",    level );
Packit 89ede9
	int i, n;
Packit 89ede9
Packit 89ede9
	if ( url==FIELDS_NOTFOUND && location==FIELDS_NOTFOUND && pdflink==FIELDS_NOTFOUND && fileattach==FIELDS_NOTFOUND ) return;
Packit 89ede9
	output_tag( outptr, lvl2indent(level), "location", NULL, TAG_OPEN, TAG_NEWLINE, NULL );
Packit 89ede9
Packit 89ede9
	n = fields_num( f );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( f->level[i]!=level ) continue;
Packit 89ede9
		if ( strcasecmp( f->tag[i].data, "URL" ) ) continue;
Packit 89ede9
		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( f->level[i]!=level ) continue;
Packit 89ede9
		if ( strcasecmp( f->tag[i].data, "PDFLINK" ) ) continue;
Packit 89ede9
/*		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "urlType", "pdf", NULL ); */
Packit 89ede9
		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( f->level[i]!=level ) continue;
Packit 89ede9
		if ( strcasecmp( f->tag[i].data, "FILEATTACH" ) ) continue;
Packit 89ede9
		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "displayLabel", "Electronic full text", "access", "raw object", NULL );
Packit 89ede9
	}
Packit 89ede9
	if ( location!=-1 )
Packit 89ede9
		output_fil( outptr, lvl2indent(incr_level(level,1)), "physicalLocation", f, location, TAG_OPENCLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
Packit 89ede9
	output_tag( outptr, lvl2indent(level), "location", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* refnum should start with a non-number and not include spaces -- ignore this */
Packit 89ede9
static void
Packit 89ede9
output_refnum( fields *f, int n, FILE *outptr )
Packit 89ede9
{
Packit 89ede9
	char *p = fields_value( f, n, FIELDS_CHRP_NOUSE );
Packit 89ede9
/*	if ( p && ((*p>='0' && *p<='9') || *p=='-' || *p=='_' ))
Packit 89ede9
		fprintf( outptr, "ref" );*/
Packit 89ede9
	while ( p && *p ) {
Packit 89ede9
		if ( !is_ws(*p) ) fprintf( outptr, "%c", *p );
Packit 89ede9
/*		if ( (*p>='A' && *p<='Z') ||
Packit 89ede9
		     (*p>='a' && *p<='z') ||
Packit 89ede9
		     (*p>='0' && *p<='9') ||
Packit 89ede9
		     (*p=='-') || (*p=='
Packit 89ede9
		     (*p=='_') ) fprintf( outptr, "%c", *p );*/
Packit 89ede9
		p++;
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_head( fields *f, FILE *outptr, int dropkey, unsigned long numrefs )
Packit 89ede9
{
Packit 89ede9
	int n;
Packit 89ede9
	fprintf( outptr, "
Packit 89ede9
	if ( !dropkey ) {
Packit 89ede9
		n = fields_find( f, "REFNUM", LEVEL_MAIN );
Packit 89ede9
		if ( n!=FIELDS_NOTFOUND ) {
Packit 89ede9
			fprintf( outptr, " ID=\"");
Packit 89ede9
			output_refnum( f, n, outptr );
Packit 89ede9
			fprintf( outptr, "\"");
Packit 89ede9
		}
Packit 89ede9
	}
Packit 89ede9
	fprintf( outptr, ">\n" );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static int
Packit 89ede9
original_items( fields *f, int level )
Packit 89ede9
{
Packit 89ede9
	int i, targetlevel, n;
Packit 89ede9
	if ( level < 0 ) return 0;
Packit 89ede9
	targetlevel = -( level + 2 );
Packit 89ede9
	n = fields_num( f );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( fields_level( f, i ) == targetlevel )
Packit 89ede9
			return targetlevel;
Packit 89ede9
	}
Packit 89ede9
	return 0;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output_citeparts( fields *f, FILE *outptr, int level, int max )
Packit 89ede9
{
Packit 89ede9
	int orig_level;
Packit 89ede9
Packit 89ede9
	output_title(       f, outptr, level );
Packit 89ede9
	output_names(       f, outptr, level );
Packit 89ede9
	output_origin(      f, outptr, level );
Packit 89ede9
	output_type(        f, outptr, level );
Packit 89ede9
	output_language(    f, outptr, level );
Packit 89ede9
	output_description( f, outptr, level );
Packit 89ede9
Packit 89ede9
	if ( level >= 0 && level < max ) {
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_OPEN,  TAG_NEWLINE, "type", "host", NULL );
Packit 89ede9
		output_citeparts( f, outptr, incr_level(level,1), max );
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
	/* Look for original item things */
Packit 89ede9
	orig_level = original_items( f, level );
Packit 89ede9
	if ( orig_level ) {
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_OPEN,  TAG_NEWLINE, "type", "original", NULL );
Packit 89ede9
		output_citeparts( f, outptr, orig_level, max );
Packit 89ede9
		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );
Packit 89ede9
	}
Packit 89ede9
	output_abs(        f, outptr, level );
Packit 89ede9
	output_notes(      f, outptr, level );
Packit 89ede9
	output_toc(        f, outptr, level );
Packit 89ede9
	output_key(        f, outptr, level );
Packit 89ede9
	output_sn(         f, outptr, level );
Packit 89ede9
	output_url(        f, outptr, level );
Packit 89ede9
	output_part(       f, outptr, level );
Packit 89ede9
Packit 89ede9
	output_recordInfo( f, outptr, level );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
modsout_report_unused_tags( fields *f, param *p, unsigned long numrefs )
Packit 89ede9
{
Packit 89ede9
	int i, n, nwritten, nunused = 0, level;
Packit 89ede9
	char *tag, *value;
Packit 89ede9
	n = fields_num( f );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		if ( fields_used( f, i ) ) continue;
Packit 89ede9
		nunused++;
Packit 89ede9
	}
Packit 89ede9
	if ( nunused ) {
Packit 89ede9
		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
Packit 89ede9
		fprintf( stderr, "Reference %lu has unused tags.\n", numrefs+1 );
Packit 89ede9
		/* Find author from level 0 */
Packit 89ede9
		nwritten = 0;
Packit 89ede9
		for ( i=0; i
Packit 89ede9
			if ( fields_level( f, i ) != 0 ) continue;
Packit 89ede9
			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );
Packit 89ede9
			if ( strcasecmp( tag, "AUTHOR" ) && strcasecmp( tag, "AUTHOR:ASIS" ) && strcasecmp( tag, "AUTHOR:CORP" ) ) continue;
Packit 89ede9
			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
Packit 89ede9
			if ( nwritten==0 ) fprintf( stderr, "\tAuthor(s) (level=0):\n" );
Packit 89ede9
			fprintf( stderr, "\t\t'%s'\n", value );
Packit 89ede9
			nwritten++;
Packit 89ede9
		}
Packit 89ede9
		nwritten = 0;
Packit 89ede9
		for ( i=0; i
Packit 89ede9
			if ( fields_level( f, i ) != 0 ) continue;
Packit 89ede9
			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );
Packit 89ede9
			if ( strcasecmp( tag, "DATE:YEAR" ) && strcasecmp( tag, "PARTDATE:YEAR" ) ) continue;
Packit 89ede9
			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
Packit 89ede9
			if ( nwritten==0 ) fprintf( stderr, "\tYear(s) (level=0):\n" );
Packit 89ede9
			fprintf( stderr, "\t\t'%s'\n", value );
Packit 89ede9
			nwritten++;
Packit 89ede9
		}
Packit 89ede9
		nwritten = 0;
Packit 89ede9
		for ( i=0; i
Packit 89ede9
			if ( fields_level( f, i ) != 0 ) continue;
Packit 89ede9
			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );
Packit 89ede9
			if ( strncasecmp( tag, "TITLE", 5 ) ) continue;
Packit 89ede9
			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
Packit 89ede9
			if ( nwritten==0 ) fprintf( stderr, "\tTitle(s) (level=0):\n" );
Packit 89ede9
			fprintf( stderr, "\t\t'%s'\n", value );
Packit 89ede9
			nwritten++;
Packit 89ede9
		}
Packit 89ede9
	
Packit 89ede9
		fprintf( stderr, "\tUnused tags:\n" );
Packit 89ede9
		for ( i=0; i
Packit 89ede9
			if ( fields_used( f, i ) ) continue;
Packit 89ede9
			tag   = fields_tag(   f, i, FIELDS_CHRP_NOUSE );
Packit 89ede9
			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
Packit 89ede9
			level = fields_level( f, i );
Packit 89ede9
			fprintf( stderr, "\t\ttag: '%s' value: '%s' level: %d\n",
Packit 89ede9
				tag, value, level );
Packit 89ede9
		}
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static int
Packit 89ede9
modsout_write( fields *f, FILE *outptr, param *p, unsigned long numrefs )
Packit 89ede9
{
Packit 89ede9
	int max, dropkey;
Packit 89ede9
	max = fields_maxlevel( f );
Packit 89ede9
	dropkey = ( p->format_opts & BIBL_FORMAT_MODSOUT_DROPKEY );
Packit 89ede9
Packit 89ede9
	output_head( f, outptr, dropkey, numrefs );
Packit 89ede9
	output_citeparts( f, outptr, 0, max );
Packit 89ede9
	modsout_report_unused_tags( f, p, numrefs );
Packit 89ede9
Packit 89ede9
	fprintf( outptr, "</mods>\n" );
Packit 89ede9
	fflush( outptr );
Packit 89ede9
Packit 89ede9
	return BIBL_OK;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
modsout_writeheader( FILE *outptr, param *p )
Packit 89ede9
{
Packit 89ede9
	if ( p->utf8bom ) utf8_writebom( outptr );
Packit 89ede9
	fprintf(outptr,"\n",
Packit 89ede9
			charset_get_xmlname( p->charsetout ) );
Packit 89ede9
	fprintf(outptr,"<modsCollection xmlns=\"http://www.loc.gov/mods/v3\">\n");
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
modsout_writefooter( FILE *outptr )
Packit 89ede9
{
Packit 89ede9
	fprintf(outptr,"</modsCollection>\n");
Packit 89ede9
	fflush( outptr );
Packit 89ede9
}
Packit 89ede9