Fix dup'ed identifers for MARC-8 encoding YAZ-650
[yaz-moved-to-github.git] / src / marcdisp.c
index 186f708..ff4c97e 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of the YAZ toolkit.
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2010 Index Data
+ * Copyright (C) 1995-2013 Index Data
  * See the file LICENSE for details.
  */
 
  * See the file LICENSE for details.
  */
 
@@ -20,7 +20,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #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>
 #include <yaz/marcdisp.h>
 #include <yaz/wrbuf.h>
 #include <yaz/yaz-util.h>
@@ -37,10 +36,10 @@ enum yaz_collection_state {
     collection_first,
     collection_second
 };
     collection_first,
     collection_second
 };
-   
+
 /** \brief node types for yaz_marc_node */
 enum YAZ_MARC_NODE_TYPE
 /** \brief node types for yaz_marc_node */
 enum YAZ_MARC_NODE_TYPE
-{ 
+{
     YAZ_MARC_DATAFIELD,
     YAZ_MARC_CONTROLFIELD,
     YAZ_MARC_COMMENT,
     YAZ_MARC_DATAFIELD,
     YAZ_MARC_CONTROLFIELD,
     YAZ_MARC_COMMENT,
@@ -87,7 +86,6 @@ struct yaz_marc_subfield {
 struct yaz_marc_t_ {
     WRBUF m_wr;
     NMEM nmem;
 struct yaz_marc_t_ {
     WRBUF m_wr;
     NMEM nmem;
-    int input_format;
     int output_format;
     int debug;
     int write_using_libxml2;
     int output_format;
     int debug;
     int write_using_libxml2;
@@ -141,7 +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);
 
 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)
 {
 
 static struct yaz_marc_node *yaz_marc_add_node(yaz_marc_t mt)
 {
@@ -163,8 +166,8 @@ void yaz_marc_add_controlfield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
     n->u.controlfield.data = nmem_text_node_cdata(ptr_data, mt->nmem);
 }
 
     n->u.controlfield.data = nmem_text_node_cdata(ptr_data, mt->nmem);
 }
 
-void yaz_marc_add_controlfield_turbo_xml(yaz_marc_t mt, const char *tag,
-                                   const xmlNode *ptr_data)
+void yaz_marc_add_controlfield_xml2(yaz_marc_t mt, char *tag,
+                                    const xmlNode *ptr_data)
 {
     struct yaz_marc_node *n = yaz_marc_add_node(mt);
     n->which = YAZ_MARC_CONTROLFIELD;
 {
     struct yaz_marc_node *n = yaz_marc_add_node(mt);
     n->which = YAZ_MARC_CONTROLFIELD;
@@ -241,6 +244,42 @@ void yaz_marc_add_datafield(yaz_marc_t mt, const char *tag,
     mt->subfield_pp = &n->u.datafield.subfields;
 }
 
     mt->subfield_pp = &n->u.datafield.subfields;
 }
 
+/** \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 */
+
+    int encode = 0;
+    int index = 0;
+    int success = 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;
+    }
+    /* 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)
 #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 +295,16 @@ void yaz_marc_add_datafield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
     mt->subfield_pp = &n->u.datafield.subfields;
 }
 
     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_xml2(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;
 {
     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) */
     mt->subfield_pp = &n->u.datafield.subfields;
     n->u.datafield.subfields = 0;
 
     /* 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)
 }
 
 void yaz_marc_datafield_set_indicators(struct yaz_marc_node *n, char *indicator)
@@ -304,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,
 void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
                          int *indicator_length,
                          int *identifier_length,
@@ -316,9 +366,14 @@ void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
 
     memcpy(leader, leader_c, 24);
 
 
     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))
     {
     if (!atoi_n_check(leader+10, 1, indicator_length))
     {
-        yaz_marc_cprintf(mt, 
+        yaz_marc_cprintf(mt,
                          "Indicator length at offset 10 should hold a digit."
                          " Assuming 2");
         leader[10] = '2';
                          "Indicator length at offset 10 should hold a digit."
                          " Assuming 2");
         leader[10] = '2';
@@ -326,7 +381,7 @@ void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
     }
     if (!atoi_n_check(leader+11, 1, identifier_length))
     {
     }
     if (!atoi_n_check(leader+11, 1, identifier_length))
     {
-        yaz_marc_cprintf(mt, 
+        yaz_marc_cprintf(mt,
                          "Identifier length at offset 11 should hold a digit."
                          " Assuming 2");
         leader[11] = '2';
                          "Identifier length at offset 11 should hold a digit."
                          " Assuming 2");
         leader[11] = '2';
@@ -334,14 +389,17 @@ void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
     }
     if (!atoi_n_check(leader+12, 5, base_address))
     {
     }
     if (!atoi_n_check(leader+12, 5, base_address))
     {
-        yaz_marc_cprintf(mt, 
+        yaz_marc_cprintf(mt,
                          "Base address at offsets 12..16 should hold a number."
                          " Assuming 0");
         *base_address = 0;
     }
                          "Base address at offsets 12..16 should hold a number."
                          " 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))
     {
     if (!atoi_n_check(leader+20, 1, length_data_entry))
     {
-        yaz_marc_cprintf(mt, 
+        yaz_marc_cprintf(mt,
                          "Length data entry at offset 20 should hold a digit."
                          " Assuming 4");
         *length_data_entry = 4;
                          "Length data entry at offset 20 should hold a digit."
                          " Assuming 4");
         *length_data_entry = 4;
@@ -357,12 +415,13 @@ void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
     }
     if (!atoi_n_check(leader+22, 1, length_implementation))
     {
     }
     if (!atoi_n_check(leader+22, 1, length_implementation))
     {
-        yaz_marc_cprintf(mt, 
+        yaz_marc_cprintf(mt,
                          "Length implementation at offset 22 should hold a digit."
                          " Assuming 0");
         *length_implementation = 0;
         leader[22] = '0';
     }
                          "Length implementation at offset 22 should hold a digit."
                          " Assuming 0");
         *length_implementation = 0;
         leader[22] = '0';
     }
+    check_ascii(mt, leader, 23, '0');
 
     if (mt->debug)
     {
 
     if (mt->debug)
     {
@@ -404,6 +463,7 @@ static size_t cdata_one_character(yaz_marc_t mt, const char *buf)
             size_t inbytesleft = i;
             size_t r = yaz_iconv(mt->iconv_cd, (char**) &inp, &inbytesleft,
                                  &outp, &outbytesleft);
             size_t inbytesleft = i;
             size_t r = yaz_iconv(mt->iconv_cd, (char**) &inp, &inbytesleft,
                                  &outp, &outbytesleft);
+            yaz_iconv(mt->iconv_cd, 0, 0, &outp, &outbytesleft);
             if (r != (size_t) (-1))
                 return i;  /* got a complete sequence */
         }
             if (r != (size_t) (-1))
                 return i;  /* got a complete sequence */
         }
@@ -411,7 +471,7 @@ static size_t cdata_one_character(yaz_marc_t mt, const char *buf)
     }
     return 1; /* we don't know */
 }
     }
     return 1; /* we don't know */
 }
-                              
+
 void yaz_marc_reset(yaz_marc_t mt)
 {
     nmem_reset(mt->nmem);
 void yaz_marc_reset(yaz_marc_t mt)
 {
     nmem_reset(mt->nmem);
@@ -432,7 +492,7 @@ int yaz_marc_write_check(yaz_marc_t mt, WRBUF wr)
             leader = n->u.leader;
             break;
         }
             leader = n->u.leader;
             break;
         }
-    
+
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
@@ -443,7 +503,7 @@ int yaz_marc_write_check(yaz_marc_t mt, WRBUF wr)
         switch(n->which)
         {
         case YAZ_MARC_COMMENT:
         switch(n->which)
         {
         case YAZ_MARC_COMMENT:
-            wrbuf_iconv_write(wr, mt->iconv_cd, 
+            wrbuf_iconv_write(wr, mt->iconv_cd,
                               n->u.comment, strlen(n->u.comment));
             wrbuf_puts(wr, "\n");
             break;
                               n->u.comment, strlen(n->u.comment));
             wrbuf_puts(wr, "\n");
             break;
@@ -478,7 +538,7 @@ int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr)
             leader = n->u.leader;
             break;
         }
             leader = n->u.leader;
             break;
         }
-    
+
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
@@ -496,12 +556,12 @@ int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr)
             {
                 size_t using_code_len = get_subfield_len(mt, s->code_data,
                                                          identifier_length);
             {
                 size_t using_code_len = get_subfield_len(mt, s->code_data,
                                                          identifier_length);
-                
-                wrbuf_puts (wr, mt->subfield_str); 
-                wrbuf_iconv_write(wr, mt->iconv_cd, s->code_data, 
+
+                wrbuf_puts (wr, mt->subfield_str);
+                wrbuf_iconv_write(wr, mt->iconv_cd, s->code_data,
                                   using_code_len);
                 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
                                   using_code_len);
                 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
-                wrbuf_iconv_puts(wr, mt->iconv_cd, 
+                wrbuf_iconv_puts(wr, mt->iconv_cd,
                                  s->code_data + using_code_len);
                 marc_iconv_reset(mt, wr);
             }
                                  s->code_data + using_code_len);
                 marc_iconv_reset(mt, wr);
             }
@@ -516,7 +576,7 @@ int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr)
             break;
         case YAZ_MARC_COMMENT:
             wrbuf_puts(wr, "(");
             break;
         case YAZ_MARC_COMMENT:
             wrbuf_puts(wr, "(");
-            wrbuf_iconv_write(wr, mt->iconv_cd, 
+            wrbuf_iconv_write(wr, mt->iconv_cd,
                               n->u.comment, strlen(n->u.comment));
             marc_iconv_reset(mt, wr);
             wrbuf_puts(wr, ")\n");
                               n->u.comment, strlen(n->u.comment));
             marc_iconv_reset(mt, wr);
             wrbuf_puts(wr, ")\n");
@@ -536,7 +596,7 @@ int yaz_marc_write_trailer(yaz_marc_t mt, WRBUF wr)
         switch(mt->output_format)
         {
         case YAZ_MARC_MARCXML:
         switch(mt->output_format)
         {
         case YAZ_MARC_MARCXML:
-        case YAZ_MARC_TMARCXML:
+        case YAZ_MARC_TURBOMARC:
             wrbuf_printf(wr, "</collection>\n");
             break;
         case YAZ_MARC_XCHANGE:
             wrbuf_printf(wr, "</collection>\n");
             break;
         case YAZ_MARC_XCHANGE:
@@ -559,8 +619,9 @@ int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr)
     case YAZ_MARC_LINE:
         return yaz_marc_write_line(mt, wr);
     case YAZ_MARC_MARCXML:
     case YAZ_MARC_LINE:
         return yaz_marc_write_line(mt, wr);
     case YAZ_MARC_MARCXML:
-    case YAZ_MARC_TMARCXML:
         return yaz_marc_write_marcxml(mt, wr);
         return yaz_marc_write_marcxml(mt, wr);
+    case YAZ_MARC_TURBOMARC:
+        return yaz_marc_write_turbomarc(mt, wr);
     case YAZ_MARC_XCHANGE:
         return yaz_marc_write_marcxchange(mt, wr, 0, 0); /* no format, type */
     case YAZ_MARC_ISO2709:
     case YAZ_MARC_XCHANGE:
         return yaz_marc_write_marcxchange(mt, wr, 0, 0); /* no format, type */
     case YAZ_MARC_ISO2709:
@@ -571,49 +632,52 @@ int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr)
     return -1;
 }
 
     return -1;
 }
 
-const char *collection_name[2]  = { "collection", "collection"};
-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 *subfield_name[2]   = { "subfield", "s"};
+static const char *record_name[2]      = { "record", "r"};
+static const char *leader_name[2]      = { "leader", "l"};
+static const char *controlfield_name[2] = { "controlfield", "c"};
+static const char *datafield_name[2]   = { "datafield", "d"};
+static const char *indicator_name[2]   = { "ind", "i"};
+static const char *subfield_name[2]    = { "subfield", "s"};
 
 
-
-/** \brief common MARC XML/Xchange writer
+/** \brief common MARC XML/Xchange/turbomarc writer
     \param mt handle
     \param wr WRBUF output
     \param ns XMLNS for the elements
     \param format record format (e.g. "MARC21")
     \param type record type (e.g. "Bibliographic")
     \param mt handle
     \param wr WRBUF output
     \param ns XMLNS for the elements
     \param format record format (e.g. "MARC21")
     \param type record type (e.g. "Bibliographic")
+    \param turbo =1 for turbomarc
+    \retval 0 OK
+    \retval -1 failure
 */
 */
-static int yaz_marc_write_marcxml_ns2(yaz_marc_t mt, WRBUF wr,
-                                      const char *ns, 
-                                      const char *format,
-                                      const char *type)
+static int yaz_marc_write_marcxml_wrbuf(yaz_marc_t mt, WRBUF wr,
+                                        const char *ns,
+                                        const char *format,
+                                        const char *type,
+                                        int turbo)
 {
     struct yaz_marc_node *n;
     int identifier_length;
     const char *leader = 0;
 
 {
     struct yaz_marc_node *n;
     int identifier_length;
     const char *leader = 0;
 
-    int turbo = yaz_marc_get_write_format(mt) == YAZ_MARC_TMARCXML;
-
     for (n = mt->nodes; n; n = n->next)
         if (n->which == YAZ_MARC_LEADER)
         {
             leader = n->u.leader;
             break;
         }
     for (n = mt->nodes; n; n = n->next)
         if (n->which == YAZ_MARC_LEADER)
         {
             leader = n->u.leader;
             break;
         }
-    
+
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
         return -1;
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
         return -1;
-    
+
     if (mt->enable_collection != no_collection)
     {
         if (mt->enable_collection == collection_first)
     if (mt->enable_collection != no_collection)
     {
         if (mt->enable_collection == collection_first)
-            wrbuf_printf(wr, "<%s xmlns=\"%s\">\n", collection_name[turbo], ns);
-        mt->enable_collection = collection_second;
+        {
+            wrbuf_printf(wr, "<collection xmlns=\"%s\">\n", ns);
+            mt->enable_collection = collection_second;
+        }
         wrbuf_printf(wr, "<%s", record_name[turbo]);
     }
     else
         wrbuf_printf(wr, "<%s", record_name[turbo]);
     }
     else
@@ -632,194 +696,85 @@ static int yaz_marc_write_marcxml_ns2(yaz_marc_t mt, WRBUF wr,
         switch(n->which)
         {
         case YAZ_MARC_DATAFIELD:
         switch(n->which)
         {
         case YAZ_MARC_DATAFIELD:
+
             wrbuf_printf(wr, "  <%s", datafield_name[turbo]);
             wrbuf_printf(wr, "  <%s", datafield_name[turbo]);
-            if (!turbo) {
+            if (!turbo)
                wrbuf_printf(wr, " tag=\"");
                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));
                                     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 {
-               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,
                                                          identifier_length);
                 wrbuf_printf(wr, "    <%s", subfield_name[turbo]);
             for (s = n->u.datafield.subfields; s; s = s->next)
             {
                 size_t using_code_len = get_subfield_len(mt, s->code_data,
                                                          identifier_length);
                 wrbuf_printf(wr, "    <%s", subfield_name[turbo]);
-                               if (!turbo) {
-                                       wrbuf_printf(wr, " code=\"");
-                       wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
-                                        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);
-                                       wrbuf_puts(wr, ">\n");
-                               }
+                if (!turbo)
+                {
+                    wrbuf_printf(wr, " code=\"");
+                    wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
+                                            s->code_data, using_code_len);
+                    wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
+                }
+                else
+                {
+                    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,
                                         s->code_data + using_code_len,
                                         strlen(s->code_data + using_code_len));
                 marc_iconv_reset(mt, wr);
                 wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
                                         s->code_data + using_code_len,
                                         strlen(s->code_data + using_code_len));
                 marc_iconv_reset(mt, wr);
-                               wrbuf_printf(wr, "</%s>", subfield_name[turbo]);
-                wrbuf_puts(wr, "\n");
+                wrbuf_printf(wr, "</%s", subfield_name[turbo]);
+                if (turbo)
+                    element_name_append_attribute_value(mt, wr, 0, s->code_data, using_code_len);
+                wrbuf_puts(wr, ">\n");
             }
             }
-            wrbuf_printf(wr, "  </%s>\n", datafield_name[turbo]);
+            wrbuf_printf(wr, "  </%s", datafield_name[turbo]);
+            /* TODO Not CDATA */
+            if (turbo)
+               wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.datafield.tag,
+                                        strlen(n->u.datafield.tag));
+            wrbuf_printf(wr, ">\n");
             break;
         case YAZ_MARC_CONTROLFIELD:
             break;
         case YAZ_MARC_CONTROLFIELD:
-               wrbuf_printf(wr, "  <%s", controlfield_name[turbo]);
-               if (!turbo) {
+            wrbuf_printf(wr, "  <%s", controlfield_name[turbo]);
+            if (!turbo)
+            {
                wrbuf_printf(wr, " tag=\"");
                wrbuf_printf(wr, " tag=\"");
-                       wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
+                wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
                                        strlen(n->u.controlfield.tag));
                                        strlen(n->u.controlfield.tag));
-                       wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
-               }
-               else {
-                       //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, ">");
-               }
-               wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
-                                                                       n->u.controlfield.data,
-                                                                       strlen(n->u.controlfield.data));
-               marc_iconv_reset(mt, wr);
-               wrbuf_printf(wr, "</%s>", controlfield_name[turbo]);
-               wrbuf_puts(wr, "\n");
-            break;
-        case YAZ_MARC_COMMENT:
-            wrbuf_printf(wr, "<!-- ");
-            wrbuf_puts(wr, n->u.comment);
-            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 */,
-                                    n->u.leader, strlen(n->u.leader));
-            wrbuf_printf(wr, "  </%s>", leader_name[turbo]);
-        }
-    }
-    wrbuf_printf(wr, "</%s", record_name[turbo]);
-    return 0;
-}
-
-static int yaz_marc_write_marcxml_ns1(yaz_marc_t mt, WRBUF wr,
-                                      const char *ns, 
-                                      const char *format,
-                                      const char *type)
-{
-    struct yaz_marc_node *n;
-    int identifier_length;
-    const char *leader = 0;
-
-    for (n = mt->nodes; n; n = n->next)
-        if (n->which == YAZ_MARC_LEADER)
-        {
-            leader = n->u.leader;
-            break;
-        }
-    
-    if (!leader)
-        return -1;
-    if (!atoi_n_check(leader+11, 1, &identifier_length))
-        return -1;
-    
-    if (mt->enable_collection != no_collection)
-    {
-        if (mt->enable_collection == collection_first)
-            wrbuf_printf(wr, "<collection xmlns=\"%s\">\n", ns);
-        mt->enable_collection = collection_second;
-        wrbuf_printf(wr, "<record");
-    }
-    else
-    {
-        wrbuf_printf(wr, "<record xmlns=\"%s\"", ns);
-    }
-    if (format)
-        wrbuf_printf(wr, " format=\"%.80s\"", format);
-    if (type)
-        wrbuf_printf(wr, " type=\"%.80s\"", type);
-    wrbuf_printf(wr, ">\n");
-    for (n = mt->nodes; n; n = n->next)
-    {
-        struct yaz_marc_subfield *s;
-
-        switch(n->which)
-        {
-        case YAZ_MARC_DATAFIELD:
-            wrbuf_printf(wr, "  <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_iconv_puts(wr, mt->iconv_cd, "\">");
             }
             }
-            wrbuf_printf(wr, ">\n");
-            for (s = n->u.datafield.subfields; s; s = s->next)
+            else
             {
             {
-                size_t using_code_len = get_subfield_len(mt, s->code_data,
-                                                         identifier_length);
-                wrbuf_iconv_puts(wr, mt->iconv_cd, "    <subfield code=\"");
-                wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
-                                        s->code_data, using_code_len);
-                wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
-                wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
-                                        s->code_data + using_code_len,
-                                        strlen(s->code_data + using_code_len));
-                marc_iconv_reset(mt, wr);
-                wrbuf_iconv_puts(wr, mt->iconv_cd, "</subfield>");
-                wrbuf_puts(wr, "\n");
+                /* 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, ">");
             }
             }
-            wrbuf_printf(wr, "  </datafield>\n");
-            break;
-        case YAZ_MARC_CONTROLFIELD:
-            wrbuf_printf(wr, "  <controlfield tag=\"");
-            wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
-                                    strlen(n->u.controlfield.tag));
-            wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
             wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
                                     n->u.controlfield.data,
                                     strlen(n->u.controlfield.data));
             wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
                                     n->u.controlfield.data,
                                     strlen(n->u.controlfield.data));
-
             marc_iconv_reset(mt, wr);
             marc_iconv_reset(mt, wr);
-            wrbuf_iconv_puts(wr, mt->iconv_cd, "</controlfield>");
-            wrbuf_puts(wr, "\n");
+            wrbuf_printf(wr, "</%s", controlfield_name[turbo]);
+            /* TODO convert special */
+            if (turbo)
+                wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
+                                       strlen(n->u.controlfield.tag));
+            wrbuf_puts(wr, ">\n");
             break;
         case YAZ_MARC_COMMENT:
             wrbuf_printf(wr, "<!-- ");
             break;
         case YAZ_MARC_COMMENT:
             wrbuf_printf(wr, "<!-- ");
@@ -827,22 +782,22 @@ 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, " -->\n");
             break;
         case YAZ_MARC_LEADER:
-            wrbuf_printf(wr, "  <leader>");
-            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));
                                     n->u.leader, strlen(n->u.leader));
-            wrbuf_printf(wr, "</leader>\n");
+            wrbuf_printf(wr, "</%s>\n", leader_name[turbo]);
         }
     }
         }
     }
-    wrbuf_puts(wr, "</record>\n");
+    wrbuf_printf(wr, "</%s>\n", record_name[turbo]);
     return 0;
 }
 
     return 0;
 }
 
-
 static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr,
 static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr,
-                                     const char *ns, 
+                                     const char *ns,
                                      const char *format,
                                      const char *format,
-                                     const char *type)
+                                     const char *type,
+                                     int turbo)
 {
     if (mt->write_using_libxml2)
     {
 {
     if (mt->write_using_libxml2)
     {
@@ -850,10 +805,10 @@ static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr,
         int ret;
         xmlNode *root_ptr;
 
         int ret;
         xmlNode *root_ptr;
 
-        if (yaz_marc_get_write_format(mt) == YAZ_MARC_MARCXML)
-               ret = yaz_marc_write_xml(mt, &root_ptr, ns, format, type);
-        else // Check for Turbo XML
-               ret = yaz_marc_write_turbo_xml(mt, &root_ptr, ns, format, type);
+        if (!turbo)
+            ret = yaz_marc_write_xml(mt, &root_ptr, ns, format, type);
+        else
+            ret = yaz_marc_write_xml_turbo_xml(mt, &root_ptr, ns, format, type);
         if (ret == 0)
         {
             xmlChar *buf_out;
         if (ret == 0)
         {
             xmlChar *buf_out;
@@ -874,7 +829,7 @@ static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr,
 #endif
     }
     else
 #endif
     }
     else
-        return yaz_marc_write_marcxml_ns1(mt, wr, ns, format, type);
+        return yaz_marc_write_marcxml_wrbuf(mt, wr, ns, format, type, turbo);
 }
 
 int yaz_marc_write_marcxml(yaz_marc_t mt, WRBUF wr)
 }
 
 int yaz_marc_write_marcxml(yaz_marc_t mt, WRBUF wr)
@@ -883,11 +838,19 @@ int yaz_marc_write_marcxml(yaz_marc_t mt, WRBUF wr)
     /* http://www.loc.gov/marc/bibliographic/ecbdldrd.html#mrcblea */
     if (!mt->leader_spec)
         yaz_marc_modify_leader(mt, 9, "a");
     /* http://www.loc.gov/marc/bibliographic/ecbdldrd.html#mrcblea */
     if (!mt->leader_spec)
         yaz_marc_modify_leader(mt, 9, "a");
-    char *name_space = "http://www.loc.gov/MARC21/slim";
-    if (mt->output_format == YAZ_MARC_TMARCXML)
-       name_space = "http://www.indexdata.com/MARC21/turboxml";
-    return yaz_marc_write_marcxml_ns(mt, wr, name_space,
-                                     0, 0);
+    return yaz_marc_write_marcxml_ns(mt, wr,
+                                     "http://www.loc.gov/MARC21/slim",
+                                     0, 0, 0);
+}
+
+int yaz_marc_write_turbomarc(yaz_marc_t mt, WRBUF wr)
+{
+    /* set leader 09 to 'a' for UNICODE */
+    /* http://www.loc.gov/marc/bibliographic/ecbdldrd.html#mrcblea */
+    if (!mt->leader_spec)
+        yaz_marc_modify_leader(mt, 9, "a");
+    return yaz_marc_write_marcxml_ns(mt, wr,
+                                     "http://www.indexdata.com/turbomarc", 0, 0, 1);
 }
 
 int yaz_marc_write_marcxchange(yaz_marc_t mt, WRBUF wr,
 }
 
 int yaz_marc_write_marcxchange(yaz_marc_t mt, WRBUF wr,
@@ -896,28 +859,27 @@ int yaz_marc_write_marcxchange(yaz_marc_t mt, WRBUF wr,
 {
     return yaz_marc_write_marcxml_ns(mt, wr,
                                      "info:lc/xmlns/marcxchange-v1",
 {
     return yaz_marc_write_marcxml_ns(mt, wr,
                                      "info:lc/xmlns/marcxchange-v1",
-                                     0, 0);
+                                     0, 0, 0);
 }
 
 #if YAZ_HAVE_XML2
 
 }
 
 #if YAZ_HAVE_XML2
 
-void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n, xmlNode *record_ptr, xmlNsPtr ns_record, WRBUF wr_cdata, int identifier_length)
+void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n,
+                                  xmlNode *record_ptr,
+                                  xmlNsPtr ns_record, WRBUF wr_cdata,
+                                  int identifier_length)
 {
     xmlNode *ptr;
     struct yaz_marc_subfield *s;
 {
     xmlNode *ptr;
     struct yaz_marc_subfield *s;
-    int turbo = mt->output_format == YAZ_MARC_TMARCXML;
-    if (!turbo) {
-        ptr = xmlNewChild(record_ptr, ns_record, BAD_CAST "datafield", 0);
-        xmlNewProp(ptr, BAD_CAST "tag", BAD_CAST n->u.datafield.tag);
-    }
-    else {
-        //TODO consider if safe
-       char field[10];
-       field[0] = 'd';
-        strncpy(field + 1, n->u.datafield.tag, 3);
-        field[4] = '\0';
-        ptr = xmlNewChild(record_ptr, ns_record, BAD_CAST field, 0);
-    }
+    WRBUF subfield_name = wrbuf_alloc();
+
+    /* TODO consider if safe */
+    char field[10];
+    field[0] = 'd';
+    strncpy(field + 1, n->u.datafield.tag, 3);
+    field[4] = '\0';
+    ptr = xmlNewChild(record_ptr, ns_record, BAD_CAST field, 0);
+
     if (n->u.datafield.indicator)
     {
         int i;
     if (n->u.datafield.indicator)
     {
         int i;
@@ -925,71 +887,44 @@ void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n, xmlNod
         {
             char ind_str[6];
             char ind_val[2];
         {
             char ind_str[6];
             char ind_val[2];
-            
+
             ind_val[0] = n->u.datafield.indicator[i];
             ind_val[1] = '\0';
             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[1], i+1);
+            xmlNewProp(ptr, BAD_CAST ind_str, BAD_CAST ind_val);
         }
     }
         }
     }
-       WRBUF subfield_name = wrbuf_alloc();
     for (s = n->u.datafield.subfields; s; s = s->next)
     {
     for (s = n->u.datafield.subfields; s; s = s->next)
     {
+        int not_written;
         xmlNode *ptr_subfield;
         size_t using_code_len = get_subfield_len(mt, s->code_data,
                                                  identifier_length);
         wrbuf_rewind(wr_cdata);
         wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, s->code_data + using_code_len);
         marc_iconv_reset(mt, wr_cdata);
         xmlNode *ptr_subfield;
         size_t using_code_len = get_subfield_len(mt, s->code_data,
                                                  identifier_length);
         wrbuf_rewind(wr_cdata);
         wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, s->code_data + using_code_len);
         marc_iconv_reset(mt, wr_cdata);
-        
-        if (!turbo) {
-               ptr_subfield = xmlNewTextChild(
-                               ptr, ns_record,
-                               BAD_CAST "subfield",  BAD_CAST wrbuf_cstr(wr_cdata));
-               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));
-        }
-        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);
-               }
-               ptr_subfield = xmlNewTextChild(ptr, ns_record,
-                               BAD_CAST wrbuf_cstr(subfield_name),
-                               BAD_CAST wrbuf_cstr(wr_cdata));
+
+        wrbuf_rewind(subfield_name);
+        wrbuf_puts(subfield_name, "s");
+        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);
+    wrbuf_destroy(subfield_name);
 }
 
 }
 
-int yaz_marc_write_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
-                       const char *ns, 
-                       const char *format,
-                       const char *type)
+static int yaz_marc_write_xml_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
+                                        const char *ns,
+                                        const char *format,
+                                        const char *type)
 {
     struct yaz_marc_node *n;
     int identifier_length;
 {
     struct yaz_marc_node *n;
     int identifier_length;
@@ -997,14 +932,14 @@ int yaz_marc_write_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
     xmlNode *record_ptr;
     xmlNsPtr ns_record;
     WRBUF wr_cdata = 0;
     xmlNode *record_ptr;
     xmlNsPtr ns_record;
     WRBUF wr_cdata = 0;
-    int turbo = mt->output_format == YAZ_MARC_TMARCXML;
+
     for (n = mt->nodes; n; n = n->next)
         if (n->which == YAZ_MARC_LEADER)
         {
             leader = n->u.leader;
             break;
         }
     for (n = mt->nodes; n; n = n->next)
         if (n->which == YAZ_MARC_LEADER)
         {
             leader = n->u.leader;
             break;
         }
-    
+
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
@@ -1024,49 +959,34 @@ int yaz_marc_write_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
         xmlNewProp(record_ptr, BAD_CAST "type", BAD_CAST type);
     for (n = mt->nodes; n; n = n->next)
     {
         xmlNewProp(record_ptr, BAD_CAST "type", BAD_CAST type);
     for (n = mt->nodes; n; n = n->next)
     {
-        struct yaz_marc_subfield *s;
         xmlNode *ptr;
 
         xmlNode *ptr;
 
+        char field[10];
+        field[0] = 'c';
+        field[4] = '\0';
+
         switch(n->which)
         {
         case YAZ_MARC_DATAFIELD:
         switch(n->which)
         {
         case YAZ_MARC_DATAFIELD:
-               add_marc_datafield_turbo_xml(mt, n, record_ptr, ns_record, wr_cdata, identifier_length);
+            add_marc_datafield_turbo_xml(mt, n, record_ptr, ns_record, wr_cdata, identifier_length);
             break;
         case YAZ_MARC_CONTROLFIELD:
             wrbuf_rewind(wr_cdata);
             wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, n->u.controlfield.data);
             marc_iconv_reset(mt, wr_cdata);
             break;
         case YAZ_MARC_CONTROLFIELD:
             wrbuf_rewind(wr_cdata);
             wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, n->u.controlfield.data);
             marc_iconv_reset(mt, wr_cdata);
-            
-            if (!turbo) {
-                               ptr = xmlNewTextChild(record_ptr, ns_record,
-                                                                         BAD_CAST "controlfield",
-                                                                         BAD_CAST wrbuf_cstr(wr_cdata));
-                               xmlNewProp(ptr, BAD_CAST "tag", BAD_CAST n->u.controlfield.tag);
-            }
-            else {
-               // TODO required iconv?
-               char field[10];
-                               field[0] = 'c';
-                strncpy(field + 1, n->u.controlfield.tag, 3);
-                field[4] = '\0';
-                ptr = xmlNewTextChild(record_ptr, ns_record,
-                                                                         BAD_CAST field,
-                                                                         BAD_CAST wrbuf_cstr(wr_cdata));
-            }
 
 
+            strncpy(field + 1, n->u.controlfield.tag, 3);
+            ptr = xmlNewTextChild(record_ptr, ns_record,
+                                  BAD_CAST field,
+                                  BAD_CAST wrbuf_cstr(wr_cdata));
             break;
         case YAZ_MARC_COMMENT:
             ptr = xmlNewComment(BAD_CAST n->u.comment);
             xmlAddChild(record_ptr, ptr);
             break;
         case YAZ_MARC_LEADER:
             break;
         case YAZ_MARC_COMMENT:
             ptr = xmlNewComment(BAD_CAST n->u.comment);
             xmlAddChild(record_ptr, ptr);
             break;
         case YAZ_MARC_LEADER:
-                       {
-                               char *field = "leader";
-                               if (turbo)
-                                       field = "l";
-                               xmlNewTextChild(record_ptr, ns_record, BAD_CAST field,
-                                                               BAD_CAST n->u.leader);
-                       }
+            xmlNewTextChild(record_ptr, ns_record, BAD_CAST "l",
+                            BAD_CAST n->u.leader);
             break;
         }
     }
             break;
         }
     }
@@ -1076,7 +996,7 @@ int yaz_marc_write_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
 
 
 int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr,
 
 
 int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr,
-                       const char *ns, 
+                       const char *ns,
                        const char *format,
                        const char *type)
 {
                        const char *format,
                        const char *type)
 {
@@ -1093,7 +1013,7 @@ int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr,
             leader = n->u.leader;
             break;
         }
             leader = n->u.leader;
             break;
         }
-    
+
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+11, 1, &identifier_length))
@@ -1159,11 +1079,11 @@ int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr,
             wrbuf_rewind(wr_cdata);
             wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, n->u.controlfield.data);
             marc_iconv_reset(mt, wr_cdata);
             wrbuf_rewind(wr_cdata);
             wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, n->u.controlfield.data);
             marc_iconv_reset(mt, wr_cdata);
-            
+
             ptr = xmlNewTextChild(record_ptr, ns_record,
                                   BAD_CAST "controlfield",
                                   BAD_CAST wrbuf_cstr(wr_cdata));
             ptr = xmlNewTextChild(record_ptr, ns_record,
                                   BAD_CAST "controlfield",
                                   BAD_CAST wrbuf_cstr(wr_cdata));
-            
+
             xmlNewProp(ptr, BAD_CAST "tag", BAD_CAST n->u.controlfield.tag);
             break;
         case YAZ_MARC_COMMENT:
             xmlNewProp(ptr, BAD_CAST "tag", BAD_CAST n->u.controlfield.tag);
             break;
         case YAZ_MARC_COMMENT:
@@ -1180,9 +1100,6 @@ int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr,
     return 0;
 }
 
     return 0;
 }
 
-
-
-
 #endif
 
 int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
 #endif
 
 int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
@@ -1197,11 +1114,11 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
     const char *leader = 0;
     WRBUF wr_dir, wr_head, wr_data_tmp;
     int base_address;
     const char *leader = 0;
     WRBUF wr_dir, wr_head, wr_data_tmp;
     int base_address;
-    
+
     for (n = mt->nodes; n; n = n->next)
         if (n->which == YAZ_MARC_LEADER)
             leader = n->u.leader;
     for (n = mt->nodes; n; n = n->next)
         if (n->which == YAZ_MARC_LEADER)
             leader = n->u.leader;
-    
+
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+10, 1, &indicator_length))
     if (!leader)
         return -1;
     if (!atoi_n_check(leader+10, 1, &indicator_length))
@@ -1244,7 +1161,7 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
             wrbuf_printf(wr_dir, "%.3s", n->u.controlfield.tag);
 
             wrbuf_rewind(wr_data_tmp);
             wrbuf_printf(wr_dir, "%.3s", n->u.controlfield.tag);
 
             wrbuf_rewind(wr_data_tmp);
-            wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd, 
+            wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd,
                              n->u.controlfield.data);
             marc_iconv_reset(mt, wr_data_tmp);
             wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');/* field sep */
                              n->u.controlfield.data);
             marc_iconv_reset(mt, wr_data_tmp);
             wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');/* field sep */
@@ -1279,7 +1196,7 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
     wrbuf_printf(wr_head, "%05d", base_address);
     /* from "original" leader */
     wrbuf_write(wr_head, leader+17, 7);
     wrbuf_printf(wr_head, "%05d", base_address);
     /* from "original" leader */
     wrbuf_write(wr_head, leader+17, 7);
-    
+
     wrbuf_write(wr, wrbuf_buf(wr_head), 24);
     wrbuf_write(wr, wrbuf_buf(wr_dir), wrbuf_len(wr_dir));
     wrbuf_destroy(wr_head);
     wrbuf_write(wr, wrbuf_buf(wr_head), 24);
     wrbuf_write(wr, wrbuf_buf(wr_dir), wrbuf_len(wr_dir));
     wrbuf_destroy(wr_head);
@@ -1293,8 +1210,7 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
         switch(n->which)
         {
         case YAZ_MARC_DATAFIELD:
         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);
             for (s = n->u.datafield.subfields; s; s = s->next)
             {
                 wrbuf_putc(wr, ISO2709_IDFS);
@@ -1344,48 +1260,11 @@ int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize,
     return r;
 }
 
     return r;
 }
 
-void yaz_marc_set_read_format(yaz_marc_t mt, int format)
-{
-    if (mt)
-        mt->input_format = format;
-}
-
-int yaz_marc_get_read_format(yaz_marc_t mt)
-{
-    if (mt)
-        return mt->input_format;
-    return -1;
-}
-
-
-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;
-    }
-}
-
-int yaz_marc_get_write_format(yaz_marc_t mt)
-{
-    if (mt)
-        return mt->output_format;
-    return -1;
-}
-
-
-/**
- * Deprecated, use yaz_marc_set_write_format
- */
 void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
 {
 void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
 {
-       yaz_marc_set_write_format(mt, xmlmode);
+    mt->output_format = xmlmode;
 }
 
 }
 
-
-
 void yaz_marc_debug(yaz_marc_t mt, int level)
 {
     if (mt)
 void yaz_marc_debug(yaz_marc_t mt, int level)
 {
     if (mt)
@@ -1448,7 +1327,7 @@ static int marc_exec_leader(const char *leader_spec, char *leader, size_t size)
         {
             const char *vp = strchr(val+1, '\'');
             size_t len;
         {
             const char *vp = strchr(val+1, '\'');
             size_t len;
-            
+
             if (!vp)
                 return -1;
             len = vp-val-1;
             if (!vp)
                 return -1;
             len = vp-val-1;
@@ -1474,13 +1353,13 @@ static int marc_exec_leader(const char *leader_spec, char *leader, size_t size)
 
 int yaz_marc_decode_formatstr(const char *arg)
 {
 
 int yaz_marc_decode_formatstr(const char *arg)
 {
-    int mode = -1; 
+    int mode = -1;
     if (!strcmp(arg, "marc"))
         mode = YAZ_MARC_ISO2709;
     if (!strcmp(arg, "marcxml"))
         mode = YAZ_MARC_MARCXML;
     if (!strcmp(arg, "marc"))
         mode = YAZ_MARC_ISO2709;
     if (!strcmp(arg, "marcxml"))
         mode = YAZ_MARC_MARCXML;
-    if (!strcmp(arg, "tmarcxml"))
-        mode = YAZ_MARC_TMARCXML;
+    if (!strcmp(arg, "turbomarc"))
+        mode = YAZ_MARC_TURBOMARC;
     if (!strcmp(arg, "marcxchange"))
         mode = YAZ_MARC_XCHANGE;
     if (!strcmp(arg, "line"))
     if (!strcmp(arg, "marcxchange"))
         mode = YAZ_MARC_XCHANGE;
     if (!strcmp(arg, "line"))
@@ -1493,12 +1372,6 @@ void yaz_marc_write_using_libxml2(yaz_marc_t mt, int enable)
     mt->write_using_libxml2 = enable;
 }
 
     mt->write_using_libxml2 = enable;
 }
 
-int yaz_marc_is_turbo_format(yaz_marc_t mt)
-{
-    return mt->output_format == YAZ_MARC_TMARCXML;
-}
-
-
 /*
  * Local variables:
  * c-basic-offset: 4
 /*
  * Local variables:
  * c-basic-offset: 4