From b2bc97df294f5da6c93e1119a42536b23afce8ef Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 8 May 2015 14:53:12 +0200 Subject: [PATCH] New yaz_xml_get_prop utility YAZ-839 --- include/yaz/Makefile.am | 2 +- include/yaz/xml_get.h | 58 +++++++++++++++++++++++++++++ src/Makefile.am | 2 +- src/icu_chain.c | 27 +++++--------- src/record_conv.c | 22 +++++------ src/xml_get.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ src/xml_include.c | 1 + src/xmlquery.c | 17 ++++----- win/makefile | 1 + 9 files changed, 182 insertions(+), 41 deletions(-) create mode 100644 include/yaz/xml_get.h create mode 100644 src/xml_get.c diff --git a/include/yaz/Makefile.am b/include/yaz/Makefile.am index 21d55dc..771fcb1 100644 --- a/include/yaz/Makefile.am +++ b/include/yaz/Makefile.am @@ -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 index 0000000..cc47cbc --- /dev/null +++ b/include/yaz/xml_get.h @@ -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 +#include + +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 + */ + diff --git a/src/Makefile.am b/src/Makefile.am index de50bca..2382f57 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/icu_chain.c b/src/icu_chain.c index fa6c96a..a318e64 100644 --- a/src/icu_chain.c +++ b/src/icu_chain.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -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); diff --git a/src/record_conv.c b/src/record_conv.c index a74b4c5..b117340 100644 --- a/src/record_conv.c +++ b/src/record_conv.c @@ -20,6 +20,7 @@ #include #include #include +#include #if YAZ_HAVE_XML2 #include @@ -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 index 0000000..5b87c36 --- /dev/null +++ b/src/xml_get.c @@ -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 +#endif + +#include +#include +#include +#include +#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 + */ + diff --git a/src/xml_include.c b/src/xml_include.c index 21e6b0e..8008610 100644 --- a/src/xml_include.c +++ b/src/xml_include.c @@ -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); diff --git a/src/xmlquery.c b/src/xmlquery.c index 966dd66..4728de6 100644 --- a/src/xmlquery.c +++ b/src/xmlquery.c @@ -20,6 +20,7 @@ #include #include #include +#include #include 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; diff --git a/win/makefile b/win/makefile index b82ddf4..1f3ffb8 100644 --- a/win/makefile +++ b/win/makefile @@ -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 \ -- 1.7.10.4