SRW, CQL, 2003
[yaz-moved-to-github.git] / srw / srw-xslt.c
diff --git a/srw/srw-xslt.c b/srw/srw-xslt.c
new file mode 100644 (file)
index 0000000..c3dbac0
--- /dev/null
@@ -0,0 +1,209 @@
+/* $Id: srw-xslt.c,v 1.1 2003-01-06 08:20:28 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#if HAVE_XSLT
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/transform.h>
+#endif
+
+#include <yaz/srw-util.h>
+
+struct xslt_maps_info {
+#if HAVE_XSLT
+    xmlDocPtr doc;
+#else
+    int dummy;
+#endif
+};
+
+struct xslt_map_result_info {
+#if HAVE_XSLT
+    xmlChar *buf;
+#else
+    char *buf;
+#endif
+    int len;
+    char *schema;
+};
+
+xslt_maps xslt_maps_create()
+{
+    xslt_maps m = malloc(sizeof(*m));
+#if HAVE_XSLT
+    m->doc = 0;
+#endif
+    return m;
+}
+
+void xslt_maps_free(xslt_maps m)
+{
+#if HAVE_XSLT
+    xmlFreeDoc(m->doc);
+#endif
+    free (m);
+}
+
+int xslt_maps_file(xslt_maps m, const char *f)
+{
+#if HAVE_XSLT
+    if (m->doc)
+        xmlFreeDoc(m->doc);
+    m->doc = xmlParseFile(f);
+    if (!m->doc)
+        return -1;
+    return 0;
+#else
+    return -2;
+#endif
+}
+
+void xslt_map_free (xslt_map_result res)
+{
+    if (res)
+    {
+        free (res->schema);
+#if HAVE_XSLT
+        xmlFree(res->buf);
+#endif
+        free (res);
+    }
+}
+
+xslt_map_result xslt_map (xslt_maps m, const char *schema_source,
+                          const char *schema_target,
+                          const char *in_buf, int in_len)
+{
+#if HAVE_XSLT
+    const char *map_ns = "http://indexdata.dk/srw/schema-mappings/v1.0/";
+    xmlNodePtr ptr;
+
+    if (!m)
+        return 0;
+    ptr = xmlDocGetRootElement(m->doc);
+    while (ptr && ptr->type == XML_ELEMENT_NODE)
+    {
+        if (!strcmp(ptr->name, "schema-mappings"))
+        {
+            ptr = ptr->children;
+            break;
+        }
+    }
+    for (; ptr; ptr = ptr->next)
+    {
+        if (ptr->type == XML_ELEMENT_NODE &&  !strcmp(ptr->name, "map")
+            && !strcmp(ptr->ns->href, map_ns) && ptr->children)
+        {
+            xmlNodePtr src = ptr->children;
+            int source_ok = 0;
+            int target_ok = 0;
+            const char *full_target = 0;
+            const char *filename = 0;
+            
+            for (; src; src = src->next)
+            {
+                if (src->type == XML_ELEMENT_NODE &&
+                    !strcmp(src->name, "schema") &&
+                    !strcmp(src->ns->href, map_ns))
+                {
+                    struct _xmlAttr *attr = src->properties;
+                    for (; attr; attr = attr->next)
+                        if (!strcmp(attr->name, "target") &&
+                            attr->children &&
+                            attr->children->type == XML_TEXT_NODE)
+                        {
+                            full_target = attr->children->content;
+                            if (!strcmp(attr->children->content,
+                                        schema_target))
+                                target_ok = 1;
+                        }
+                        else if (!strcmp(attr->name, "source")
+                                 && attr->children
+                                 && attr->children->type == XML_TEXT_NODE)
+                            
+                        {
+                            if (!strcmp(schema_source,
+                                        attr->children->content))
+                                source_ok = 1;
+                        }
+                        else if (!strcmp(attr->name, "alias")
+                                 && attr->children
+                                 && attr->children->type == XML_TEXT_NODE)
+                        {
+                            if (!strcmp(attr->children->content, schema_target))
+                                target_ok = 1;
+                        }
+                }
+                if (src->type == XML_ELEMENT_NODE &&
+                    !strcmp(src->name, "stylesheet") &&
+                    !strcmp(src->ns->href, map_ns))
+                {
+                    struct _xmlAttr *attr = src->properties;
+                    for (; attr; attr = attr->next)
+                        if (!strcmp(attr->name, "filename") &&
+                            attr->children &&
+                            attr->children->type == XML_TEXT_NODE)
+                        {
+                            filename = attr->children->content;
+                        }
+                }
+            }
+            if (source_ok && target_ok)
+            {
+                if (filename)
+                {
+                    xslt_map_result out = malloc(sizeof(*out));
+                    xmlDocPtr res, doc = xmlParseMemory(in_buf, in_len);
+                    xmlDocPtr xslt_doc = xmlParseFile(filename);
+                    xsltStylesheetPtr xsp;
+                    
+                    xsp = xsltParseStylesheetDoc(xslt_doc);
+                    
+                    res = xsltApplyStylesheet(xsp, doc, 0);
+                    
+                    xmlDocDumpMemory (res, &out->buf, &out->len);
+                
+                    xsltFreeStylesheet(xsp);
+                    
+                    xmlFreeDoc(doc);
+                    xmlFreeDoc(res);
+                    
+                    out->schema = strdup(full_target);
+                    return out;
+                }
+                else
+                {
+                    xslt_map_result out = malloc(sizeof(*out));
+                    out->buf = xmlMalloc(in_len);
+                    memcpy (out->buf, in_buf, in_len);
+                    out->len = in_len;
+                    out->schema = strdup(full_target);
+                    return out; 
+                }
+            }
+        }
+    }
+#endif
+    return 0;
+}
+
+char *xslt_map_result_buf(xslt_map_result res)
+{
+    return res->buf;
+}
+int xslt_map_result_len(xslt_map_result res)
+{
+    return res->len;
+}
+
+char *xslt_map_result_schema(xslt_map_result res)
+{
+    return res->schema;
+}