31#include <libxml/parser.h>
32#include <libxml/tree.h>
33#include <libxml/xinclude.h>
34#include <libxml/xpath.h>
35#include <libxml/xpathInternals.h>
37#include <libxslt/xsltutils.h>
38#include <libxslt/transform.h>
41#include <libexslt/exslt.h>
116 const char *path,
WRBUF wr_error)
118 struct _xmlAttr *attr;
119 const char *stylesheet = 0;
125 if (strcmp((
const char *) ptr->name,
"xslt"))
128 for (attr = ptr->properties; attr; attr = attr->next)
130 if (!xmlStrcmp(attr->name, BAD_CAST
"stylesheet") &&
131 attr->children && attr->children->type == XML_TEXT_NODE)
132 stylesheet = (
const char *) attr->children->content;
136 "Expected stylesheet.", attr->name);
146 for (ptr = ptr->children; ptr; ptr = ptr->next)
148 const char *
name = 0;
149 const char *value = 0;
151 if (ptr->type != XML_ELEMENT_NODE)
153 if (strcmp((
const char *) ptr->name,
"param"))
156 "Expected param.", ptr->name);
160 for (attr = ptr->properties; attr; attr = attr->next)
162 if (!xmlStrcmp(attr->name, BAD_CAST
"name") &&
163 attr->children && attr->children->type == XML_TEXT_NODE)
164 name = (
const char *) attr->children->content;
165 else if (!xmlStrcmp(attr->name, BAD_CAST
"value") &&
166 attr->children && attr->children->type == XML_TEXT_NODE)
167 value = (
const char *) attr->children->content;
171 "Expected name or value.", attr->name);
178 wrbuf_printf(wr_error,
"Missing attributes name or value");
182 if (no_parms >= max_parms)
190 strcpy(qvalue,
"\'");
191 strcat(qvalue, value);
192 strcat(qvalue,
"\'");
195 info->
xsl_parms[2 * no_parms + 1] = qvalue;
203 "attribute 'stylesheet' expected");
209 xsltStylesheetPtr xsp;
212 wrbuf_printf(wr_error,
"Element <xslt stylesheet=\"%s\"/>:"
213 " could not locate stylesheet '%s'",
214 stylesheet, stylesheet);
221 info->
xsp_doc = xmlParseFile(fullpath);
224 wrbuf_printf(wr_error,
"Element: <xslt stylesheet=\"%s\"/>:"
225 " xml parse failed: %s", stylesheet, fullpath);
233 xsp = xsltParseStylesheetDoc(xmlCopyDoc(info->
xsp_doc, 1));
236 wrbuf_printf(wr_error,
"Element: <xslt stylesheet=\"%s\"/>:"
237 " xslt parse failed: %s", stylesheet, fullpath);
245 "EXSLT not supported"
253 xsltFreeStylesheet(xsp);
265 xmlDocPtr doc = xmlParseMemory(
wrbuf_buf(record),
275 xsltStylesheetPtr xsp = xsltParseStylesheetDoc(
xsp_doc);
276 xmlDocPtr res = xsltApplyStylesheet(xsp, doc, info->
xsl_parms);
279 xmlChar *out_buf = 0;
282#if HAVE_XSLTSAVERESULTTOSTRING
283 xsltSaveResultToString(&out_buf, &out_len, res, xsp);
285 xmlDocDumpFormatMemory (res, &out_buf, &out_len, 1);
290 "xsltSaveResultToString failed");
296 wrbuf_write(record, (
const char *) out_buf, out_len);
308 xsltFreeStylesheet(xsp);
333 const char *path,
WRBUF wr_error)
335 if (strcmp((
const char *) ptr->name,
"select"))
341 const char *attr_str;
342 const char *xpath = 0;
350 "Expected xpath.", attr_str);
365 xmlDocPtr doc = xmlParseMemory(
wrbuf_buf(record),
374 xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
377 xmlXPathObjectPtr xpathObj =
378 xmlXPathEvalExpression((
const xmlChar *) info->
xpath_expr,
382 xmlNodeSetPtr nodes = xpathObj->nodesetval;
386 if (nodes->nodeNr > 0)
388 for (i = 0; i < nodes->nodeNr; i++)
390 xmlNode *ptr = nodes->nodeTab[i];
391 if (ptr->type == XML_ELEMENT_NODE)
393 for (; ptr; ptr = ptr->next)
394 if (ptr->type == XML_TEXT_NODE)
395 wrbuf_puts(record, (
const char *) ptr->content);
398 xmlXPathFreeObject(xpathObj);
400 xmlXPathFreeContext(xpathCtx);
417 const char *path,
WRBUF wr_error)
419 if (strcmp((
const char *) ptr->name,
"solrmarc"))
429 for (i = 0; i < sz; i++)
432 if (buf[i] ==
'#' && i < sz - 3 && buf[i+3] ==
';'
450 const char *path,
WRBUF wr_error)
454 struct _xmlAttr *attr;
455 const char *input_format = 0;
456 const char *output_format = 0;
458 if (strcmp((
const char *) ptr->name,
"marc"))
470 for (attr = ptr->properties; attr; attr = attr->next)
472 if (!xmlStrcmp(attr->name, BAD_CAST
"inputcharset") &&
473 attr->children && attr->children->type == XML_TEXT_NODE)
474 info->
input_charset = (
const char *) attr->children->content;
475 else if (!xmlStrcmp(attr->name, BAD_CAST
"outputcharset") &&
476 attr->children && attr->children->type == XML_TEXT_NODE)
478 else if (!xmlStrcmp(attr->name, BAD_CAST
"inputformat") &&
479 attr->children && attr->children->type == XML_TEXT_NODE)
480 input_format = (
const char *) attr->children->content;
481 else if (!xmlStrcmp(attr->name, BAD_CAST
"outputformat") &&
482 attr->children && attr->children->type == XML_TEXT_NODE)
483 output_format = (
const char *) attr->children->content;
484 else if (!xmlStrcmp(attr->name, BAD_CAST
"leaderspec") &&
485 attr->children && attr->children->type == XML_TEXT_NODE)
490 wrbuf_printf(wr_error,
"Element <marc>: expected attributes"
491 "'inputformat', 'inputcharset', 'outputformat' or"
492 " 'outputcharset', got attribute '%s'",
501 "attribute 'inputformat' required");
505 else if (!strcmp(input_format,
"marc"))
509 else if (!strcmp(input_format,
"xml"))
518 else if (!strcmp(input_format,
"json"))
524 wrbuf_printf(wr_error,
"Element <marc inputformat='%s'>: "
525 " Unsupported input format"
526 " defined by attribute value",
535 "Element <marc>: attribute 'outputformat' required");
539 else if (!strcmp(output_format,
"line"))
543 else if (!strcmp(output_format,
"marcxml"))
549 else if (!strcmp(output_format,
"turbomarc"))
555 else if (!strcmp(output_format,
"marc"))
559 else if (!strcmp(output_format,
"marcxchange"))
565 else if (!strcmp(output_format,
"json"))
573 wrbuf_printf(wr_error,
"Element <marc outputformat='%s'>: "
574 " Unsupported output format"
575 " defined by attribute value",
587 "Element <marc inputcharset='%s' outputcharset='%s'>:"
588 " Unsupported character set mapping"
589 " defined by attribute values",
599 "attribute 'outputcharset' missing");
606 "attribute 'inputcharset' missing");
643 xmlDocPtr doc = xmlParseMemory(
wrbuf_buf(record),
690#define RDF_LOOKUP_MAX_KEYS 20
691#define RDF_LOOKUP_MAX_NAMESPACES 20
709 struct _xmlAttr *attr;
720 for (attr = ptr->properties; attr; attr = attr->next)
722 if (!xmlStrcmp(attr->name, BAD_CAST
"xpath") &&
723 attr->children && attr->children->type == XML_TEXT_NODE)
728 "Expected xpath.", attr->name);
733 for ( ; ptr ; ptr = ptr->next)
735 if (ptr->type == XML_ELEMENT_NODE)
737 if (!xmlStrcmp(ptr->name, BAD_CAST
"key"))
739 for (attr = ptr->properties; attr; attr = attr->next)
741 if (!xmlStrcmp(attr->name, BAD_CAST
"field") &&
742 attr->children && attr->children->type == XML_TEXT_NODE)
744 info->
keys[nkeys++] =
751 info->
keys[nkeys] = 0;
756 "Expected xpath.", attr->name);
761 else if (!xmlStrcmp(ptr->name, BAD_CAST
"server"))
763 for (attr = ptr->properties; attr; attr = attr->next)
765 if (!xmlStrcmp(attr->name, BAD_CAST
"url") &&
766 attr->children && attr->children->type == XML_TEXT_NODE)
770 else if (!xmlStrcmp(attr->name, BAD_CAST
"method") &&
771 attr->children && attr->children->type == XML_TEXT_NODE)
778 "Expected url or method.", attr->name);
786 "Expected 'key' or 'server'.", ptr->name);
795 const char *path,
WRBUF wr_error)
800 const char *defserver =
"http://id.loc.gov/authorities/names/label/%s";
801 char ** namespaces = 0;
805 struct _xmlAttr *attr;
806 if (strcmp((
const char *) ptr->name,
"rdf-lookup"))
810 for (attr = ptr->properties; attr; attr = attr->next)
812 if (!xmlStrcmp(attr->name, BAD_CAST
"debug") &&
813 attr->children && attr->children->type == XML_TEXT_NODE)
815 debug = atoi((
const char *) attr->children->content);
817 else if (!xmlStrcmp(attr->name, BAD_CAST
"timeout") &&
818 attr->children && attr->children->type == XML_TEXT_NODE)
820 timeout = atoi((
const char *) attr->children->content);
824 wrbuf_printf(wr_error,
"Bad attribute '%s' for <rdf-lookup>. "
825 "Expected 'debug'", attr->name);
835 for ( ; ptr ; ptr = ptr->next) {
836 if (ptr->type == XML_ELEMENT_NODE)
838 if (!strcmp((
const char *)ptr->name,
"lookup"))
851 next = &((*next)->next);
862 else if (!strcmp((
const char *)ptr->name,
"namespace"))
866 struct _xmlAttr *attr;
867 for (attr = ptr->properties; attr; attr = attr->next)
869 if (!xmlStrcmp(attr->name, BAD_CAST
"prefix") &&
870 attr->children && attr->children->type == XML_TEXT_NODE)
872 prefix =
nmem_strdup(nmem, (
const char *) attr->children->content);
874 else if (!xmlStrcmp(attr->name, BAD_CAST
"href") &&
875 attr->children && attr->children->type == XML_TEXT_NODE)
877 href =
nmem_strdup(nmem, (
const char *) attr->children->content);
882 "Expected 'prefix' or 'href'", attr->name);
889 namespaces[nns++] = prefix;
890 namespaces[nns++] = href;
891 namespaces[nns] = 0 ;
895 wrbuf_printf(wr_error,
"Bad namespace, need both 'prefix' and 'href'");
902 wrbuf_printf(wr_error,
"Expected a <lookup> tag under rdf-lookup, not <%s>",
943 xmlNodePtr comnode = xmlNewComment((
const xmlChar *)
wrbuf_cstr(com));
944 xmlAddNextSibling(n, comnode);
957 for (nkey = 0; !done && info->
keys[nkey]; nkey++)
959 xmlXPathObjectPtr xpo =
960 xmlXPathEvalExpression((
const xmlChar *)info->
keys[nkey], xpathCtx);
961 xmlNodeSetPtr fldNodes = xpo->nodesetval;
965 for (i = 0; !done && i < fldNodes->nodeNr; i++)
967 xmlNode *f = fldNodes->nodeTab[i];
968 if (f->type == XML_ELEMENT_NODE)
970 for (; f && !done; f = f->next)
971 if (f->type == XML_TEXT_NODE)
975 char *keybuf =
xmalloc(3*strlen((
const char*) f->content)+1);
994 if ((resp->
code == 302 || resp->
code == 200)
998 if (newuri && *newuri)
1000 xmlSetProp(n, (
const xmlChar *)
"rdf:about",
1001 (
const xmlChar *)newuri);
1011 "No X-URI Header in response!",
YLOG_LOG);
1023 for ( ; r; r = r->
next)
1033 if (i < resp->content_len)
1052 xmlXPathFreeObject(xpo);
1062 xmlDocPtr doc = xmlParseMemory(
wrbuf_buf(record),
1072 xmlChar *out_buf = 0;
1074 xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
1080 xmlXPathRegisterNs(xpathCtx, (
const xmlChar *)ns[0],
1081 (
const xmlChar *)ns[1]);
1086 xmlXPathObjectPtr xpathObj =
1087 xmlXPathEvalExpression((xmlChar *)(info->
xpath), xpathCtx);
1091 xmlNodeSetPtr nodes = xpathObj->nodesetval;
1096 for (i = 0; i < nodes->nodeNr; i++)
1098 xmlNode *ptr = nodes->nodeTab[i];
1100 (
const char*) ptr->name, ptr->content);
1104 xmlXPathFreeObject(xpathObj);
1109 "Cannot compile X-Path expr: %s",
1115 xmlXPathFreeContext(xpathCtx);
1117 xmlDocDumpFormatMemory (doc, &out_buf, &out_len, 1);
1121 "xmlDocDumpFormatMemory failed");
1127 wrbuf_write(record, (
const char *) out_buf, out_len);
1147 bt[i-1].
next = &bt[i];
1152 bt[i-1].
next = &bt[i];
1159 bt[i-1].
next = &bt[i];
1165 bt[i-1].
next = &bt[i];
1171 bt[i-1].
next = types;
1175 for (ptr = ptr->children; ptr; ptr = ptr->next)
1180 if (ptr->type != XML_ELEMENT_NODE)
1182 for (t = &bt[0]; t; t = t->
next)
1195 "unsupported element <%s>", ptr->name);
1202 memcpy(r->
type, t,
sizeof(*t));
1216 const char *input_record_buf,
1217 size_t input_record_len,
1218 WRBUF output_record)
1221 WRBUF record = output_record;
1224 wrbuf_write(record, input_record_buf, input_record_len);
1225 for (; ret == 0 && r; r = r->
next)
1243 WRBUF output_record)
1290 const char *input_record_buf,
1291 size_t input_record_len,
1292 WRBUF output_record)
1296 input_record_len, output_record);
int atoi_n_check(const char *buf, int size, int *val)
like atoi_n but checks for proper formatting
const char * z_HTTP_header_lookup(const Z_HTTP_Header *hp, const char *n)
void yaz_log(int level, const char *fmt,...)
Writes log message.
#define YLOG_DEBUG
log level: debugging
#define YLOG_LOG
log level: log (regular)
int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize)
read ISO2709/MARC record from buffer
int yaz_marc_read_xml(yaz_marc_t mt, const xmlNode *ptr)
parses MARCXML/MarcXchange/TurboMARC record from xmlNode pointer
int yaz_marc_leader_spec(yaz_marc_t mt, const char *leader_spec)
sets leader spec (for modifying bytes in 24 byte leader)
int yaz_marc_check_marc21_coding(const char *charset, const char *marc_buf, int sz)
check if MARC21 is UTF-8 encoded
yaz_marc_t yaz_marc_create(void)
construct yaz_marc_t handle
void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd)
set iconv handle for character set conversion
void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
set XML mode YAZ_MARC_LINE, YAZ_MARCXML, YAZ_MARC_ISO2709 ..
void yaz_marc_destroy(yaz_marc_t mt)
destroy yaz_marc_t handle
int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr)
writes record in mode - given by yaz_marc_xml mode
#define YAZ_MARC_MARCXML
Output format: MARCXML.
#define YAZ_MARC_XCHANGE
Output format: MarcXchange (ISO25577)
#define YAZ_MARC_ISO2709
Output format: ISO2709.
#define YAZ_MARC_LINE
Output format: Line-format.
#define YAZ_MARC_JSON
Output format: JSON.
#define YAZ_MARC_TURBOMARC
Output format: Turbo MARC Index Data format (XML based)
void nmem_reset(NMEM n)
releases memory associaged with an NMEM handle
NMEM nmem_create(void)
returns new NMEM handle
void * nmem_malloc(NMEM n, size_t size)
allocates memory block on NMEM handle
void nmem_destroy(NMEM n)
destroys NMEM handle and memory associated with it
Header for Nibble Memory functions.
char * nmem_strdup(NMEM mem, const char *src)
allocates string on NMEM handle (similar strdup)
int yaz_opac_check_marc21_coding(const char *charset, Z_OPACRecord *r)
void yaz_opac_decode_wrbuf(yaz_marc_t mt, Z_OPACRecord *r, WRBUF wrbuf)
Performs "pretty" display of OPAC record to WRBUF using marc_t.
static void * construct_marc(const xmlNode *ptr, const char *path, WRBUF wr_error)
static void destroy_marc(void *info)
int yaz_record_conv_configure_t(yaz_record_conv_t p, const xmlNode *ptr, struct yaz_record_conv_type *types)
static void * construct_rdf_lookup(const xmlNode *ptr, const char *path, WRBUF wr_error)
void yaz_record_conv_destroy(yaz_record_conv_t p)
static void destroy_rdf_lookup(void *info)
static int convert_solrmarc(void *info, WRBUF record, WRBUF wr_error)
const char * yaz_record_conv_get_error(yaz_record_conv_t p)
const char * yaz_record_get_output_charset(yaz_record_conv_t p)
void yaz_record_conv_set_path(yaz_record_conv_t p, const char *path)
#define RDF_LOOKUP_MAX_NAMESPACES
static int yaz_record_conv_record_rule(yaz_record_conv_t p, struct yaz_record_conv_rule *r, const char *input_record_buf, size_t input_record_len, WRBUF output_record)
int yaz_record_conv_record(yaz_record_conv_t p, const char *input_record_buf, size_t input_record_len, WRBUF output_record)
static struct rdf_lookup_info * construct_one_rdf_lookup(NMEM nmem, const xmlNode *ptr, WRBUF wr_error, int timeout)
#define RDF_LOOKUP_MAX_KEYS
static void * construct_solrmarc(const xmlNode *ptr, const char *path, WRBUF wr_error)
yaz_record_conv_t yaz_record_conv_create()
static void * construct_select(const xmlNode *ptr, const char *path, WRBUF wr_error)
static void rdf_lookup_debug_comment(xmlNode *n, WRBUF uri, Z_HTTP_Response *resp, struct rdf_lookup_info *info, yaz_timing_t tim, const char *msg, int yloglevel)
static int convert_rdf_lookup(void *rinfo, WRBUF record, WRBUF wr_error)
static void rdf_lookup_node(xmlNode *n, xmlXPathContextPtr xpathCtx, struct rdf_lookup_info *info)
static void destroy_xslt(void *vinfo)
int yaz_record_conv_configure(yaz_record_conv_t p, const xmlNode *ptr)
static int convert_marc(void *info, WRBUF record, WRBUF wr_error)
int yaz_record_conv_opac_record(yaz_record_conv_t p, Z_OPACRecord *input_record, WRBUF output_record)
static void destroy_solrmarc(void *info)
static int convert_select(void *vinfo, WRBUF record, WRBUF wr_error)
static void * construct_xslt(const xmlNode *ptr, const char *path, WRBUF wr_error)
static void destroy_select(void *vinfo)
static void yaz_record_conv_reset(yaz_record_conv_t p)
reset rules+configuration
static int convert_xslt(void *vinfo, WRBUF record, WRBUF wr_error)
Record Conversions Utility.
struct yaz_record_conv_struct * yaz_record_conv_t
int yaz_iconv_close(yaz_iconv_t cd)
just like iconv_close(3)
yaz_iconv_t yaz_iconv_open(const char *tocode, const char *fromcode)
just like iconv_open(3)
const char * output_charset
const char * input_charset
char * keys[RDF_LOOKUP_MAX_KEYS]
struct rdf_lookup_info * next
the internals of a yaz_marc_t handle
transformation info (rule info)
struct yaz_record_conv_type * type
struct yaz_record_conv_rule * next
The internal structure for yaz_record_conv_t.
NMEM nmem
memory for configuration
WRBUF wr_error
string buffer for error messages
char * path
path for opening files
struct yaz_record_conv_rule * rules
conversion rules (allocated using NMEM)
struct yaz_record_conv_rule ** rules_p
pointer to last conversion rule pointer in chain
struct yaz_record_conv_type * next
pointer to next type ; NULL for last
int(* convert)(void *info, WRBUF record, WRBUF error_msg)
converts a record
void *(* construct)(const xmlNode *, const char *path, WRBUF error_msg)
construct and configure a type of ours
void(* destroy)(void *info)
destroys our conversion handler
yaz_timing_t yaz_timing_create(void)
create timing handle
void yaz_timing_stop(yaz_timing_t t)
stop timer
void yaz_timing_destroy(yaz_timing_t *tp)
destroys timing handle
void yaz_timing_start(yaz_timing_t t)
start timer
double yaz_timing_get_real(yaz_timing_t t)
returns real time in seconds
char * yaz_filepath_resolve(const char *fname, const char *path, const char *base, char *fullpath)
resolve file on path
void yaz_encode_uri_component(char *dst, const char *uri)
encodes URI component
void yaz_url_set_timeout(yaz_url_t p, int sec, int ns)
sets I/O timeout
yaz_url_t yaz_url_create(void)
creates a URL fetcher handle
Z_HTTP_Response * yaz_url_exec(yaz_url_t p, const char *uri, const char *method, Z_HTTP_Header *user_headers, const char *buf, size_t len)
executes the actual HTTP request (including redirects, etc)
void yaz_url_set_max_redirects(yaz_url_t p, int num)
sets maximum number of redirects
void yaz_url_destroy(yaz_url_t p)
destroys a URL fetcher
const char * yaz_url_get_error(yaz_url_t p)
get last error from yaz_url_exec
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
void wrbuf_rewind(WRBUF b)
empty WRBUF content (length of buffer set to 0)
WRBUF wrbuf_alloc(void)
construct WRBUF
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
void wrbuf_puts_replace_str(WRBUF b, const char *buf, const char *from, const char *to)
puts buf to WRBUF and replaces a string with another
void wrbuf_puts(WRBUF b, const char *buf)
appends C-string to WRBUF
void wrbuf_write(WRBUF b, const char *buf, size_t size)
append constant size buffer to WRBUF
Header for WRBUF (growing buffer)
Header for memory handling functions.
#define xstrdup(s)
utility macro which calls xstrdup_f
#define xfree(x)
utility macro which calls xfree_f
#define xmalloc(x)
utility macro which calls malloc_f
const char * yaz_xml_get_prop(const xmlNode *n, const char *fmt,...)
XML node getter/creation utilities.
Header for YAZ iconv interface.
ASN.1 Module RecordSyntax-opac.