New yaz_xml_get_prop utility YAZ-839
authorAdam Dickmeiss <adam@indexdata.dk>
Fri, 8 May 2015 12:53:12 +0000 (14:53 +0200)
committerAdam Dickmeiss <adam@indexdata.dk>
Fri, 8 May 2015 12:53:12 +0000 (14:53 +0200)
include/yaz/Makefile.am
include/yaz/xml_get.h [new file with mode: 0644]
src/Makefile.am
src/icu_chain.c
src/record_conv.c
src/xml_get.c [new file with mode: 0644]
src/xml_include.c
src/xmlquery.c
win/makefile

index 21d55dc..771fcb1 100644 (file)
@@ -12,7 +12,7 @@ pkginclude_HEADERS= backend.h backtrace.h base64.h \
  readconf.h record_conv.h record_render.h retrieval.h statserv.h \
  tcpip.h test.h timing.h unix.h tpath.h wrbuf.h xmalloc.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 \
+ xml_get.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 xml_include.h \
  \
diff --git a/include/yaz/xml_get.h b/include/yaz/xml_get.h
new file mode 100644 (file)
index 0000000..cc47cbc
--- /dev/null
@@ -0,0 +1,58 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) Index Data.
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Index Data nor the names of its contributors
+ *       may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \file xml_get.h
+    \brief XML node getter/creation utilities
+*/
+
+#ifndef YAZ_XML_GET_H
+#define YAZ_XML_GET_H
+
+#include <yaz/yconfig.h>
+#include <yaz/xmltypes.h>
+
+YAZ_BEGIN_CDECL
+
+#if YAZ_HAVE_XML2
+
+YAZ_EXPORT const char *yaz_xml_get_prop(const xmlNode *n, const char *fmt, ...);
+
+#endif
+
+YAZ_END_CDECL
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index de50bca..2382f57 100644 (file)
@@ -104,7 +104,7 @@ libyaz_la_SOURCES= $(GEN_FILES) \
   cqlstrer.c querytowrbuf.c \
   tcpdchk.c \
   test.c timing.c \
-  xmlquery.c xmlerror.c http.c \
+  xml_get.c xmlquery.c xmlerror.c http.c \
   mime.c mime.h oid_util.c tokenizer.c \
   record_conv.c retrieval.c elementset.c snprintf.c query-charset.c \
   copy_types.c match_glob.c poll.c daemon.c iconv_encode_danmarc.c \
index fa6c96a..a318e64 100644 (file)
@@ -22,6 +22,7 @@
 #include <yaz/log.h>
 #include <yaz/nmem.h>
 #include <yaz/nmem_xml.h>
+#include <yaz/xml_get.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -250,13 +251,10 @@ struct icu_chain *icu_chain_xml_config(const xmlNode *xml_node,
 
     if (xml_node && xml_node->type == XML_ELEMENT_NODE)
     {
-        xmlChar *xml_locale = xmlGetProp((xmlNode *) xml_node,
-                                         (xmlChar *) "locale");
+        const char *xml_locale = yaz_xml_get_prop((xmlNode *) xml_node,
+                                                  "locale");
         if (xml_locale)
-        {
             chain = icu_chain_create((const char *) xml_locale, sort, status);
-            xmlFree(xml_locale);
-        }
     }
 
     if (!chain)
@@ -267,24 +265,17 @@ struct icu_chain *icu_chain_xml_config(const xmlNode *xml_node,
     {
         char *rule = 0;
         struct icu_chain_step *step = 0;
-        struct _xmlAttr *attr;
+        const char *attr_str;
 
         nmem_reset(nmem);
         if (node->type != XML_ELEMENT_NODE)
             continue;
-
-        for (attr = node->properties; attr; attr = attr->next)
+        attr_str = yaz_xml_get_prop(node, "rule%s", &rule);
+        if (attr_str)
         {
-            if (!strcmp((const char *) attr->name, "rule"))
-            {
-                rule = nmem_text_node_cdata(attr->children, nmem);
-            }
-            else
-            {
-                yaz_log(YLOG_WARN, "Unsupported attribute '%s' for "
-                        "element '%s'", attr->name, node->name);
-                no_errors++;
-            }
+            yaz_log(YLOG_WARN, "Unsupported attribute '%s' for "
+                    "element '%s'", attr_str, node->name);
+            no_errors++;
         }
         if (!rule && node->children)
             rule = nmem_text_node_cdata(node->children, nmem);
index a74b4c5..b117340 100644 (file)
@@ -20,6 +20,7 @@
 #include <yaz/nmem.h>
 #include <yaz/tpath.h>
 #include <yaz/z-opac.h>
+#include <yaz/xml_get.h>
 
 #if YAZ_HAVE_XML2
 #include <libxml/parser.h>
@@ -331,26 +332,23 @@ static void *construct_select(const xmlNode *ptr,
         return 0;
     else
     {
-        struct _xmlAttr *attr;
         NMEM nmem = nmem_create();
         struct select_info *info = nmem_malloc(nmem, sizeof(*info));
+        const char *attr_str;
+        const char *xpath = 0;
 
         info->nmem = nmem;
         info->xpath_expr = 0;
-        for (attr = ptr->properties; attr; attr = attr->next)
+        attr_str = yaz_xml_get_prop(ptr, "path%s", &xpath);
+        if (attr_str)
         {
-            if (!xmlStrcmp(attr->name, BAD_CAST "path") &&
-                attr->children && attr->children->type == XML_TEXT_NODE)
-                info->xpath_expr =
-                    nmem_strdup(nmem, (const char *) attr->children->content);
-            else
-            {
-                wrbuf_printf(wr_error, "Bad attribute '%s'"
-                             "Expected xpath.", attr->name);
-                nmem_destroy(nmem);
+            wrbuf_printf(wr_error, "Bad attribute '%s'"
+                         "Expected xpath.", attr_str);
+            nmem_destroy(nmem);
                 return 0;
-            }
         }
+        if (xpath)
+            info->xpath_expr = nmem_strdup(nmem, xpath);
         return info;
     }
 }
diff --git a/src/xml_get.c b/src/xml_get.c
new file mode 100644 (file)
index 0000000..5b87c36
--- /dev/null
@@ -0,0 +1,93 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) Index Data
+ * See the file LICENSE for details.
+ */
+/**
+ * \file xml_get.c
+ * \brief XML node getter/creation utilities
+ */
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdarg.h>
+#include <yaz/xmalloc.h>
+#include <yaz/xml_get.h>
+#if YAZ_HAVE_XML2
+
+const char *yaz_xml_get_prop(const xmlNode *n, const char *fmt, ...)
+{
+    int no = 0;
+    va_list ap;
+    const char *cp;
+    struct _xmlAttr *attr;
+
+    va_start(ap, fmt);
+    for (cp = fmt; *cp; cp++)
+        if (*cp == '%')
+            no++;
+    if (no > 0)
+    {
+        const char ***ar = xmalloc(sizeof(*ar) * no);
+        int i;
+        for (i = 0; i < no; i++)
+        {
+            const char **s = va_arg(ap, const char **);
+            ar[i] = s;
+        }
+        for (attr = n->properties; attr; attr = attr->next)
+        {
+            const char *cp1 = fmt;
+            for (i = 0; *cp1; i++)
+            {
+                const char *cp2 = cp1;
+                size_t l;
+                while (*cp2 != '\0' && *cp2 != '%')
+                    cp2++;
+                if (*cp2 != '\0')
+                { /* no % following, break out (bad fmt really) */
+                    cp1 = cp2;
+                    break;
+                }
+                l = cp2 - cp1;
+                if (l > 0 && strlen((const char *) attr->name) == l &&
+                    !memcmp((const char *) attr->name, cp1, l))
+                    break;
+                cp1 = 1 + cp2;
+                if (*cp1)
+                    cp1++; /* skip char following % */
+            }
+            if (!*cp1)
+            {
+                /* attribute not listed in fmt: return first unknown one */
+                xfree(ar);
+                return (const char *) attr->name;
+            }
+            *ar[i] = (const char *) attr->children->content;
+        }
+        xfree(ar);
+    }
+    else
+    {
+        for (attr = n->properties; attr; attr = attr->next)
+        {
+            if (!strcmp((const char *) attr->name, fmt))
+                return (const char *) attr->children->content;
+        }
+    }
+    va_end(ap);
+    return 0; /* failure for simple mode; successful for %mode */
+}
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 21e6b0e..8008610 100644 (file)
@@ -131,6 +131,7 @@ static int process_config_includes(yaz_xml_include_t config, xmlNode *n)
                 xmlChar *src = xmlGetProp(n, (xmlChar *) "src");
                 if (src)
                 {
+                    /* src must be preserved, because n is destroyed */
                     int ret = config_include_src(config, &n,
                                                  (const char *) src);
                     xmlFree(src);
index 966dd66..4728de6 100644 (file)
@@ -20,6 +20,7 @@
 #include <yaz/logrpn.h>
 #include <yaz/xmlquery.h>
 #include <yaz/nmem_xml.h>
+#include <yaz/xml_get.h>
 #include <yaz/oid_db.h>
 
 static int check_diagnostic(const xmlNode *ptr, ODR odr,
@@ -362,7 +363,7 @@ static void yaz_xml2query_operator(const xmlNode *ptr, Z_Operator **op,
                                    ODR odr,
                                    int *error_code, const char **addinfo)
 {
-    xmlChar *type = xmlGetProp((xmlNodePtr) ptr, BAD_CAST "type");
+    const char *type = yaz_xml_get_prop((xmlNodePtr) ptr, "type");
     if (!type)
     {
         *error_code = 1;
@@ -370,22 +371,22 @@ static void yaz_xml2query_operator(const xmlNode *ptr, Z_Operator **op,
         return;
     }
     *op = (Z_Operator*) odr_malloc(odr, sizeof(Z_Operator));
-    if (!xmlStrcmp(type, BAD_CAST "and"))
+    if (!strcmp(type, "and"))
     {
         (*op)->which = Z_Operator_and;
         (*op)->u.op_and = odr_nullval();
     }
-    else if (!xmlStrcmp(type, BAD_CAST "or"))
+    else if (!strcmp(type, "or"))
     {
         (*op)->which = Z_Operator_or;
         (*op)->u.op_or = odr_nullval();
     }
-    else if (!xmlStrcmp(type, BAD_CAST "not"))
+    else if (!strcmp(type, "not"))
     {
         (*op)->which = Z_Operator_and_not;
         (*op)->u.and_not = odr_nullval();
     }
-    else if (!xmlStrcmp(type, BAD_CAST "prox"))
+    else if (!strcmp(type, "prox"))
     {
         struct _xmlAttr *attr;
         Z_ProximityOperator *pop = (Z_ProximityOperator *)
@@ -437,7 +438,6 @@ static void yaz_xml2query_operator(const xmlNode *ptr, Z_Operator **op,
         *error_code = 1;
         *addinfo = "bad operator type";
     }
-    xmlFree(type);
 }
 
 static void yaz_xml2query_attribute_element(const xmlNode *ptr,
@@ -749,15 +749,14 @@ static void yaz_xml2query_rpnstructure(const xmlNode *ptr, Z_RPNStructure **zs,
 static void yaz_xml2query_rpn(const xmlNode *ptr, Z_RPNQuery **query, ODR odr,
                               int *error_code, const char **addinfo)
 {
-    xmlChar *set = xmlGetProp((xmlNodePtr) ptr, BAD_CAST "set");
+    const char  *set = yaz_xml_get_prop((xmlNodePtr) ptr, "set");
 
     *query = (Z_RPNQuery*) odr_malloc(odr, sizeof(Z_RPNQuery));
     if (set)
     {
         (*query)->attributeSetId =
             yaz_string_to_oid_odr(yaz_oid_std(),
-                                  CLASS_ATTSET, (const char *) set, odr);
-        xmlFree(set);
+                                  CLASS_ATTSET, set, odr);
     }
     else
         (*query)->attributeSetId = 0;
index b82ddf4..1f3ffb8 100644 (file)
@@ -486,6 +486,7 @@ MISC_OBJS= \
    $(OBJDIR)\charneg.obj \
    $(OBJDIR)\grs1disp.obj \
    $(OBJDIR)\opac_to_xml.obj \
+   $(OBJDIR)\xml_get.obj \
    $(OBJDIR)\xml_add.obj \
    $(OBJDIR)\xml_match.obj \
    $(OBJDIR)\xml_to_opac.obj \