30 #include <libxml/parser.h>
31 #include <libxml/tree.h>
32 #include <libxml/xinclude.h>
33 #include <libxml/xpath.h>
34 #include <libxml/xpathInternals.h>
36 #include <libxslt/xsltutils.h>
37 #include <libxslt/transform.h>
40 #include <libexslt/exslt.h>
115 const char *path,
WRBUF wr_error)
117 struct _xmlAttr *attr;
118 const char *stylesheet = 0;
124 if (strcmp((
const char *) ptr->name,
"xslt"))
127 for (attr = ptr->properties; attr; attr = attr->next)
129 if (!xmlStrcmp(attr->name, BAD_CAST
"stylesheet") &&
130 attr->children && attr->children->type == XML_TEXT_NODE)
131 stylesheet = (
const char *) attr->children->content;
135 "Expected stylesheet.", attr->name);
143 nmem, (2 * max_parms + 1) *
sizeof(*info->xsl_parms));
145 for (ptr = ptr->children; ptr; ptr = ptr->next)
147 const char *
name = 0;
148 const char *value = 0;
150 if (ptr->type != XML_ELEMENT_NODE)
152 if (strcmp((
const char *) ptr->name,
"param"))
155 "Expected param.", ptr->name);
159 for (attr = ptr->properties; attr; attr = attr->next)
161 if (!xmlStrcmp(attr->name, BAD_CAST
"name") &&
162 attr->children && attr->children->type == XML_TEXT_NODE)
163 name = (
const char *) attr->children->content;
164 else if (!xmlStrcmp(attr->name, BAD_CAST
"value") &&
165 attr->children && attr->children->type == XML_TEXT_NODE)
166 value = (
const char *) attr->children->content;
170 "Expected name or value.", attr->name);
177 wrbuf_printf(wr_error,
"Missing attributes name or value");
181 if (no_parms >= max_parms)
189 strcpy(qvalue,
"\'");
190 strcat(qvalue, value);
191 strcat(qvalue,
"\'");
194 info->xsl_parms[2 * no_parms + 1] = qvalue;
197 info->xsl_parms[2 * no_parms] = 0;
202 "attribute 'stylesheet' expected");
208 xsltStylesheetPtr xsp;
211 wrbuf_printf(wr_error,
"Element <xslt stylesheet=\"%s\"/>:"
212 " could not locate stylesheet '%s'",
213 stylesheet, stylesheet);
220 info->xsp_doc = xmlParseFile(fullpath);
223 wrbuf_printf(wr_error,
"Element: <xslt stylesheet=\"%s\"/>:"
224 " xml parse failed: %s", stylesheet, fullpath);
232 xsp = xsltParseStylesheetDoc(xmlCopyDoc(info->xsp_doc, 1));
235 wrbuf_printf(wr_error,
"Element: <xslt stylesheet=\"%s\"/>:"
236 " xslt parse failed: %s", stylesheet, fullpath);
244 "EXSLT not supported"
247 xmlFreeDoc(info->xsp_doc);
252 xsltFreeStylesheet(xsp);
264 xmlDocPtr doc = xmlParseMemory(
wrbuf_buf(record),
274 xsltStylesheetPtr xsp = xsltParseStylesheetDoc(
xsp_doc);
275 xmlDocPtr res = xsltApplyStylesheet(xsp, doc, info->
xsl_parms);
278 xmlChar *out_buf = 0;
281 #if HAVE_XSLTSAVERESULTTOSTRING
282 xsltSaveResultToString(&out_buf, &out_len, res, xsp);
284 xmlDocDumpFormatMemory (res, &out_buf, &out_len, 1);
289 "xsltSaveResultToString failed");
295 wrbuf_write(record, (
const char *) out_buf, out_len);
307 xsltFreeStylesheet(xsp);
332 const char *path,
WRBUF wr_error)
334 if (strcmp((
const char *) ptr->name,
"select"))
340 const char *attr_str;
341 const char *xpath = 0;
349 "Expected xpath.", attr_str);
364 xmlDocPtr doc = xmlParseMemory(
wrbuf_buf(record),
373 xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
376 xmlXPathObjectPtr xpathObj =
377 xmlXPathEvalExpression((
const xmlChar *) info->
xpath_expr,
381 xmlNodeSetPtr nodes = xpathObj->nodesetval;
385 if (nodes->nodeNr > 0)
387 for (i = 0; i < nodes->nodeNr; i++)
389 xmlNode *ptr = nodes->nodeTab[i];
390 if (ptr->type == XML_ELEMENT_NODE)
392 for (; ptr; ptr = ptr->next)
393 if (ptr->type == XML_TEXT_NODE)
394 wrbuf_puts(record, (
const char *) ptr->content);
397 xmlXPathFreeObject(xpathObj);
399 xmlXPathFreeContext(xpathCtx);
416 const char *path,
WRBUF wr_error)
418 if (strcmp((
const char *) ptr->name,
"solrmarc"))
428 for (i = 0; i < sz; i++)
431 if (buf[i] ==
'#' && i < sz - 3 && buf[i+3] ==
';'
449 const char *path,
WRBUF wr_error)
453 struct _xmlAttr *attr;
454 const char *input_format = 0;
455 const char *output_format = 0;
457 if (strcmp((
const char *) ptr->name,
"marc"))
469 for (attr = ptr->properties; attr; attr = attr->next)
471 if (!xmlStrcmp(attr->name, BAD_CAST
"inputcharset") &&
472 attr->children && attr->children->type == XML_TEXT_NODE)
473 info->
input_charset = (
const char *) attr->children->content;
474 else if (!xmlStrcmp(attr->name, BAD_CAST
"outputcharset") &&
475 attr->children && attr->children->type == XML_TEXT_NODE)
477 else if (!xmlStrcmp(attr->name, BAD_CAST
"inputformat") &&
478 attr->children && attr->children->type == XML_TEXT_NODE)
479 input_format = (
const char *) attr->children->content;
480 else if (!xmlStrcmp(attr->name, BAD_CAST
"outputformat") &&
481 attr->children && attr->children->type == XML_TEXT_NODE)
482 output_format = (
const char *) attr->children->content;
483 else if (!xmlStrcmp(attr->name, BAD_CAST
"leaderspec") &&
484 attr->children && attr->children->type == XML_TEXT_NODE)
489 wrbuf_printf(wr_error,
"Element <marc>: expected attributes"
490 "'inputformat', 'inputcharset', 'outputformat' or"
491 " 'outputcharset', got attribute '%s'",
500 "attribute 'inputformat' required");
504 else if (!strcmp(input_format,
"marc"))
508 else if (!strcmp(input_format,
"xml"))
517 else if (!strcmp(input_format,
"json"))
523 wrbuf_printf(wr_error,
"Element <marc inputformat='%s'>: "
524 " Unsupported input format"
525 " defined by attribute value",
534 "Element <marc>: attribute 'outputformat' required");
538 else if (!strcmp(output_format,
"line"))
542 else if (!strcmp(output_format,
"marcxml"))
548 else if (!strcmp(output_format,
"turbomarc"))
554 else if (!strcmp(output_format,
"marc"))
558 else if (!strcmp(output_format,
"marcxchange"))
564 else if (!strcmp(output_format,
"json"))
572 wrbuf_printf(wr_error,
"Element <marc outputformat='%s'>: "
573 " Unsupported output format"
574 " defined by attribute value",
586 "Element <marc inputcharset='%s' outputcharset='%s'>:"
587 " Unsupported character set mapping"
588 " defined by attribute values",
598 "attribute 'outputcharset' missing");
605 "attribute 'inputcharset' missing");
642 xmlDocPtr doc = xmlParseMemory(
wrbuf_buf(record),
689 #define RDF_LOOKUP_MAX_KEYS 20
690 #define RDF_LOOKUP_MAX_NAMESPACES 20
708 struct _xmlAttr *attr;
719 for (attr = ptr->properties; attr; attr = attr->next)
721 if (!xmlStrcmp(attr->name, BAD_CAST
"xpath") &&
722 attr->children && attr->children->type == XML_TEXT_NODE)
727 "Expected xpath.", attr->name);
732 for ( ; ptr ; ptr = ptr->next)
734 if (ptr->type == XML_ELEMENT_NODE)
736 if (!xmlStrcmp(ptr->name, BAD_CAST
"key"))
738 for (attr = ptr->properties; attr; attr = attr->next)
740 if (!xmlStrcmp(attr->name, BAD_CAST
"field") &&
741 attr->children && attr->children->type == XML_TEXT_NODE)
743 info->
keys[nkeys++] =
750 info->
keys[nkeys] = 0;
755 "Expected xpath.", attr->name);
760 else if (!xmlStrcmp(ptr->name, BAD_CAST
"server"))
762 for (attr = ptr->properties; attr; attr = attr->next)
764 if (!xmlStrcmp(attr->name, BAD_CAST
"url") &&
765 attr->children && attr->children->type == XML_TEXT_NODE)
769 else if (!xmlStrcmp(attr->name, BAD_CAST
"method") &&
770 attr->children && attr->children->type == XML_TEXT_NODE)
777 "Expected url or method.", attr->name);
785 "Expected 'key' or 'server'.", ptr->name);
794 const char *path,
WRBUF wr_error)
799 const char *defserver =
"http://id.loc.gov/authorities/names/label/%s";
800 char ** namespaces = 0;
804 struct _xmlAttr *attr;
805 if (strcmp((
const char *) ptr->name,
"rdf-lookup"))
809 for (attr = ptr->properties; attr; attr = attr->next)
811 if (!xmlStrcmp(attr->name, BAD_CAST
"debug") &&
812 attr->children && attr->children->type == XML_TEXT_NODE)
814 debug = atoi((
const char *) attr->children->content);
816 else if (!xmlStrcmp(attr->name, BAD_CAST
"timeout") &&
817 attr->children && attr->children->type == XML_TEXT_NODE)
819 timeout = atoi((
const char *) attr->children->content);
823 wrbuf_printf(wr_error,
"Bad attribute '%s' for <rdf-lookup>. "
824 "Expected 'debug'", attr->name);
834 for ( ; ptr ; ptr = ptr->next) {
835 if (ptr->type == XML_ELEMENT_NODE)
837 if (!strcmp((
const char *)ptr->name,
"lookup"))
850 next = &((*next)->next);
861 else if (!strcmp((
const char *)ptr->name,
"namespace"))
865 struct _xmlAttr *attr;
866 for (attr = ptr->properties; attr; attr = attr->next)
868 if (!xmlStrcmp(attr->name, BAD_CAST
"prefix") &&
869 attr->children && attr->children->type == XML_TEXT_NODE)
871 prefix =
nmem_strdup(nmem, (
const char *) attr->children->content);
873 else if (!xmlStrcmp(attr->name, BAD_CAST
"href") &&
874 attr->children && attr->children->type == XML_TEXT_NODE)
876 href =
nmem_strdup(nmem, (
const char *) attr->children->content);
881 "Expected 'prefix' or 'href'", attr->name);
888 namespaces[nns++] = prefix;
889 namespaces[nns++] = href;
890 namespaces[nns] = 0 ;
894 wrbuf_printf(wr_error,
"Bad namespace, need both 'prefix' and 'href'");
901 wrbuf_printf(wr_error,
"Expected a <lookup> tag under rdf-lookup, not <%s>",
942 xmlNodePtr comnode = xmlNewComment((
const xmlChar *)
wrbuf_cstr(com));
943 xmlAddNextSibling(n, comnode);
956 for (nkey = 0; !done && info->
keys[nkey]; nkey++)
958 xmlXPathObjectPtr xpo =
959 xmlXPathEvalExpression((
const xmlChar *)info->
keys[nkey], xpathCtx);
960 xmlNodeSetPtr fldNodes = xpo->nodesetval;
964 for (i = 0; !done && i < fldNodes->nodeNr; i++)
966 xmlNode *f = fldNodes->nodeTab[i];
967 if (f->type == XML_ELEMENT_NODE)
969 for (; f && !done; f = f->next)
970 if (f->type == XML_TEXT_NODE)
974 char *keybuf =
xmalloc(3*strlen((
const char*) f->content)+1);
993 if ((resp->
code == 302 || resp->
code == 200)
997 if (newuri && *newuri)
999 xmlSetProp(n, (
const xmlChar *)
"rdf:about",
1000 (
const xmlChar *)newuri);
1010 "No X-URI Header in response!",
YLOG_LOG);
1022 for ( ; r; r = r->
next)
1032 if (i < resp->content_len)
1051 xmlXPathFreeObject(xpo);
1061 xmlDocPtr doc = xmlParseMemory(
wrbuf_buf(record),
1071 xmlChar *out_buf = 0;
1073 xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
1079 xmlXPathRegisterNs(xpathCtx, (
const xmlChar *)ns[0],
1080 (
const xmlChar *)ns[1]);
1085 xmlXPathObjectPtr xpathObj =
1086 xmlXPathEvalExpression((xmlChar *)(info->
xpath), xpathCtx);
1090 xmlNodeSetPtr nodes = xpathObj->nodesetval;
1095 for (i = 0; i < nodes->nodeNr; i++)
1097 xmlNode *ptr = nodes->nodeTab[i];
1099 (
const char*) ptr->name, ptr->content);
1103 xmlXPathFreeObject(xpathObj);
1108 "Cannot compile X-Path expr: %s",
1114 xmlXPathFreeContext(xpathCtx);
1116 xmlDocDumpFormatMemory (doc, &out_buf, &out_len, 1);
1120 "xmlDocDumpFormatMemory failed");
1126 wrbuf_write(record, (
const char *) out_buf, out_len);
1146 bt[i-1].
next = &bt[i];
1151 bt[i-1].
next = &bt[i];
1158 bt[i-1].
next = &bt[i];
1164 bt[i-1].
next = &bt[i];
1170 bt[i-1].
next = types;
1174 for (ptr = ptr->children; ptr; ptr = ptr->next)
1179 if (ptr->type != XML_ELEMENT_NODE)
1181 for (t = &bt[0]; t; t = t->
next)
1194 "unsupported element <%s>", ptr->name);
1201 memcpy(r->
type, t,
sizeof(*t));
1215 const char *input_record_buf,
1216 size_t input_record_len,
1217 WRBUF output_record)
1220 WRBUF record = output_record;
1223 wrbuf_write(record, input_record_buf, input_record_len);
1224 for (; ret == 0 && r; r = r->
next)
1242 WRBUF output_record)
1289 const char *input_record_buf,
1290 size_t input_record_len,
1291 WRBUF output_record)
1295 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 destroy_marc(void *info)
int yaz_record_conv_configure_t(yaz_record_conv_t p, const xmlNode *ptr, struct yaz_record_conv_type *types)
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)
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)
static void * construct_rdf_lookup(const xmlNode *ptr, const char *path, WRBUF wr_error)
int yaz_record_conv_record(yaz_record_conv_t p, const char *input_record_buf, size_t input_record_len, WRBUF output_record)
#define RDF_LOOKUP_MAX_KEYS
yaz_record_conv_t yaz_record_conv_create()
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)
static void * construct_xslt(const xmlNode *ptr, const char *path, WRBUF wr_error)
int yaz_record_conv_configure(yaz_record_conv_t p, const xmlNode *ptr)
static struct rdf_lookup_info * construct_one_rdf_lookup(NMEM nmem, const xmlNode *ptr, WRBUF wr_error, int timeout)
const char * yaz_record_get_output_charset(yaz_record_conv_t p)
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 * construct_marc(const xmlNode *ptr, const char *path, WRBUF wr_error)
static void destroy_solrmarc(void *info)
static void * construct_solrmarc(const xmlNode *ptr, const char *path, WRBUF wr_error)
static int convert_select(void *vinfo, WRBUF record, WRBUF wr_error)
static void * construct_select(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
void *(* construct)(const xmlNode *, const char *path, WRBUF error_msg)
construct and configure a type of ours
int(* convert)(void *info, WRBUF record, WRBUF error_msg)
converts a record
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
const char * yaz_url_get_error(yaz_url_t p)
get last error from yaz_url_exec
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
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
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 wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
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
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
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.