X-Git-Url: http://git.indexdata.com/?p=idzebra-moved-to-github.git;a=blobdiff_plain;f=data1%2Fd1_marc.c;h=a332b2a0bbbcd10e694cc332b54887c929ba2419;hp=d038d19cf4ee1a5114f28e77b73ae7cd7e20a76b;hb=85ad68ab178a261dc548284ee68aae9107cbfaaf;hpb=02266b68e2e2c86d8a8467ee56721926b365d2d0 diff --git a/data1/d1_marc.c b/data1/d1_marc.c index d038d19..a332b2a 100644 --- a/data1/d1_marc.c +++ b/data1/d1_marc.c @@ -1,8 +1,5 @@ -/* $Id: d1_marc.c,v 1.2 2002-10-22 13:19:50 adam Exp $ - Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002 - Index Data Aps - -This file is part of the Zebra server. +/* This file is part of the Zebra server. + Copyright (C) 1994-2011 Index Data Zebra is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -15,24 +12,27 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Zebra; see the file LICENSE.zebra. If not, write to the -Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ /* converts data1 tree to ISO2709/MARC record */ +#if HAVE_CONFIG_H +#include +#endif #include #include #include -#include #include +#include #include #include #include #include -#include +#include data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { @@ -44,13 +44,10 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) int argc; if (!(f = data1_path_fopen(dh, file, "r"))) - { - yaz_log(LOG_WARN|LOG_ERRNO, "%s", file); return 0; - } res->name = 0; - res->reference = VAL_NONE; + res->oid = 0; res->next = 0; res->length_data_entry = 4; res->length_starting = 5; @@ -70,7 +67,7 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { if (argc != 2) { - yaz_log(LOG_WARN, "%s:%d:Missing arg for %s", file, lineno, + yaz_log(YLOG_WARN, "%s:%d:Missing arg for %s", file, lineno, *argv); continue; } @@ -80,13 +77,16 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { if (argc != 2) { - yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno, + yaz_log(YLOG_WARN, "%s:%d: Missing arg for %s", file, lineno, *argv); continue; } - if ((res->reference = oid_getvalbyname(argv[1])) == VAL_NONE) + res->oid = yaz_string_to_oid_nmem(yaz_oid_std(), + CLASS_TAGSET, argv[1], + mem); + if (!res->oid) { - yaz_log(LOG_WARN, "%s:%d: Unknown tagset reference '%s'", + yaz_log(YLOG_WARN, "%s:%d: Unknown tagset reference '%s'", file, lineno, argv[1]); continue; } @@ -95,7 +95,7 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { if (argc != 2) { - yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno, + yaz_log(YLOG_WARN, "%s:%d: Missing arg for %s", file, lineno, *argv); continue; } @@ -105,7 +105,7 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { if (argc != 2) { - yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno, + yaz_log(YLOG_WARN, "%s:%d: Missing arg for %s", file, lineno, *argv); continue; } @@ -115,7 +115,7 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { if (argc != 2) { - yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno, + yaz_log(YLOG_WARN, "%s:%d: Missing arg for %s", file, lineno, *argv); continue; } @@ -125,7 +125,7 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { if (argc != 2) { - yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno, + yaz_log(YLOG_WARN, "%s:%d: Missing arg for %s", file, lineno, *argv); continue; } @@ -135,7 +135,7 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { if (argc != 2) { - yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno, + yaz_log(YLOG_WARN, "%s:%d: Missing arg for %s", file, lineno, *argv); continue; } @@ -145,14 +145,29 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { if (argc != 2) { - yaz_log(LOG_WARN, "%s:%d: Missing arg for %s", file, lineno, + yaz_log(YLOG_WARN, "%s:%d: Missing arg for %s", file, lineno, *argv); continue; } res->force_identifier_length = atoi(argv[1]); } + else if (!strcmp(*argv, "implementation-codes")) + { + if (argc != 2) + { + yaz_log(YLOG_WARN, "%s:%d: Missing arg for %s", file, lineno, + *argv); + continue; + } + /* up to 4 characters .. space pad */ + if (strlen(argv[1]) > 4) + yaz_log(YLOG_WARN, "%s:%d: Max 4 characters for " + "implementation-codes", file, lineno); + else + memcpy(res->implementation_codes, argv[1], strlen(argv[1])); + } else - yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'", file, lineno, + yaz_log(YLOG_WARN, "%s:%d: Unknown directive '%s'", file, lineno, *argv); fclose(f); @@ -160,40 +175,30 @@ data1_marctab *data1_read_marctab (data1_handle dh, const char *file) } -/* - * Locate some data under this node. This routine should handle variants - * prettily. - */ -static char *get_data(data1_node *n, int *len) +static void get_data2(data1_node *n, int *len, char *dst, size_t max) { - char *r; + *len = 0; while (n) { if (n->which == DATA1N_data) { - int i; - *len = n->u.data.len; - - for (i = 0; i<*len; i++) - if (!d1_isspace(n->u.data.data[i])) - break; - while (*len && d1_isspace(n->u.data.data[*len - 1])) - (*len)--; - *len = *len - i; - if (*len > 0) - return n->u.data.data + i; + if (dst && *len < max) + { + size_t copy_len = max - *len; + if (copy_len > n->u.data.len) + copy_len = n->u.data.len; + memcpy(dst + *len, n->u.data.data, copy_len); + } + *len += n->u.data.len; } - if (n->which == DATA1N_tag) + if (n->which == DATA1N_tag && *len == 0) n = n->child; else if (n->which == DATA1N_data) n = n->next; else break; } - r = ""; - *len = strlen(r); - return r; } static void memint (char *p, int val, int len) @@ -209,16 +214,12 @@ static void memint (char *p, int val, int len) } } +/* check for indicator. non MARCXML only */ static int is_indicator (data1_marctab *p, data1_node *subf) { -#if 1 if (p->indicator_length != 2 || (subf && subf->which == DATA1N_tag && strlen(subf->u.tag.tag) == 2)) return 1; -#else - if (subf && subf->which == DATA1N_tag && subf->child->which == DATA1N_tag) - return 1; -#endif return 0; } @@ -226,6 +227,8 @@ static int nodetomarc(data1_handle dh, data1_marctab *p, data1_node *n, int selected, char **buf, int *size) { + char leader[24]; + int len = 26; int dlen; int base_address = 25; @@ -233,49 +236,86 @@ static int nodetomarc(data1_handle dh, char *op; data1_node *field, *subf; - yaz_log (LOG_DEBUG, "nodetomarc"); +#if 0 + data1_pr_tree(dh, n, stdout); +#endif + yaz_log (YLOG_DEBUG, "nodetomarc"); + + memcpy (leader+5, p->record_status, 1); + memcpy (leader+6, p->implementation_codes, 4); + memint (leader+10, p->indicator_length, 1); + memint (leader+11, p->identifier_length, 1); + memcpy (leader+17, p->user_systems, 3); + memint (leader+20, p->length_data_entry, 1); + memint (leader+21, p->length_starting, 1); + memint (leader+22, p->length_implementation, 1); + memcpy (leader+23, p->future_use, 1); for (field = n->child; field; field = field->next) { - int is00X = 0; + int control_field = 0; /* 00X fields - usually! */ + int marc_xml = 0; if (field->which != DATA1N_tag) - { - yaz_log(LOG_WARN, "Malformed field composition for marc output."); - return -1; - } + continue; if (selected && !field->u.tag.node_selected) continue; - + subf = field->child; if (!subf) continue; + + if (!yaz_matchstr(field->u.tag.tag, "mc?")) + continue; + else if (!strcmp(field->u.tag.tag, "leader")) + { + int dlen = 0; + get_data2(subf, &dlen, leader, 24); + continue; + } + else if (!strcmp(field->u.tag.tag, "controlfield")) + { + control_field = 1; + marc_xml = 1; + } + else if (!strcmp(field->u.tag.tag, "datafield")) + { + control_field = 0; + marc_xml = 1; + } + else if (subf->which == DATA1N_data) + { + control_field = 1; + marc_xml = 0; + } + else + { + control_field = 0; + marc_xml = 0; + } len += 4 + p->length_data_entry + p->length_starting + p->length_implementation; base_address += 3 + p->length_data_entry + p->length_starting + p->length_implementation; - if (subf->which == DATA1N_data) - is00X = 1; - if (!data1_is_xmlmode(dh)) - { - if (subf->which == DATA1N_tag && !strcmp(subf->u.tag.tag, "@")) - is00X = 1; - } - - - if (!is00X) + if (!control_field) len += p->indicator_length; - /* we'll allow no indicator if length is not 2 */ - if (is_indicator (p, subf)) - subf = subf->child; + /* we'll allow no indicator if length is not 2 */ + /* select when old XML format, since indicator is an element */ + if (marc_xml == 0 && is_indicator (p, subf)) + subf = subf->child; + for (; subf; subf = subf->next) { - if (!is00X) + if (!control_field) + { + if (marc_xml && subf->which != DATA1N_tag) + continue; /* we skip comments, cdata .. */ len += p->identifier_length; - get_data(subf, &dlen); + } + get_data2(subf, &dlen, 0, 0); len += dlen; } } @@ -286,74 +326,131 @@ static int nodetomarc(data1_handle dh, *buf = (char *)xrealloc(*buf, *size = len); op = *buf; + + /* we know the base address now */ + memint (leader+12, base_address, 5); + + /* copy temp leader to real output buf op */ + memcpy (op, leader, 24); memint (op, len, 5); - memcpy (op+5, p->record_status, 1); - memcpy (op+6, p->implementation_codes, 4); - memint (op+10, p->indicator_length, 1); - memint (op+11, p->identifier_length, 1); - memint (op+12, base_address, 5); - memcpy (op+17, p->user_systems, 3); - memint (op+20, p->length_data_entry, 1); - memint (op+21, p->length_starting, 1); - memint (op+22, p->length_implementation, 1); - memcpy (op+23, p->future_use, 1); entry_p = 24; data_p = base_address; for (field = n->child; field; field = field->next) { - int is00X = 0; + int control_field = 0; + int marc_xml = 0; + const char *tag = 0; int data_0 = data_p; - char *indicator_data = " "; + char indicator_data[6]; + + memset (indicator_data, ' ', sizeof(indicator_data)-1); + indicator_data[sizeof(indicator_data)-1] = '\0'; + + if (field->which != DATA1N_tag) + continue; + if (selected && !field->u.tag.node_selected) continue; subf = field->child; if (!subf) continue; - - if (subf->which == DATA1N_data) - is00X = 1; - if (!data1_is_xmlmode(dh)) - { - if (subf->which == DATA1N_tag && !strcmp(subf->u.tag.tag, "@")) - is00X = 1; - } - - if (is_indicator (p, subf)) + + if (!yaz_matchstr(field->u.tag.tag, "mc?")) + continue; + else if (!strcmp(field->u.tag.tag, "leader")) + continue; + else if (!strcmp(field->u.tag.tag, "controlfield")) { - indicator_data = subf->u.tag.tag; + control_field = 1; + marc_xml = 1; + } + else if (!strcmp(field->u.tag.tag, "datafield")) + { + control_field = 0; + marc_xml = 1; + } + else if (subf->which == DATA1N_data) + { + control_field = 1; + marc_xml = 0; + } + else + { + control_field = 0; + marc_xml = 0; + } + if (marc_xml == 0 && is_indicator (p, subf)) + { + strncpy(indicator_data, subf->u.tag.tag, sizeof(indicator_data)-1); subf = subf->child; } - if (!is00X) - { - memcpy (op + data_p, indicator_data, p->indicator_length); - data_p += p->indicator_length; - } - for (; subf; subf = subf->next) + else if (marc_xml == 1 && !control_field) + { + data1_xattr *xa; + for (xa = field->u.tag.attributes; xa; xa = xa->next) + { + if (!strcmp(xa->name, "ind1")) + indicator_data[0] = xa->value[0]; + if (!strcmp(xa->name, "ind2")) + indicator_data[1] = xa->value[0]; + if (!strcmp(xa->name, "ind3")) + indicator_data[2] = xa->value[0]; + } + } + if (!control_field) + { + memcpy (op + data_p, indicator_data, p->indicator_length); + data_p += p->indicator_length; + } + for (; subf; subf = subf->next) { - char *data; - - if (!is00X) + if (!control_field) { const char *identifier = "a"; - if (subf->which != DATA1N_tag) - yaz_log(LOG_WARN, "Malformed fields for marc output."); + if (marc_xml) + { + data1_xattr *xa; + if (subf->which != DATA1N_tag) + continue; + if (strcmp(subf->u.tag.tag, "subfield")) + yaz_log(YLOG_WARN, "Unhandled tag %s", + subf->u.tag.tag); + + for (xa = subf->u.tag.attributes; xa; xa = xa->next) + if (!strcmp(xa->name, "code")) + identifier = xa->value; + } + else if (subf->which != DATA1N_tag) + yaz_log(YLOG_WARN, "Malformed fields for marc output."); else identifier = subf->u.tag.tag; op[data_p] = ISO2709_IDFS; memcpy (op + data_p+1, identifier, p->identifier_length-1); data_p += p->identifier_length; } - data = get_data(subf, &dlen); - memcpy (op + data_p, data, dlen); + get_data2(subf, &dlen, op + data_p, 100000); data_p += dlen; } op[data_p++] = ISO2709_FS; - memcpy (op + entry_p, field->u.tag.tag, 3); + if (marc_xml) + { + data1_xattr *xa; + for (xa = field->u.tag.attributes; xa; xa = xa->next) + if (!strcmp(xa->name, "tag")) + tag = xa->value; + } + else + tag = field->u.tag.tag; + + if (!tag || strlen(tag) != 3) + tag = "000"; + memcpy (op + entry_p, tag, 3); + entry_p += 3; memint (op + entry_p, data_p - data_0, p->length_data_entry); entry_p += p->length_data_entry; @@ -380,3 +477,12 @@ char *data1_nodetomarc(data1_handle dh, data1_marctab *p, data1_node *n, *len = nodetomarc(dh, p, n, selected, buf, size); return *buf; } +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ +