From bc34bd42eb228125be6ff9143d9f98dbe11889a0 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 22 Jan 2010 15:38:32 +0100 Subject: [PATCH] Adding XML Include utility (not W3C's include) --- configure.ac | 2 +- include/yaz/Makefile.am | 2 +- src/Makefile.am | 2 +- src/xml_include.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++ win/makefile | 3 +- 5 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 src/xml_include.c diff --git a/configure.ac b/configure.ac index ce9e760..01f0835 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/include/yaz/Makefile.am b/include/yaz/Makefile.am index 246dbd8..d40777d 100644 --- a/include/yaz/Makefile.am +++ b/include/yaz/Makefile.am @@ -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 \ diff --git a/src/Makefile.am b/src/Makefile.am index 23eeeef..7cff54e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 0000000..db5f13e --- /dev/null +++ b/src/xml_include.c @@ -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 +#endif + +#if HAVE_GLOB_H +#define USE_POSIX_GLOB 1 +#else +#define USE_POSIX_GLOB 0 +#endif + +#if USE_POSIX_GLOB +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if YAZ_HAVE_XML2 + +#include +#include + +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 + */ + diff --git a/win/makefile b/win/makefile index e4e9b6d..e430cb9 100644 --- a/win/makefile +++ b/win/makefile @@ -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\ -- 1.7.10.4