creates NMEM string.
Added first parts of record conversion utility (yaz_record_conv_t).
-## $Id: Makefile.am,v 1.27 2006-01-27 17:31:52 adam Exp $
+## $Id: Makefile.am,v 1.28 2006-05-02 20:47:45 adam Exp $
pkginclude_HEADERS= backend.h ccl.h cql.h comstack.h \
diagbib1.h diagsrw.h sortspec.h log.h logrpn.h marcdisp.h nmem.h odr.h \
oid.h options.h otherinfo.h pquery.h prt-ext.h querytowrbuf.h \
- readconf.h statserv.h \
+ readconf.h record_conv.h statserv.h \
tcpip.h test.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 \
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*
- * $Id: nmem.h,v 1.17 2005-06-25 15:46:03 adam Exp $
+ * $Id: nmem.h,v 1.18 2006-05-02 20:47:45 adam Exp $
*/
/**
YAZ_EXPORT void nmem_strsplit(NMEM nmem, const char *delim,
const char *dstr,
char ***darray, int *num);
+YAZ_EXPORT char *nmem_text_node_cdata(const void *ptr_cdata, NMEM nmem);
YAZ_EXPORT int *nmem_intdup (NMEM mem, int v);
YAZ_EXPORT void nmem_transfer (NMEM dst, NMEM src);
--- /dev/null
+/*
+ * Copyright (C) 2005-2006, Index Data ApS
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation, in whole or in part, for any purpose, is hereby granted,
+ * provided that:
+ *
+ * 1. This copyright and permission notice appear in all copies of the
+ * software and its documentation. Notices of copyright or attribution
+ * which appear at the beginning of any file must remain unchanged.
+ *
+ * 2. The name of Index Data or the individual authors may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ * IN NO EVENT SHALL INDEX DATA BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR
+ * NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * $Id: record_conv.h,v 1.1 2006-05-02 20:47:45 adam Exp $
+ */
+/**
+ * \file record_conv.h
+ * \brief Record Conversions Utility
+ */
+
+#ifndef YAZ_RECORD_CONV_H
+#define YAZ_RECORD_CONV_H
+
+#include <stddef.h>
+#include <yaz/yconfig.h>
+
+YAZ_BEGIN_CDECL
+
+/** record conversion handle */
+typedef struct yaz_record_conv_struct *yaz_record_conv_t;
+
+/** creates record handle
+ \return record handle
+*/
+YAZ_EXPORT yaz_record_conv_t yaz_record_conv_create(void);
+
+/** destroys record handle
+ \param p record conversion handle
+*/
+YAZ_EXPORT void yaz_record_conv_destroy(yaz_record_conv_t p);
+
+
+/** configures record conversion
+ \param p record conversion handle
+ \param node xmlNode pointer (root element of XML config)
+ \retval 0 success
+ \retval -1 failure
+
+ \verbatim
+ <convert>
+ <xslt stylesheet="dc2marcxml.xsl"/>
+ <xmltomarc charset="marc-8"/>
+ </convert>
+ \endverbatim
+
+ \verbatim
+ <convert>
+ <marctoxml charset="marc-8"/>
+ <xslt stylesheet="marcxml2mods.xsl"/>
+ <xslt stylesheet="mods2dc.xsl"/>
+ </convert>
+ \endverbatim
+
+ For retrieval (ignore here):
+ \verbatim
+ <retrievalinfo>
+ <retrieval syntax="usmarc" name="marcxml"
+ identifier="info:srw/schema/1/marcxml-v1.1"
+ >
+ <title>MARCXML</title>
+ <backend syntax="xml" name="dc" charset="utf-8"/>
+ <convert>
+ <xslt stylesheet="dc2marcxml.xsl"/>
+ <xmltomarc charset="marc-8"/>
+ </convert>
+ </retrieval>
+ </retrievalinfo>
+ \endverbatim
+*/
+YAZ_EXPORT
+int yaz_record_conv_configure(yaz_record_conv_t p, const void *node);
+
+
+/** returns error string (for last error)
+ \param p record conversion handle
+ \return error string
+*/
+YAZ_EXPORT
+const char *yaz_record_conv_get_error(yaz_record_conv_t p);
+
+YAZ_END_CDECL
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
## This file is part of the YAZ toolkit.
## Copyright (C) 1994-2006, Index Data, All rights reserved.
-## $Id: Makefile.am,v 1.32 2006-04-21 12:54:36 marc Exp $
+## $Id: Makefile.am,v 1.33 2006-05-02 20:47:45 adam Exp $
YAZ_VERSION_INFO=2:1:0
eventl.c seshigh.c statserv.c requestq.c tcpdchk.c \
eventl.h service.c service.h session.h test.c \
xmlquery.c \
+ record_conv.c \
mime.c mime.h
libyaz_la_LDFLAGS=-version-info $(YAZ_VERSION_INFO)
* Copyright (C) 1995-2006, Index Data ApS
* See the file LICENSE for details.
*
- * $Id: marcdisp.c,v 1.28 2006-04-20 20:35:02 adam Exp $
+ * $Id: marcdisp.c,v 1.29 2006-05-02 20:47:45 adam Exp $
*/
/**
n->u.comment = nmem_strdup(mt->nmem, comment);
}
-#if HAVE_XML2
-static char *yaz_marc_get_xml_text(const xmlNode *ptr_cdata, NMEM nmem)
-{
- char *cdata;
- int len = 0;
- const xmlNode *ptr;
-
- for (ptr = ptr_cdata; ptr; ptr = ptr->next)
- if (ptr->type == XML_TEXT_NODE)
- len += xmlStrlen(ptr->content);
- cdata = (char *) nmem_malloc(nmem, len+1);
- *cdata = '\0';
- for (ptr = ptr_cdata; ptr; ptr = ptr->next)
- if (ptr->type == XML_TEXT_NODE)
- strcat(cdata, (const char *) ptr->content);
- return cdata;
-}
-#endif
-
void yaz_marc_cprintf(yaz_marc_t mt, const char *fmt, ...)
{
va_list ap;
{
struct yaz_marc_node *n = yaz_marc_add_node(mt);
n->which = YAZ_MARC_CONTROLFIELD;
- n->u.controlfield.tag = yaz_marc_get_xml_text(ptr_tag, mt->nmem);
- n->u.controlfield.data = yaz_marc_get_xml_text(ptr_data, mt->nmem);
+ n->u.controlfield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
+ n->u.controlfield.data = nmem_text_node_cdata(ptr_data, mt->nmem);
}
#endif
{
struct yaz_marc_node *n = yaz_marc_add_node(mt);
n->which = YAZ_MARC_DATAFIELD;
- n->u.datafield.tag = yaz_marc_get_xml_text(ptr_tag, mt->nmem);
+ n->u.datafield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
n->u.datafield.indicator =
nmem_strdupn(mt->nmem, indicator, indicator_len);
n->u.datafield.subfields = 0;
/*
- * Copyright (C) 1995-2005, Index Data ApS
+ * Copyright (C) 1995-2006, Index Data ApS
* See the file LICENSE for details.
*
- * $Id: nmemsdup.c,v 1.5 2005-06-25 15:46:04 adam Exp $
+ * $Id: nmemsdup.c,v 1.6 2006-05-02 20:47:45 adam Exp $
*/
/**
#include <string.h>
#include <yaz/nmem.h>
+#if HAVE_XML2
+#include <libxml/tree.h>
+#endif
char *nmem_strdup (NMEM mem, const char *src)
{
}
}
+#if HAVE_XML2
+char *nmem_text_node_cdata(const void *ptr_cdata, NMEM nmem)
+{
+ char *cdata;
+ int len = 0;
+ const xmlNode *ptr;
+
+ for (ptr = (const xmlNode *) ptr_cdata; ptr; ptr = ptr->next)
+ if (ptr->type == XML_TEXT_NODE)
+ len += xmlStrlen(ptr->content);
+ cdata = (char *) nmem_malloc(nmem, len+1);
+ *cdata = '\0';
+ for (ptr = (const xmlNode *) ptr_cdata; ptr; ptr = ptr->next)
+ if (ptr->type == XML_TEXT_NODE)
+ strcat(cdata, (const char *) ptr->content);
+ return cdata;
+}
+#endif
+
/*
* Local variables:
* c-basic-offset: 4
--- /dev/null
+/*
+ * Copyright (C) 2005-2006, Index Data ApS
+ * See the file LICENSE for details.
+ *
+ * $Id: record_conv.c,v 1.1 2006-05-02 20:47:45 adam Exp $
+ */
+/**
+ * \file record_conv.c
+ * \brief Record Conversions utility
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if HAVE_XML2
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#endif
+
+#include <string.h>
+
+#include <yaz/record_conv.h>
+#include <yaz/wrbuf.h>
+#include <yaz/xmalloc.h>
+#include <yaz/nmem.h>
+
+/** \brief The internal structure for yaz_record_conv_t */
+struct yaz_record_conv_struct {
+ /** memory for configuration */
+ NMEM nmem;
+
+ /** conversion rules (allocated using NMEM) */
+ struct yaz_record_conv_rule *rules;
+
+ /** pointer to last conversion rule pointer in chain */
+ struct yaz_record_conv_rule **rules_p;
+
+ /** string buffer for error messages */
+ WRBUF wr_error;
+};
+
+/** \brief tranformation types (rule types) */
+enum YAZ_RECORD_CONV_RULE
+{
+ YAZ_RECORD_CONV_RULE_XSLT,
+ YAZ_RECORD_CONV_RULE_MARC_TO_XML,
+ YAZ_RECORD_CONV_RULE_XML_TO_MARC
+};
+
+/** \brief tranformation info (rule info) */
+struct yaz_record_conv_rule {
+ enum YAZ_RECORD_CONV_RULE which;
+ union {
+ struct {
+ const char *stylesheet;
+ } xslt;
+ struct {
+ const char *charset;
+ } marc_to_xml;
+ struct {
+ const char *charset;
+ } xml_to_marc;
+ } u;
+ struct yaz_record_conv_rule *next;
+};
+
+yaz_record_conv_t yaz_record_conv_create()
+{
+ yaz_record_conv_t p = xmalloc(sizeof(*p));
+ p->nmem = nmem_create();
+ p->wr_error = wrbuf_alloc();
+ return p;
+}
+
+void yaz_record_conv_destroy(yaz_record_conv_t p)
+{
+ if (p)
+ {
+ nmem_destroy(p->nmem);
+ wrbuf_free(p->wr_error, 1);
+ xfree(p);
+ }
+}
+
+#if HAVE_XML2
+static struct yaz_record_conv_rule *add_rule(yaz_record_conv_t p,
+ enum YAZ_RECORD_CONV_RULE type)
+{
+ struct yaz_record_conv_rule *r = nmem_malloc(p->nmem, sizeof(*r));
+ r->which = type;
+ r->next = 0;
+ *p->rules_p = r;
+ p->rules_p = &r->next;
+ return r;
+}
+
+static void yaz_record_conv_reset(yaz_record_conv_t p)
+{
+ wrbuf_rewind(p->wr_error);
+ nmem_reset(p->nmem);
+ p->rules = 0;
+ p->rules_p = &p->rules;
+}
+
+static int conv_xslt(yaz_record_conv_t p, const xmlNode *ptr)
+{
+ struct _xmlAttr *attr;
+ const char *stylesheet = 0;
+
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ if (!xmlStrcmp(attr->name, BAD_CAST "stylesheet") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ stylesheet = (const char *) attr->children->content;
+ else
+ {
+ wrbuf_printf(p->wr_error, "Bad attribute '%s'."
+ "Expected stylesheet.", attr->name);
+ return -1;
+ }
+ }
+ if (stylesheet)
+ {
+ struct yaz_record_conv_rule *r =
+ add_rule(p, YAZ_RECORD_CONV_RULE_XSLT);
+ r->u.xslt.stylesheet = nmem_strdup(p->nmem, stylesheet);
+ return 0;
+ }
+ wrbuf_printf(p->wr_error, "Missing attribute 'stylesheet'");
+ return -1;
+}
+
+static int conv_marc_to_xml(yaz_record_conv_t p, const xmlNode *ptr)
+{
+ struct _xmlAttr *attr;
+ const char *charset = 0;
+ struct yaz_record_conv_rule *r;
+
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ if (!xmlStrcmp(attr->name, BAD_CAST "charset") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ charset = (const char *) attr->children->content;
+ else
+ {
+ wrbuf_printf(p->wr_error, "Bad attribute '%s'."
+ "Expected charset.", attr->name);
+ return -1;
+ }
+ }
+ r = add_rule(p, YAZ_RECORD_CONV_RULE_MARC_TO_XML);
+ if (charset)
+ r->u.marc_to_xml.charset = nmem_strdup(p->nmem, charset);
+ else
+ r->u.marc_to_xml.charset = 0;
+ return 0;
+}
+
+static int conv_xml_to_marc(yaz_record_conv_t p, const xmlNode *ptr)
+{
+ struct _xmlAttr *attr;
+ const char *charset = 0;
+ struct yaz_record_conv_rule *r;
+
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ if (!xmlStrcmp(attr->name, BAD_CAST "charset") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ charset = (const char *) attr->children->content;
+ else
+ {
+ wrbuf_printf(p->wr_error, "Bad attribute '%s'."
+ "Expected charset.", attr->name);
+ return -1;
+ }
+ }
+ r = add_rule(p, YAZ_RECORD_CONV_RULE_XML_TO_MARC);
+ if (charset)
+ r->u.xml_to_marc.charset = nmem_strdup(p->nmem, charset);
+ else
+ r->u.xml_to_marc.charset = 0;
+ return 0;
+}
+
+
+int yaz_record_conv_configure(yaz_record_conv_t p, const void *ptr_v)
+{
+ const xmlNode *ptr = ptr_v;
+
+ yaz_record_conv_reset(p);
+
+ if (ptr && ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "convert"))
+ {
+ for (ptr = ptr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type != XML_ELEMENT_NODE)
+ continue;
+ if (!strcmp((const char *) ptr->name, "xslt"))
+ {
+ if (conv_xslt(p, ptr))
+ return -1;
+ }
+ else if (!strcmp((const char *) ptr->name, "marc_to_xml"))
+ {
+ if (conv_marc_to_xml(p, ptr))
+ return -1;
+ }
+ else if (!strcmp((const char *) ptr->name, "xml_to_marc"))
+ {
+ if (conv_xml_to_marc(p, ptr))
+ return -1;
+ }
+ else
+ {
+ wrbuf_printf(p->wr_error, "Bad element '%s'."
+ "Expected xslt, marc_to_xml,...", ptr->name);
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ wrbuf_printf(p->wr_error, "Missing 'convert' element");
+ return -1;
+ }
+ return 0;
+}
+
+#else
+/* HAVE_XML2 */
+int yaz_record_conv_configure(yaz_record_conv_t p, const void *ptr_v)
+{
+ wrbuf_rewind(p->wr_error);
+ wrbuf_printf(p->wr_error, "No XML support for yaz_record_conv");
+ return -1;
+}
+
+#endif
+
+const char *yaz_record_conv_get_error(yaz_record_conv_t p)
+{
+ return wrbuf_buf(p->wr_error);
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
* Copyright (C) 1995-2006, Index Data ApS
* All rights reserved.
*
- * $Id: xmlquery.c,v 1.8 2006-04-20 20:50:51 adam Exp $
+ * $Id: xmlquery.c,v 1.9 2006-05-02 20:47:45 adam Exp $
*/
/** \file xmlquery.c
char *strVal(const xmlNode *ptr_cdata, ODR odr)
{
- char *cdata;
- int len = 0;
- const xmlNode *ptr;
-
- for (ptr = ptr_cdata; ptr; ptr = ptr->next)
- if (ptr->type == XML_TEXT_NODE)
- len += xmlStrlen(ptr->content);
- cdata = (char *) odr_malloc(odr, len+1);
- *cdata = '\0';
- for (ptr = ptr_cdata; ptr; ptr = ptr->next)
- if (ptr->type == XML_TEXT_NODE)
- strcat(cdata, (const char *) ptr->content);
- return cdata;
+ return nmem_text_node_cdata(ptr_cdata, odr->mem);
}
void yaz_xml2query_term(const xmlNode *ptr,
tstlogthread
tstxmlquery
tstpquery
+tst_filepath
+tst_record_conv
-## Copyright (C) 1994-2006, Index Data
+## Copyright (C) 1994-2006, Index Data ApS
## All rights reserved.
-## $Id: Makefile.am,v 1.14 2006-04-26 09:40:43 adam Exp $
+## $Id: Makefile.am,v 1.15 2006-05-02 20:47:46 adam Exp $
check_PROGRAMS = tsticonv tstnmem tstmatchstr tstwrbuf tstodr tstccl tstlog \
tstsoap1 tstsoap2 tstodrstack tstlogthread tstxmlquery tstpquery \
- tst_filepath
+ tst_filepath tst_record_conv
check_SCRIPTS = tstcql.sh tstmarciso.sh tstmarcxml.sh
TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
tstxmlquery_SOURCES = tstxmlquery.c
tstpquery_SOURCES = tstpquery.c
tst_filepath_SOURCES = tst_filepath.c
+tst_record_conv_SOURCES = tst_record_conv.c
--- /dev/null
+/*
+ * Copyright (C) 2005-2006, Index Data ApS
+ * See the file LICENSE for details.
+ *
+ * $Id: tst_record_conv.c,v 1.1 2006-05-02 20:47:46 adam Exp $
+ *
+ */
+#include <yaz/record_conv.h>
+#include <yaz/test.h>
+#include <yaz/wrbuf.h>
+#include <string.h>
+
+#if HAVE_XML2
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+yaz_record_conv_t conv_from_xml(const char *xmlstring, WRBUF w)
+{
+ xmlDocPtr doc = xmlParseMemory(xmlstring, strlen(xmlstring));
+ if (!doc)
+ {
+ wrbuf_printf(w, "xmlParseMemory");
+ return 0;
+ }
+ else
+ {
+ xmlNodePtr ptr = xmlDocGetRootElement(doc);
+ yaz_record_conv_t p = yaz_record_conv_create();
+
+ if (!ptr)
+ {
+ wrbuf_printf(w, "xmlDocGetRootElement");
+ yaz_record_conv_destroy(p);
+ p = 0;
+ }
+ else if (!p)
+ {
+ wrbuf_printf(w, "yaz_record_conv_create");
+ }
+ else
+ {
+ int r = yaz_record_conv_configure(p, ptr);
+
+ if (r)
+ {
+ wrbuf_puts(w, yaz_record_conv_get_error(p));
+ yaz_record_conv_destroy(p);
+ p = 0;
+ }
+ }
+ xmlFreeDoc(doc);
+ return p;
+ }
+}
+
+int conv_from_xml_compare(const char *xmlstring, const char *expect_error,
+ yaz_record_conv_t *pt)
+{
+ WRBUF w = wrbuf_alloc();
+ int ret;
+
+ yaz_record_conv_t p = conv_from_xml(xmlstring, w);
+
+ if (!p)
+ {
+ if (expect_error && !strcmp(wrbuf_buf(w), expect_error))
+ ret = 1;
+ else
+ ret = 0;
+ }
+ else
+ {
+ if (expect_error)
+ {
+ ret = 0;
+ yaz_record_conv_destroy(p);
+ }
+ else
+ {
+ if (pt)
+ *pt = p;
+ else
+ yaz_record_conv_destroy(p);
+ ret = 1;
+ }
+ }
+ wrbuf_free(w, 1);
+ return ret;
+}
+
+static void tst()
+{
+ YAZ_CHECK(conv_from_xml_compare("<bad", "xmlParseMemory", 0));
+ YAZ_CHECK(conv_from_xml_compare("<bad/>", "Missing 'convert' element", 0));
+ YAZ_CHECK(conv_from_xml_compare("<convert/>", 0, 0));
+ YAZ_CHECK(conv_from_xml_compare("<convert><bad/></convert>",
+ "Bad element 'bad'."
+ "Expected xslt, marc_to_xml,...", 0));
+ YAZ_CHECK(conv_from_xml_compare("<convert>"
+ "<xslt stylesheet=\"x.xsl\"/>"
+ "<marc_to_xml charset=\"marc-8\"/>"
+ "</convert>",
+ 0, 0));
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ YAZ_CHECK_INIT(argc, argv);
+#if HAVE_XML2
+ tst();
+#endif
+ YAZ_CHECK_TERM;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+