Added grs.danbib filter - for Danish Bibliographic Centre.
[idzebra-moved-to-github.git] / recctrl / marcread.c
index c112f9c..8699373 100644 (file)
@@ -1,5 +1,5 @@
-/* $Id: marcread.c,v 1.19 2003-03-05 11:12:18 oleg Exp $
-   Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
+/* $Id: marcread.c,v 1.23 2003-12-10 23:30:15 adam Exp $
+   Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003
    Index Data Aps
 
 This file is part of the Zebra server.
@@ -34,7 +34,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define MARC_DEBUG 0
 #define MARCOMP_DEBUG 0
 
-static data1_node *grs_read_iso2709 (struct grs_read_info *p)
+static data1_node *grs_read_iso2709 (struct grs_read_info *p, int marc_xml)
 {
     char buf[100000];
     int entry_p;
@@ -83,9 +83,20 @@ static data1_node *grs_read_iso2709 (struct grs_read_info *p)
         yaz_log (LOG_WARN, "cannot read MARC without an abstract syntax");
         return 0;
     }
-    res_top = data1_mk_tag (p->dh, p->mem, absynName, 0, res_root);
+    if (marc_xml)
+    {
+       data1_node *lead;
+       const char *attr[] = { "xmlns", "http://www.loc.gov/MARC21/slim", 0};
+                        
+       res_top = data1_mk_tag (p->dh, p->mem, "record", attr, res_root);
+
+       lead = data1_mk_tag(p->dh, p->mem, "leader", 0, res_top);
+       data1_mk_text_n(p->dh, p->mem, buf, 24, lead);
+    }
+    else
+       res_top = data1_mk_tag (p->dh, p->mem, absynName, 0, res_root);
 
-    if (marctab = res_root->u.root.absyn->marc)
+    if ((marctab = res_root->u.root.absyn->marc))
     {
        memcpy(marctab->leader, buf, 24);
         memcpy(marctab->implementation_codes, buf+6, 4);
@@ -102,7 +113,7 @@ static data1_node *grs_read_iso2709 (struct grs_read_info *p)
        identifier_length = marctab->force_identifier_length;
     else
        identifier_length = atoi_n (buf+11, 1);
-    base_address = atoi_n (buf+12, 4);
+    base_address = atoi_n (buf+12, 5);
 
     length_data_entry = atoi_n (buf+20, 1);
     length_starting = atoi_n (buf+21, 1);
@@ -125,10 +136,11 @@ static data1_node *grs_read_iso2709 (struct grs_read_info *p)
         entry_p += 3;
         tag[3] = '\0';
 
-
-        /* generate field node */
-        res = data1_mk_tag_n (p->dh, p->mem, tag, 3, 0 /* attr */, parent);
-
+       if (marc_xml)
+           res = parent;
+       else
+           res = data1_mk_tag_n (p->dh, p->mem, tag, 3, 0 /* attr */, parent);
+       
 #if MARC_DEBUG
         fprintf (outf, "%s ", tag);
 #endif
@@ -142,58 +154,86 @@ static data1_node *grs_read_iso2709 (struct grs_read_info *p)
         if (memcmp (tag, "00", 2) && indicator_length)
         {
             /* generate indicator node */
+           if (marc_xml)
+           {
+               const char *attr[10];
+               int j;
+
+               attr[0] = "tag";
+               attr[1] = tag;
+               attr[2] = 0;
+
+               res = data1_mk_tag(p->dh, p->mem, "datafield", attr, res);
+
+               for (j = 0; j<indicator_length; j++)
+               {
+                   char str1[18], str2[2];
+                   sprintf (str1, "ind%d", j+1);
+                   str2[0] = buf[i+j];
+                   str2[1] = '\0';
+
+                   attr[0] = str1;
+                   attr[1] = str2;
+                   
+                   data1_tag_add_attr (p->dh, p->mem, res, attr);
+               }
+           }
+           else
+           {
 #if MARC_DEBUG
-            int j;
+               int j;
 #endif
-            res = data1_mk_tag_n (p->dh, p->mem, 
-                                  buf+i, indicator_length, 0 /* attr */, res);
+               res = data1_mk_tag_n (p->dh, p->mem, 
+                                     buf+i, indicator_length, 0 /* attr */, res);
 #if MARC_DEBUG
-            for (j = 0; j<indicator_length; j++)
-                fprintf (outf, "%c", buf[j+i]);
+               for (j = 0; j<indicator_length; j++)
+                   fprintf (outf, "%c", buf[j+i]);
 #endif
-            i += indicator_length;
-        }
+           }
+           i += indicator_length;
+        } 
+       else
+       {
+           if (marc_xml)
+           {
+               const char *attr[10];
+               
+               attr[0] = "tag";
+               attr[1] = tag;
+               attr[2] = 0;
+               
+               res = data1_mk_tag(p->dh, p->mem, "controlfield", attr, res);
+           }
+       }
         parent = res;
         /* traverse sub fields */
         i0 = i;
         while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
         {
-
-           if (!memcmp(tag, "4", 1) && (!yaz_matchstr(absynName, "UNIMARC")||
-               !yaz_matchstr(absynName, "RUSMARC")))
-           {
-               int go = 1;
-               data1_node *res =
-                   data1_mk_tag_n (p->dh, p->mem,
-                                    buf+i+1, identifier_length-1, 
-                                    0 /* attr */, parent);
-                i += identifier_length;
-                i0 = i;
-               do {
-                   while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
-                        buf[i] != ISO2709_FS && i < end_offset)
-                   {
-                       i++;
-                   }
-                   if (!memcmp(buf+i+1, "1", 1) && i<end_offset)
-                   {
-                       go = 0;
-                   }
-                   else
-                   {
-                       buf[i] = '$';
-                   }               
-               } while (go && i < end_offset);
-               
-               data1_mk_text_n (p->dh, p->mem, buf + i0, i - i0, res);
-               i0 = i;
-           }
-            else if (memcmp (tag, "00", 2) && identifier_length)
+           if (memcmp (tag, "00", 2) && identifier_length)
             {
-               data1_node *res =
-                   data1_mk_tag_n (p->dh, p->mem,
-                                    buf+i+1, identifier_length-1, 
-                                    0 /* attr */, parent);
+               data1_node *res;
+               if (marc_xml)
+               {
+                   int j;
+                   const char *attr[3];
+                   char code[10];
+                   
+                   for (j = 1; j<identifier_length && j < 9; j++)
+                       code[j-1] = buf[i+j];
+                   code[j-1] = 0;
+                   attr[0] = "code";
+                   attr[1] = code;
+                   attr[2] = 0;
+                   res = data1_mk_tag(p->dh, p->mem, "subfield",
+                                      attr, parent);
+               }
+               else
+               {
+                   res = data1_mk_tag_n (p->dh, p->mem,
+                                          buf+i+1, identifier_length-1, 
+                                          0 /* attr */, parent);
+               }
 #if MARC_DEBUG
                 fprintf (outf, " $"); 
                 for (j = 1; j<identifier_length; j++)
@@ -270,18 +310,6 @@ static char *get_data(data1_node *n, int *len)
     *len = strlen(r);
     return r;
 }
-static char *tr(char *s, int c1, int c2)
-{
-    char *p = s;
-    
-    while(*p)
-    {
-       if (*p == c1)
-           *p = c2;
-       p++;
-    }
-    return s;
-}
 static data1_node *lookup_subfield(data1_node *node, const char *name)
 {
     data1_node *p;
@@ -374,15 +402,38 @@ static inline_subfield *cat_inline_subfield(mc_subfield *psf, char *buf, inline_
     return pisf; 
 }
 static void cat_inline_field(mc_field *pf, char *buf, data1_node *subfield)
-{
-    
+{    
     if (!pf || !subfield)
        return;
 
-    for (;subfield; subfield = subfield->next)
+    for (;subfield;)
     {
        int len;
-       inline_field *pif = inline_parse(get_data(subfield,&len));
+       inline_field *pif=NULL;
+       data1_node *psubf;
+       
+       if (yaz_matchstr(subfield->u.tag.tag, "1"))
+       {
+           subfield = subfield->next;
+           continue;
+       }
+       
+       psubf = subfield;
+       pif = inline_mk_field();
+       do
+       {
+           int i;
+           if ((i=inline_parse(pif, psubf->u.tag.tag, get_data(psubf, &len)))<0)
+           {
+               logf(LOG_WARN, "inline subfield ($%s): parse error",
+                   psubf->u.tag.tag);
+               inline_destroy_field(pif);
+               return; 
+           }
+           psubf = psubf->next;
+       } while (psubf && yaz_matchstr(psubf->u.tag.tag, "1"));
+       
+       subfield = psubf;
        
        if (pif && !yaz_matchstr(pif->name, pf->name))
        {
@@ -653,9 +704,29 @@ static void parse_data1_tree(struct grs_read_info *p, const char *mc_stmnt, data
     mc_destroy_context(c);
 }
 
+data1_node *grs_read_marcxml(struct grs_read_info *p)
+{
+    data1_node *root = grs_read_iso2709(p, 1);
+    data1_element *e;
+
+    if (!root)
+       return 0;
+       
+    for (e=root->u.root.absyn->main_elements; e; e=e->next)
+    {
+       data1_tag *tag = e->tag;
+       
+       if (tag && tag->which == DATA1T_string &&
+           !yaz_matchstr(tag->value.string, "mc?"))
+               parse_data1_tree(p, tag->value.string, root);
+    }
+    return root;
+}
+
+
 data1_node *grs_read_marc(struct grs_read_info *p)
 {
-    data1_node *root = grs_read_iso2709(p);
+    data1_node *root = grs_read_iso2709(p, 0);
     data1_element *e;
 
     if (!root)
@@ -688,3 +759,12 @@ static struct recTypeGrs marc_type = {
 };
 
 RecTypeGrs recTypeGrs_marc = &marc_type;
+
+static struct recTypeGrs marcxml_type = {
+    "marcxml",
+    grs_init_marc,
+    grs_destroy_marc,
+    grs_read_marcxml
+};
+
+RecTypeGrs recTypeGrs_marcxml = &marcxml_type;