ZOOM_record_get: pretty xml format (bug #3182)
authorAdam Dickmeiss <adam@indexdata.dk>
Thu, 21 Jan 2010 12:18:18 +0000 (13:18 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Thu, 21 Jan 2010 12:18:18 +0000 (13:18 +0100)
ZOOM_record_get supports new parameter "format" which makes it pretty
format XML record content.

NEWS
doc/zoom.xml
src/zoom-c.c
src/zoom-p.h

diff --git a/NEWS b/NEWS
index 3ac49d6..b5853d3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+ZOOM_record_get supports new parameter "format" which makes it format
+XML record content.
+
 --- 4.0.0 2010/01/20
 
 Windows binaries for YAZ now compiled with Visual Studio 2008 (VC9).
index ebf09ee..041949a 100644 (file)
@@ -726,7 +726,7 @@ ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn)
     The <parameter>type</parameter> is a string of the format:
    </para>
    <para>
-    <replaceable>form</replaceable>[; charset=<replaceable>from</replaceable>[,<replaceable>to</replaceable>]]
+    <replaceable>form</replaceable>[;charset=<replaceable>from</replaceable>[,<replaceable>to</replaceable>]][;format=<replaceable>v</replaceable>]
    </para>
    <para>
     where <replaceable>form</replaceable> specifies the format of the
@@ -739,6 +739,12 @@ ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn)
     If <replaceable>to</replaceable> is omitted UTF-8 is assumed.
    </para>
    <para>
+    The format argument controls whether record data should be XML
+    pretty-printed (post process operation).
+    It is enabled only if format value <replaceable>v</replaceable> is 
+    <literal>1</literal> and the record content is XML well-formed.
+   </para>
+   <para>
     In addition, for certain types, the length
     <literal>len</literal> passed will be set to the size in bytes of
     the returned information. 
index cb6144e..42f30a0 100644 (file)
@@ -1011,6 +1011,20 @@ ZOOM_API(int)
     return 0;
 }
 
+static void ZOOM_record_release(ZOOM_record rec)
+{
+    if (!rec)
+        return;
+    if (rec->wrbuf)
+        wrbuf_destroy(rec->wrbuf);
+#if YAZ_HAVE_XML2
+    if (rec->xml_mem)
+        xmlFree(rec->xml_mem);
+#endif
+    if (rec->odr)
+        odr_destroy(rec->odr);
+}
+
 ZOOM_API(void)
     ZOOM_resultset_cache_reset(ZOOM_resultset r)
 {
@@ -1020,8 +1034,7 @@ ZOOM_API(void)
         ZOOM_record_cache rc;
         for (rc = r->record_hash[i]; rc; rc = rc->next)
         {
-            if (rc->rec.wrbuf)
-                wrbuf_destroy(rc->rec.wrbuf);
+            ZOOM_record_release(&rc->rec);
         }
         r->record_hash[i] = 0;
     }
@@ -1780,6 +1793,10 @@ ZOOM_API(ZOOM_record)
     nrec = (ZOOM_record) xmalloc(sizeof(*nrec));
     nrec->odr = odr_createmem(ODR_DECODE);
     nrec->wrbuf = 0;
+#if YAZ_HAVE_XML2
+    nrec->xml_mem = 0;
+    nrec->xml_size = 0;
+#endif
     odr_setbuf(nrec->odr, buf, size, 0);
     z_NamePlusRecord(nrec->odr, &nrec->npr, 0, 0);
     
@@ -1827,11 +1844,7 @@ ZOOM_API(ZOOM_record)
 ZOOM_API(void)
     ZOOM_record_destroy(ZOOM_record rec)
 {
-    if (!rec)
-        return;
-    if (rec->wrbuf)
-        wrbuf_destroy(rec->wrbuf);
-    odr_destroy(rec->odr);
+    ZOOM_record_release(rec);
     xfree(rec);
 }
 
@@ -2058,12 +2071,39 @@ ZOOM_API(int)
     return 0;
 }
 
+static const char *get_record_format(ZOOM_record rec, int *len,
+                                     Z_NamePlusRecord *npr,
+                                     int marctype, const char *charset,
+                                     const char *format)
+{
+    const char *res = return_record(rec, len, npr, marctype, charset);
+#if YAZ_HAVE_XML2
+    if (*format == '1' && len)
+    {
+        /* try to XML format res */
+        xmlKeepBlanksDefault(0);
+        xmlDocPtr doc = xmlParseMemory(res, *len);
+        if (doc)
+        {
+            if (rec->xml_mem)
+                xmlFree(rec->xml_mem);
+            xmlDocDumpFormatMemory(doc, &rec->xml_mem, &rec->xml_size, 1);
+            xmlFreeDoc(doc);
+            res = (char *) rec->xml_mem;
+            *len = rec->xml_size;
+        } 
+    }
+#endif
+    return res;
+}
+
+
 ZOOM_API(const char *)
     ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len)
 {
     char type[40];
     char charset[40];
-    char xpath[512];
+    char format[3];
     const char *cp;
     size_t i;
     Z_NamePlusRecord *npr;
@@ -2078,41 +2118,43 @@ ZOOM_API(const char *)
         return 0;
 
     cp = type_spec;
-    for (i = 0; cp[i] && i < sizeof(type)-1; i++)
-    {
-        if (cp[i] == ';' || cp[i] == ' ')
-            break;
+    for (i = 0; cp[i] && cp[i] != ';' && cp[i] != ' ' && i < sizeof(type)-1;
+         i++)
         type[i] = cp[i];
-    }
     type[i] = '\0';
     charset[0] = '\0';
-    while (type_spec[i] == ';')
+    format[0] = '\0';
+    while (1)
     {
+        while (cp[i] == ' ')
+            i++;
+        if (cp[i] != ';')
+            break;
         i++;
-        while (type_spec[i] == ' ')
+        while (cp[i] == ' ')
             i++;
-        if (!strncmp(type_spec+i, "charset=", 8))
+        if (!strncmp(cp + i, "charset=", 8))
         {
             size_t j = 0;
             i = i + 8; /* skip charset= */
-            for (j = 0; type_spec[i]  && j < sizeof(charset)-1; i++, j++)
+            for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++)
             {
-                if (type_spec[i] == ';' || type_spec[i] == ' ')
-                    break;
-                charset[j] = cp[i];
+                if (j < sizeof(charset)-1)
+                    charset[j++] = cp[i];
             }
             charset[j] = '\0';
         }
-        else if (!strncmp(type_spec+i, "xpath=", 6))
+        else if (!strncmp(cp + i, "format=", 7))
         {
             size_t j = 0; 
-            i = i + 6;
-            for (j = 0; type_spec[i] && j < sizeof(xpath)-1; i++, j++)
-                xpath[j] = cp[i];
-            xpath[j] = '\0';
+            i = i + 7;
+            for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++)
+            {
+                if (j < sizeof(format)-1)
+                    format[j++] = cp[i];
+            }
+            format[j] = '\0';
         } 
-        while (type_spec[i] == ' ')
-            i++;
     }
     if (!strcmp(type, "database"))
     {
@@ -2146,15 +2188,17 @@ ZOOM_API(const char *)
     /* from now on - we have a database record .. */
     if (!strcmp(type, "render"))
     {
-        return return_record(rec, len, npr, YAZ_MARC_LINE, charset);
+        return get_record_format(rec, len, npr, YAZ_MARC_LINE, charset, format);
     }
     else if (!strcmp(type, "xml"))
     {
-        return return_record(rec, len, npr, YAZ_MARC_MARCXML, charset);
+        return get_record_format(rec, len, npr, YAZ_MARC_MARCXML, charset,
+                                 format);
     }
     else if (!strcmp(type, "raw"))
     {
-        return return_record(rec, len, npr, YAZ_MARC_ISO2709, charset);
+        return get_record_format(rec, len, npr, YAZ_MARC_ISO2709, charset,
+            format);
     }
     else if (!strcmp(type, "ext"))
     {
@@ -2164,7 +2208,8 @@ ZOOM_API(const char *)
     else if (!strcmp(type, "opac"))
     {
         if (npr->u.databaseRecord->which == Z_External_OPAC)
-            return return_record(rec, len, npr, YAZ_MARC_MARCXML, charset);
+            return get_record_format(rec, len, npr, YAZ_MARC_MARCXML, charset,
+                format);
     }
     return 0;
 }
@@ -2209,6 +2254,9 @@ static void record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
         rc = (ZOOM_record_cache) odr_malloc(r->odr, sizeof(*rc));
         rc->rec.odr = 0;
         rc->rec.wrbuf = 0;
+#if YAZ_HAVE_XML2
+        rc->rec.xml_mem = 0;
+#endif
         rc->elementSetName = odr_strdup_null(r->odr, elementSetName);
         
         rc->syntax = odr_strdup_null(r->odr, syntax);
index bde6b55..a464f29 100644 (file)
@@ -150,6 +150,11 @@ struct ZOOM_record_p {
     Z_NamePlusRecord *npr;
     const char *schema;
 
+#if YAZ_HAVE_XML2
+    xmlChar *xml_mem;
+    int xml_size;
+#endif
+
     const char *diag_uri;
     const char *diag_message;
     const char *diag_details;