Adding XML Include utility (not W3C's include)
authorAdam Dickmeiss <adam@indexdata.dk>
Fri, 22 Jan 2010 14:38:32 +0000 (15:38 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Fri, 22 Jan 2010 14:38:32 +0000 (15:38 +0100)
configure.ac
include/yaz/Makefile.am
src/Makefile.am
src/xml_include.c [new file with mode: 0644]
win/makefile

index ce9e760..01f0835 100644 (file)
@@ -21,7 +21,7 @@ dnl
 YAZ_DOC
 dnl 
 dnl
-AC_CHECK_HEADERS([dirent.h fnmatch.h wchar.h locale.h langinfo.h pwd.h unistd.h sys/select.h sys/socket.h sys/stat.h sys/time.h sys/times.h sys/types.h sys/un.h sys/wait.h netdb.h arpa/inet.h netinet/tcp.h netinet/in_systm.h],[],[],[])
+AC_CHECK_HEADERS([dirent.h fnmatch.h wchar.h locale.h langinfo.h pwd.h unistd.h sys/select.h sys/socket.h sys/stat.h sys/time.h sys/times.h sys/types.h glob.h sys/un.h sys/wait.h netdb.h arpa/inet.h netinet/tcp.h netinet/in_systm.h],[],[],[])
 AC_CHECK_HEADERS([net/if.h netinet/in.h netinet/if_ether.h],[],[],[
  #if HAVE_SYS_TYPES_H
  #include <sys/types.h>
index 246dbd8..d40777d 100644 (file)
@@ -12,7 +12,7 @@ pkginclude_HEADERS= backend.h ccl.h ccl_xml.h cql.h rpn2cql.h comstack.h \
  yaz-ccl.h yaz-iconv.h yaz-util.h yaz-version.h yconfig.h proto.h \
  xmlquery.h xmltypes.h snprintf.h query-charset.h \
  mutex.h oid_db.h oid_util.h oid_std.h tokenizer.h copy_types.h \
- icu.h match_glob.h poll.h daemon.h sc.h \
+ icu.h match_glob.h poll.h daemon.h sc.h xml_include.h \
  \
  ill.h ill-core.h item-req.h oclc-ill-req-ext.h z-accdes1.h z-accform1.h \
  z-acckrb1.h z-core.h z-date.h z-diag1.h z-espec1.h z-estask.h z-exp.h \
index 23eeeef..7cff54e 100644 (file)
@@ -103,7 +103,7 @@ libyaz_la_SOURCES=version.c options.c log.c \
   copy_types.c match_glob.c poll.c daemon.c \
   iconv_encode_marc8.c iconv_encode_iso_8859_1.c iconv_encode_wchar.c \
   iconv_decode_marc8.c iconv_decode_iso5426.c iconv_decode_danmarc.c sc.c \
-  json.c
+  json.c xml_include.c
 
 libyaz_la_LDFLAGS=-version-info $(YAZ_VERSION_INFO)
 
diff --git a/src/xml_include.c b/src/xml_include.c
new file mode 100644 (file)
index 0000000..db5f13e
--- /dev/null
@@ -0,0 +1,183 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2010 Index Data
+ * See the file LICENSE for details.
+ */
+
+/** \file 
+    \brief XML Include (not to be confused with W3C XInclude)
+*/
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if HAVE_GLOB_H
+#define USE_POSIX_GLOB 1
+#else
+#define USE_POSIX_GLOB 0
+#endif
+
+#if USE_POSIX_GLOB
+#include <glob.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <yaz/wrbuf.h>
+#include <yaz/tpath.h>
+#include <yaz/log.h>
+#include <yaz/xml_include.h>
+
+#if YAZ_HAVE_XML2
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+struct yaz_xml_include_s {
+    const char *confdir;
+};
+
+typedef struct yaz_xml_include_s *yaz_xml_include_t;
+
+static int process_config_includes(yaz_xml_include_t config, xmlNode *n);
+
+static void conf_dir_path(yaz_xml_include_t config, WRBUF w, const char *src)
+{
+    if (config->confdir && *config->confdir > 0 &&
+        !yaz_is_abspath(src))
+    {
+        wrbuf_printf(w, "%s/%s", config->confdir, src);
+    }
+    else
+        wrbuf_puts(w, src);
+}
+
+static int config_include_one(yaz_xml_include_t config, xmlNode **sib,
+                              const char *path)
+{
+    struct stat st;
+    if (stat(path, &st) < 0)
+    {
+        yaz_log(YLOG_FATAL|YLOG_ERRNO, "stat %s", path);
+        return -1;
+    }
+    else
+    {
+        if ((st.st_mode & S_IFMT) == S_IFREG)
+        {
+            xmlDoc *doc = xmlParseFile(path);
+            if (doc)
+            {
+                xmlNodePtr t = xmlDocGetRootElement(doc);
+                int ret = process_config_includes(config, t);
+                *sib = xmlAddNextSibling(*sib, xmlCopyNode(t, 1));
+                xmlFreeDoc(doc);
+                if (ret)
+                    return -1;
+            }
+            else
+            {
+                yaz_log(YLOG_FATAL, "Could not parse %s", path);
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+static int config_include_src(yaz_xml_include_t config, xmlNode **np,
+                              const char *src)
+{
+    int ret = 0; /* return code. OK so far */
+    WRBUF w = wrbuf_alloc();
+    xmlNodePtr sib; /* our sibling that we append */
+    xmlNodePtr c; /* tmp node */
+
+    wrbuf_printf(w, " begin include src=\"%s\" ", src);
+
+    /* replace include element with a 'begin' comment */
+    sib = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
+    xmlReplaceNode(*np, sib);
+
+    xmlFreeNode(*np);
+
+    wrbuf_rewind(w);
+    conf_dir_path(config, w, src);
+#if USE_POSIX_GLOB
+    {
+        size_t i;
+        glob_t glob_res;
+        glob(wrbuf_cstr(w), 0 /* flags */, 0 /* errfunc */, &glob_res);
+        
+        for (i = 0; ret == 0 && i < glob_res.gl_pathc; i++)
+        {
+            const char *path = glob_res.gl_pathv[i];
+            ret = config_include_one(config, &sib, path);
+        }
+        globfree(&glob_res);
+    }
+#else
+    ret = config_include_one(config, &sib, wrbuf_cstr(w));
+#endif
+    wrbuf_rewind(w);
+    wrbuf_printf(w, " end include src=\"%s\" ", src);
+    c = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
+    sib = xmlAddNextSibling(sib, c);
+    
+    *np = sib;
+    wrbuf_destroy(w);
+    return ret;
+}
+
+static int process_config_includes(yaz_xml_include_t config, xmlNode *n)
+{
+    for (; n; n = n->next)
+    {
+        if (n->type == XML_ELEMENT_NODE)
+        {
+            if (!strcmp((const char *) n->name, "include"))
+            {
+                xmlChar *src = xmlGetProp(n, (xmlChar *) "src");
+                if (src)
+                {
+                    int ret = config_include_src(config, &n,
+                                                 (const char *) src);
+                    xmlFree(src);
+                    if (ret)
+                        return ret;
+                        
+                }
+            }
+            else
+            {
+                if (process_config_includes(config, n->children))
+                    return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+int yaz_xml_include_simple(xmlNode *n, const char *base_path)
+{
+    struct yaz_xml_include_s s;
+
+    s.confdir = base_path;
+    process_config_includes(&s, n);
+    return 0;
+}
+
+/* YAZ_HAVE_XML2 */
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index e4e9b6d..e430cb9 100644 (file)
@@ -496,7 +496,8 @@ MISC_OBJS= \
    $(OBJDIR)\iconv_decode_danmarc.obj \
    $(OBJDIR)\mutex.obj \
    $(OBJDIR)\json.obj \
-   $(OBJDIR)\sc.obj
+   $(OBJDIR)\sc.obj \
+   $(OBJDIR)\xml_include.obj
 
 Z3950_OBJS= \
    $(OBJDIR)\z-date.obj\