MARC: skip non-ASCII characters always for leader
[yaz-moved-to-github.git] / src / marcdisp.c
index d4fdf6c..da48198 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2010 Index Data
+ * Copyright (C) 1995-2012 Index Data
  * See the file LICENSE for details.
  */
 
@@ -20,7 +20,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 #include <yaz/marcdisp.h>
 #include <yaz/wrbuf.h>
 #include <yaz/yaz-util.h>
@@ -140,10 +139,12 @@ static void marc_iconv_reset(yaz_marc_t mt, WRBUF wr)
 
 static int marc_exec_leader(const char *leader_spec, char *leader,
                             size_t size);
+#if YAZ_HAVE_XML2
 static int yaz_marc_write_xml_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
                                         const char *ns, 
                                         const char *format,
                                         const char *type);
+#endif
 
 static struct yaz_marc_node *yaz_marc_add_node(yaz_marc_t mt)
 {
@@ -243,13 +244,17 @@ void yaz_marc_add_datafield(yaz_marc_t mt, const char *tag,
     mt->subfield_pp = &n->u.datafield.subfields;
 }
 
-// Magic function: adds a attribute value to the element name if it is plain characters.
-// if not, and if the attribute name is not null, it will append a attribute element with the value
-// if attribute name is null it will return a non-zero value meaning it couldnt handle the value.
-
-int element_name_append_attribute_value(yaz_marc_t mt, WRBUF buffer, const char *attribute_name, char *code_data, size_t code_len)
+/** \brief adds a attribute value to the element name if it is plain chars
+    
+    If not, and if the attribute name is not null, it will append a
+    attribute element with the value if attribute name is null it will
+    return a non-zero value meaning it couldnt handle the value.
+*/
+static int element_name_append_attribute_value(
+    yaz_marc_t mt, WRBUF buffer,
+    const char *attribute_name, char *code_data, size_t code_len)
 {
-    // TODO Map special codes to something possible for XML ELEMENT names
+    /* TODO Map special codes to something possible for XML ELEMENT names */
 
     int encode = 0;
     int index = 0;
@@ -261,7 +266,7 @@ int element_name_append_attribute_value(yaz_marc_t mt, WRBUF buffer, const char
               (code_data[index] >= 'A' && code_data[index] <= 'Z')))
             encode = 1;
     }
-    // Add as attribute
+    /* Add as attribute */
     if (encode && attribute_name)
         wrbuf_printf(buffer, " %s=\"", attribute_name);
 
@@ -271,7 +276,7 @@ int element_name_append_attribute_value(yaz_marc_t mt, WRBUF buffer, const char
         success = -1;
 
     if (encode && attribute_name)
-        wrbuf_printf(buffer, "\"");    // return error if we couldn't handle it.
+        wrbuf_printf(buffer, "\""); /* return error if we couldn't handle it.*/
     return success;
 }
 
@@ -298,7 +303,7 @@ void yaz_marc_add_datafield_xml2(yaz_marc_t mt, char *tag_value, char *indicator
     n->u.datafield.indicator = indicators;
     n->u.datafield.subfields = 0;
 
-    // make subfield_pp the current (last one)
+    /* make subfield_pp the current (last one) */
     mt->subfield_pp = &n->u.datafield.subfields;
 }
 
@@ -337,6 +342,18 @@ void yaz_marc_add_subfield(yaz_marc_t mt,
     }
 }
 
+static void check_ascii(yaz_marc_t mt, char *leader, int offset,
+                        int ch_default)
+{
+    if (leader[offset] < ' ' || leader[offset] > 127)
+    {
+        yaz_marc_cprintf(mt, 
+                         "Leader character at offset %d is non-ASCII. "
+                         "Setting value to '%c'", offset, ch_default);
+        leader[offset] = ch_default;
+    }
+}
+
 void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
                          int *indicator_length,
                          int *identifier_length,
@@ -349,6 +366,11 @@ void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
 
     memcpy(leader, leader_c, 24);
 
+    check_ascii(mt, leader, 5, 'a');
+    check_ascii(mt, leader, 6, 'a');
+    check_ascii(mt, leader, 7, 'a');
+    check_ascii(mt, leader, 8, '#');
+    check_ascii(mt, leader, 9, '#');
     if (!atoi_n_check(leader+10, 1, indicator_length))
     {
         yaz_marc_cprintf(mt, 
@@ -372,6 +394,9 @@ void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
                          " Assuming 0");
         *base_address = 0;
     }
+    check_ascii(mt, leader, 17, '#');
+    check_ascii(mt, leader, 18, '#');
+    check_ascii(mt, leader, 19, '#');
     if (!atoi_n_check(leader+20, 1, length_data_entry))
     {
         yaz_marc_cprintf(mt, 
@@ -396,6 +421,7 @@ void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
         *length_implementation = 0;
         leader[22] = '0';
     }
+    check_ascii(mt, leader, 23, '0');
 
     if (mt->debug)
     {
@@ -716,7 +742,7 @@ static int yaz_marc_write_marcxml_wrbuf(yaz_marc_t mt, WRBUF wr,
                 wrbuf_puts(wr, ">\n");
             }
             wrbuf_printf(wr, "  </%s", datafield_name[turbo]);
-            //TODO Not CDATA
+            /* TODO Not CDATA */
             if (turbo)
                wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.datafield.tag,
                                         strlen(n->u.datafield.tag));
@@ -733,7 +759,7 @@ static int yaz_marc_write_marcxml_wrbuf(yaz_marc_t mt, WRBUF wr,
             }
             else
             {
-                //TODO convert special
+                /* TODO convert special */
                 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
                                        strlen(n->u.controlfield.tag));
                 wrbuf_iconv_puts(wr, mt->iconv_cd, ">");
@@ -743,7 +769,7 @@ static int yaz_marc_write_marcxml_wrbuf(yaz_marc_t mt, WRBUF wr,
                                     strlen(n->u.controlfield.data));
             marc_iconv_reset(mt, wr);
             wrbuf_printf(wr, "</%s", controlfield_name[turbo]);
-            //TODO convert special
+            /* TODO convert special */
             if (turbo)
                 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
                                        strlen(n->u.controlfield.tag));
@@ -823,7 +849,7 @@ int yaz_marc_write_turbomarc(yaz_marc_t mt, WRBUF wr)
     if (!mt->leader_spec)
         yaz_marc_modify_leader(mt, 9, "a");
     return yaz_marc_write_marcxml_ns(mt, wr,
-                                     "http://www.indexdata.com/MARC21/turboxml", 0, 0, 1);
+                                     "http://www.indexdata.com/turbomarc", 0, 0, 1);
 }
 
 int yaz_marc_write_marcxchange(yaz_marc_t mt, WRBUF wr,
@@ -846,7 +872,7 @@ void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n,
     struct yaz_marc_subfield *s;
     WRBUF subfield_name = wrbuf_alloc();
 
-    //TODO consider if safe
+    /* TODO consider if safe */
     char field[10];
     field[0] = 'd';
     strncpy(field + 1, n->u.datafield.tag, 3);
@@ -885,7 +911,7 @@ void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n,
                                        BAD_CAST wrbuf_cstr(wr_cdata));
         if (not_written)
         {
-            // Generate code attribute value and add
+            /* Generate code attribute value and add */
             wrbuf_rewind(wr_cdata);
             wrbuf_iconv_write(wr_cdata, mt->iconv_cd,s->code_data, using_code_len);
             xmlNewProp(ptr_subfield, BAD_CAST "code",  BAD_CAST wrbuf_cstr(wr_cdata));
@@ -958,13 +984,9 @@ static int yaz_marc_write_xml_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
             xmlAddChild(record_ptr, ptr);
             break;
         case YAZ_MARC_LEADER:
-        {
-            char *field = "leader";
-            field = "l";
-            xmlNewTextChild(record_ptr, ns_record, BAD_CAST field,
+            xmlNewTextChild(record_ptr, ns_record, BAD_CAST "l",
                             BAD_CAST n->u.leader);
-        }
-        break;
+            break;
         }
     }
     wrbuf_destroy(wr_cdata);
@@ -1187,8 +1209,7 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
         switch(n->which)
         {
         case YAZ_MARC_DATAFIELD:
-            wrbuf_printf(wr, "%.*s", indicator_length,
-                         n->u.datafield.indicator);
+            wrbuf_write(wr, n->u.datafield.indicator, indicator_length);
             for (s = n->u.datafield.subfields; s; s = s->next)
             {
                 wrbuf_putc(wr, ISO2709_IDFS);