X-Git-Url: http://git.indexdata.com/?p=idzebra-moved-to-github.git;a=blobdiff_plain;f=data1%2Fd1_marc.c;h=19d05df307c17880f37d4cfcc7b97de0dd6a518a;hp=d038d19cf4ee1a5114f28e77b73ae7cd7e20a76b;hb=4478d785b7769691261005c98063b98a5a5971b3;hpb=02266b68e2e2c86d8a8467ee56721926b365d2d0 diff --git a/data1/d1_marc.c b/data1/d1_marc.c index d038d19..19d05df 100644 --- a/data1/d1_marc.c +++ b/data1/d1_marc.c @@ -1,6 +1,6 @@ -/* $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 +/* $Id: d1_marc.c,v 1.16 2006-08-14 10:40:06 adam Exp $ + Copyright (C) 1995-2006 + Index Data ApS This file is part of the Zebra server. @@ -15,9 +15,9 @@ 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 */ @@ -26,13 +26,13 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include #include -#include #include +#include #include #include #include #include -#include +#include data1_marctab *data1_read_marctab (data1_handle dh, const char *file) { @@ -44,10 +44,7 @@ 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; @@ -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,13 @@ 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) { - 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 +92,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 +102,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 +112,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 +122,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 +132,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 +142,14 @@ 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 - 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); @@ -164,7 +161,7 @@ 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 char *get_data(data1_node *n, int *len, int chop) { char *r; @@ -174,15 +171,21 @@ static char *get_data(data1_node *n, int *len) { 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 (chop) + { + 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; + } + else + if (*len > 0) + return n->u.data.data; } if (n->which == DATA1N_tag) n = n->child; @@ -209,16 +212,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 +225,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 +234,90 @@ 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; + char *dbuf = get_data(subf, &dlen, 0); + if (dlen > 24) + dlen = 24; + if (dbuf && dlen > 0) + memcpy (leader, dbuf, dlen); + 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_data(subf, &dlen, control_field ? 0 : 1); len += dlen; } } @@ -286,74 +328,134 @@ 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")) + { + 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 { - indicator_data = subf->u.tag.tag; + 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); + data = get_data(subf, &dlen, control_field ? 0 : 1); memcpy (op + data_p, data, dlen); 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 +482,11 @@ 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 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ +