Fixed: double writting of code value
[yaz-moved-to-github.git] / src / marcdisp.c
index 46b1d80..5cda038 100644 (file)
@@ -241,6 +241,36 @@ 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) {
+       // TODO Map special codes to something possible for XML ELEMENT names
+
+       int encode = 0;
+       int index = 0;
+       for (index = 0; index < code_len; index++) {
+               if (!((code_data[index] >= '0' && code_data[index] <= '9') ||
+                         (code_data[index] >= 'a' && code_data[index] <= 'z') ||
+                         (code_data[index] >= 'A' && code_data[index] <= 'Z')))
+                       encode = 1;
+       }
+       int success = 0;
+       // Add as attribute
+       if (encode && attribute_name)
+               wrbuf_printf(buffer, " %s=\"", attribute_name);
+
+       if (!encode || attribute_name)
+               wrbuf_iconv_write_cdata(buffer, mt->iconv_cd, code_data, code_len);
+       else
+               success = -1;
+
+       if (encode && attribute_name)
+               wrbuf_printf(buffer, "\"");     // return error if we couldn't handle it.
+       return success;
+}
+
 #if YAZ_HAVE_XML2
 void yaz_marc_add_datafield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
                                 const char *indicator, size_t indicator_len)
@@ -256,17 +286,16 @@ void yaz_marc_add_datafield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
     mt->subfield_pp = &n->u.datafield.subfields;
 }
 
-struct yaz_marc_node* yaz_marc_add_datafield_turbo_xml(yaz_marc_t mt, char *tag_value)
+void yaz_marc_add_datafield_turbo_xml(yaz_marc_t mt, char *tag_value, char *indicators)
 {
     struct yaz_marc_node *n = yaz_marc_add_node(mt);
     n->which = YAZ_MARC_DATAFIELD;
     n->u.datafield.tag = tag_value;
-    n->u.datafield.indicator = 0;
+    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;
-    return n;
 }
 
 void yaz_marc_datafield_set_indicators(struct yaz_marc_node *n, char *indicator)
@@ -576,6 +605,7 @@ const char *record_name[2]          = { "record", "r"};
 const char *leader_name[2]     = { "leader", "l"};
 const char *controlfield_name[2]= { "controlfield", "c"};
 const char *datafield_name[2]          = { "datafield", "d"};
+const char *indicator_name[2]          = { "ind", "i"};
 const char *subfield_name[2]   = { "subfield", "s"};
 
 
@@ -635,42 +665,24 @@ static int yaz_marc_write_marcxml_ns1(yaz_marc_t mt, WRBUF wr,
         case YAZ_MARC_DATAFIELD:
 
                wrbuf_printf(wr, "  <%s", datafield_name[turbo]);
-            if (!turbo) {
+            if (!turbo)
                wrbuf_printf(wr, " tag=\"");
-               wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.datafield.tag,
+            wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.datafield.tag,
                                     strlen(n->u.datafield.tag));
-                   wrbuf_printf(wr, "\"");
-               if (n->u.datafield.indicator)
-                   {
-                   int i;
-                       for (i = 0; n->u.datafield.indicator[i]; i++)
-                       {
-                       wrbuf_printf(wr, " ind%d=\"", i+1);
-                           wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
-                                             n->u.datafield.indicator+i, 1);
-                           wrbuf_iconv_puts(wr, mt->iconv_cd, "\"");
-                       }
-               }
-                   wrbuf_printf(wr, ">\n");
-            } else {
-               // TODO Not CDATA.
-               wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.datafield.tag,
-                               strlen(n->u.datafield.tag));
-               // Write tag
-               wrbuf_printf(wr, ">\n");
-               if (n->u.datafield.indicator)
-               {
-                       int i;
-                       for (i = 0; n->u.datafield.indicator[i]; i++)
-                       {
-                               wrbuf_printf(wr, "    <i%d>", i+1);
-                               wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
-                                               n->u.datafield.indicator+i, 1);
-                               wrbuf_printf(wr, "</i%d>", i+1);
-                        wrbuf_puts(wr, "\n");
-                       }
-               }
+               if (!turbo)
+                       wrbuf_printf(wr, "\"");
+           if (n->u.datafield.indicator)
+           {
+               int i;
+               for (i = 0; n->u.datafield.indicator[i]; i++)
+               {
+                       wrbuf_printf(wr, " %s%d=\"", indicator_name[turbo], i+1);
+                       wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
+                                       n->u.datafield.indicator+i, 1);
+                       wrbuf_iconv_puts(wr, mt->iconv_cd, "\"");
+                               }
             }
+               wrbuf_printf(wr, ">\n");
             for (s = n->u.datafield.subfields; s; s = s->next)
             {
                 size_t using_code_len = get_subfield_len(mt, s->code_data,
@@ -682,9 +694,7 @@ static int yaz_marc_write_marcxml_ns1(yaz_marc_t mt, WRBUF wr,
                                         s->code_data, using_code_len);
                        wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
                                } else {
-                                       // TODO check this. encode special characters.
-                       wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
-                                        s->code_data, using_code_len);
+                                       element_name_append_attribute_value(mt, wr, "code", s->code_data, using_code_len);
                                        wrbuf_puts(wr, ">");
                                }
                 wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
@@ -692,9 +702,8 @@ static int yaz_marc_write_marcxml_ns1(yaz_marc_t mt, WRBUF wr,
                                         strlen(s->code_data + using_code_len));
                 marc_iconv_reset(mt, wr);
                                wrbuf_printf(wr, "</%s", subfield_name[turbo]);
-               if (turbo)
-                       wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
-                                       s->code_data, using_code_len);
+                               if (turbo)
+                               element_name_append_attribute_value(mt, wr, 0, s->code_data, using_code_len);
                 wrbuf_puts(wr, ">\n");
             }
             wrbuf_printf(wr, "  </%s", datafield_name[turbo]);
@@ -735,9 +744,9 @@ static int yaz_marc_write_marcxml_ns1(yaz_marc_t mt, WRBUF wr,
             wrbuf_printf(wr, " -->\n");
             break;
         case YAZ_MARC_LEADER:
-            wrbuf_printf(wr, "  <%s>", leader_name[turbo]);
-            wrbuf_iconv_write_cdata(wr, 
-                                    0 /* no charset conversion for leader */,
+               wrbuf_printf(wr, "  <%s>", leader_name[turbo]);
+               wrbuf_iconv_write_cdata(wr,
+                                    0 , /* no charset conversion for leader */
                                     n->u.leader, strlen(n->u.leader));
             wrbuf_printf(wr, "</%s>\n", leader_name[turbo]);
         }
@@ -943,14 +952,8 @@ void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n, xmlNod
             
             ind_val[0] = n->u.datafield.indicator[i];
             ind_val[1] = '\0';
-            if (!turbo) {
-                sprintf(ind_str, "ind%d", i+1);
-               xmlNewProp(ptr, BAD_CAST ind_str, BAD_CAST ind_val);
-            }
-            else {
-                sprintf(ind_str, "i%d", i+1);
-               xmlNewTextChild(ptr, ns_record, BAD_CAST ind_str, BAD_CAST ind_val);
-            }
+            sprintf(ind_str, "%s%d", indicator_name[turbo], i+1);
+                       xmlNewProp(ptr, BAD_CAST ind_str, BAD_CAST ind_val);
         }
     }
        WRBUF subfield_name = wrbuf_alloc();
@@ -967,6 +970,7 @@ void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n, xmlNod
                ptr_subfield = xmlNewTextChild(
                                ptr, ns_record,
                                BAD_CAST "subfield",  BAD_CAST wrbuf_cstr(wr_cdata));
+               // 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",
@@ -975,27 +979,16 @@ void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n, xmlNod
         else { // Turbo format
                wrbuf_rewind(subfield_name);
                wrbuf_puts(subfield_name, "s");
-               // TODO Map special codes to something possible for XML ELEMENT names
-               if ((s->code_data[0] >= '0' && s->code_data[0] <= '9') ||
-                   (s->code_data[0] >= 'a' && s->code_data[0] <= 'z') ||
-                               (s->code_data[0] >= 'A' && s->code_data[0] <= 'Z'))
-               {
-                       wrbuf_iconv_write(subfield_name, mt->iconv_cd,s->code_data, using_code_len);
-               }
-               else {
-                               char buffer[2*using_code_len + 1];
-                               int index;
-                               for (index = 0; index < using_code_len; index++) {
-                                       sprintf(buffer + 2*index, "%02X", (unsigned char) s->code_data[index] & 0xFF);
-                               };
-                               buffer[2*(index+1)] = 0;
-                               wrbuf_puts(subfield_name, "-");
-                               wrbuf_puts(subfield_name, buffer);
-                       yaz_log(YLOG_WARN, "Using numeric value in element name: %s", buffer);
-               }
+               int not_written = element_name_append_attribute_value(mt, subfield_name, 0, s->code_data, using_code_len) != 0;
                ptr_subfield = xmlNewTextChild(ptr, ns_record,
                                BAD_CAST wrbuf_cstr(subfield_name),
                                BAD_CAST wrbuf_cstr(wr_cdata));
+               if (not_written) {
+               // 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));
+               }
         }
     }
        wrbuf_destroy(subfield_name);
@@ -1377,11 +1370,6 @@ void yaz_marc_set_write_format(yaz_marc_t mt, int format)
 {
     if (mt) {
         mt->output_format = format;
-/*
-        // Force using libxml2
-        if (mt->output_format == YAZ_MARC_TMARCXML)
-               mt->write_using_libxml2 = 1;
-*/
     }
 }