1 /* $Id: mod_dom.c,v 1.3 2007-02-12 13:24:31 marc Exp $
2 Copyright (C) 1995-2007
5 This file is part of the Zebra server.
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <yaz/diagbib1.h>
28 #include <yaz/tpath.h>
30 #include <libxml/xmlversion.h>
31 #include <libxml/parser.h>
32 #include <libxml/tree.h>
33 #include <libxml/xmlIO.h>
34 #include <libxml/xmlreader.h>
35 #include <libxslt/transform.h>
36 #include <libxslt/xsltutils.h>
39 #include <libexslt/exslt.h>
42 #include <idzebra/util.h>
43 #include <idzebra/recctrl.h>
46 const char *stylesheet;
47 xsltStylesheetPtr stylesheet_xsp;
48 struct convert_s *next;
51 struct filter_extract {
53 struct convert_s *convert;
57 struct convert_s *convert;
60 struct filter_retrieve {
62 const char *identifier;
63 struct convert_s *convert;
64 struct filter_retrieve *next;
67 #define DOM_INPUT_XMLREADER 1
68 #define DOM_INPUT_MARC 2
72 struct convert_s *convert;
76 const char *input_charset;
81 xmlTextReaderPtr reader;
85 struct filter_input *next;
91 const char *profile_path;
95 struct filter_extract *extract;
96 struct filter_retrieve *retrieve_list;
97 struct filter_input *input_list;
98 struct filter_store *store;
101 #define XML_STRCMP(a,b) strcmp((char*)a, b)
102 #define XML_STRLEN(a) strlen((char*)a)
106 static void format_pi_zebra_err(char *err_str, const char *pi_str, const char *look)
108 strncpy(err_str, pi_str, look - pi_str);
109 strncpy(err_str + (look - pi_str), "->", 2);
110 strcpy(err_str + (look - pi_str + 2) , look);
115 use PI parsing like this
117 if (!parse_pi_zebra_20(pi_str, err_str))
118 printf("ERROR '%s'\n", err_str);
122 static int parse_pi_zebra_20(const char *pi_str, char *err_str)
124 const char *look = pi_str;
136 // parsing record instruction
137 if (0 == strncmp(look, "record", 6)){
141 if (*look && 0 == strncmp(look, " id=", 4)){
145 while (*look && ' ' != *look)
148 strncpy(value, bval, eval - bval);
149 value[eval - bval] = '\0';
151 printf("%s\n", value);
154 if (*look && 0 == strncmp(look, " rank=", 6)){
158 while (*look && ' ' != *look)
161 strncpy(value, bval, eval - bval);
162 value[eval - bval] = '\0';
164 printf("%s\n", value);
170 format_pi_zebra_err(err_str, pi_str, look);
173 // parsing index instruction
174 else if (0 == strncmp(look, "index", 5)){
178 // parsing all index name/type pairs
179 while (*look && ' ' == *look && *(look+1)){
182 // index name must not start with ';' or ' '
183 if (!*look || ':' == *look || ' ' == *look){
184 format_pi_zebra_err(err_str, pi_str, look);
188 // setting name and type to zero
192 // parsing one index name
194 while (*look && ':' != *look && ' ' != *look){
198 strncpy(index, bval, eval - bval);
199 index[eval - bval] = '\0';
202 // parsing one index type, if existing
207 while (*look && ' ' != *look){
211 strncpy(type, bval, eval - bval);
212 type[eval - bval] = '\0';
215 printf(" %s:%s\n", index, type);
221 format_pi_zebra_err(err_str, pi_str, look);
225 // remaining unparsed rest of PI
227 format_pi_zebra_err(err_str, pi_str, look);
234 static void set_param_str(const char **params, const char *name,
235 const char *value, ODR odr)
237 char *quoted = odr_malloc(odr, 3 + strlen(value));
238 sprintf(quoted, "'%s'", value);
246 static void set_param_int(const char **params, const char *name,
249 char *quoted = odr_malloc(odr, 30); /* 25 digits enough for 2^64 */
252 sprintf(quoted, "'" ZINT_FORMAT "'", value);
258 static void *filter_init(Res res, RecType recType)
260 struct filter_info *tinfo = (struct filter_info *) xmalloc(sizeof(*tinfo));
262 tinfo->full_name = 0;
263 tinfo->profile_path = 0;
264 tinfo->odr_record = odr_createmem(ODR_ENCODE);
265 tinfo->odr_config = odr_createmem(ODR_ENCODE);
267 tinfo->retrieve_list = 0;
268 tinfo->input_list = 0;
270 tinfo->doc_config = 0;
279 static int attr_content(struct _xmlAttr *attr, const char *name,
280 const char **dst_content)
282 if (!XML_STRCMP(attr->name, name) && attr->children
283 && attr->children->type == XML_TEXT_NODE)
285 *dst_content = (const char *)(attr->children->content);
291 static void destroy_xsp(struct convert_s *c)
295 if (c->stylesheet_xsp)
296 xsltFreeStylesheet(c->stylesheet_xsp);
301 static void destroy_dom(struct filter_info *tinfo)
305 destroy_xsp(tinfo->extract->convert);
310 destroy_xsp(tinfo->store->convert);
313 if (tinfo->input_list)
315 struct filter_input *i_ptr;
316 for (i_ptr = tinfo->input_list; i_ptr; i_ptr = i_ptr->next)
320 case DOM_INPUT_XMLREADER:
321 if (i_ptr->u.xmlreader.reader)
322 xmlFreeTextReader(i_ptr->u.xmlreader.reader);
325 yaz_iconv_close(i_ptr->u.marc.iconv);
326 yaz_marc_destroy(i_ptr->u.marc.handle);
329 destroy_xsp(i_ptr->convert);
331 tinfo->input_list = 0;
333 if (tinfo->retrieve_list)
335 struct filter_retrieve *r_ptr;
336 for (r_ptr = tinfo->retrieve_list; r_ptr; r_ptr = r_ptr->next)
337 destroy_xsp(r_ptr->convert);
338 tinfo->retrieve_list = 0;
341 if (tinfo->doc_config)
343 xmlFreeDoc(tinfo->doc_config);
344 tinfo->doc_config = 0;
346 odr_reset(tinfo->odr_config);
349 static ZEBRA_RES parse_convert(struct filter_info *tinfo, xmlNodePtr ptr,
350 struct convert_s **l)
353 for(; ptr; ptr = ptr->next)
355 if (ptr->type != XML_ELEMENT_NODE)
357 if (!XML_STRCMP(ptr->name, "xslt"))
359 struct _xmlAttr *attr;
360 struct convert_s *p = odr_malloc(tinfo->odr_config, sizeof(*p));
364 p->stylesheet_xsp = 0;
366 for (attr = ptr->properties; attr; attr = attr->next)
367 if (attr_content(attr, "stylesheet", &p->stylesheet))
370 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
372 tinfo->fname, attr->name);
375 char tmp_xslt_full_name[1024];
376 if (!yaz_filepath_resolve(p->stylesheet, tinfo->profile_path,
377 NULL, tmp_xslt_full_name))
380 "%s: dom filter: stylesheet %s not found in "
383 p->stylesheet, tinfo->profile_path);
388 = xsltParseStylesheetFile((const xmlChar*) tmp_xslt_full_name);
389 if (!p->stylesheet_xsp)
392 "%s: dom filter: could not parse xslt "
394 tinfo->fname, tmp_xslt_full_name);
401 "%s: dom filter: missing attribute 'stylesheet' "
402 "for element 'xslt'", tinfo->fname);
410 yaz_log(YLOG_LOG, "%s: dom filter: bad node '%s' for <conv>",
411 tinfo->fname, ptr->name);
419 static ZEBRA_RES perform_convert(struct filter_info *tinfo,
420 struct convert_s *convert,
423 xsltStylesheetPtr *last_xsp)
425 for (; convert; convert = convert->next)
427 xmlDocPtr res_doc = xsltApplyStylesheet(convert->stylesheet_xsp,
430 *last_xsp = convert->stylesheet_xsp;
437 static struct filter_input *new_input(struct filter_info *tinfo, int type)
439 struct filter_input *p;
440 struct filter_input **np = &tinfo->input_list;
441 for (;*np; np = &(*np)->next)
443 p = *np = odr_malloc(tinfo->odr_config, sizeof(*p));
452 static ZEBRA_RES parse_input(struct filter_info *tinfo, xmlNodePtr ptr,
456 for (; ptr; ptr = ptr->next)
458 if (ptr->type != XML_ELEMENT_NODE)
460 if (!XML_STRCMP(ptr->name, "marc"))
462 yaz_iconv_t iconv = 0;
463 const char *input_charset = "marc-8";
464 struct _xmlAttr *attr;
466 for (attr = ptr->properties; attr; attr = attr->next)
468 if (attr_content(attr, "charset", &input_charset))
471 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
473 tinfo->fname, attr->name);
475 iconv = yaz_iconv_open("utf-8", input_charset);
478 yaz_log(YLOG_WARN, "%s: dom filter: unsupported charset "
480 tinfo->fname, input_charset);
485 struct filter_input *p = new_input(tinfo, DOM_INPUT_MARC);
486 p->u.marc.handle = yaz_marc_create();
487 p->u.marc.iconv = iconv;
489 yaz_marc_iconv(p->u.marc.handle, p->u.marc.iconv);
493 parse_convert(tinfo, ptr, &p->convert);
498 else if (!XML_STRCMP(ptr->name, "xmlreader"))
500 struct filter_input *p = new_input(tinfo, DOM_INPUT_XMLREADER);
501 struct _xmlAttr *attr;
502 const char *level_str = 0;
504 p->u.xmlreader.split_level = 0;
505 p->u.xmlreader.reader = 0;
507 for (attr = ptr->properties; attr; attr = attr->next)
509 if (attr_content(attr, "level", &level_str))
512 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
514 tinfo->fname, attr->name);
517 p->u.xmlreader.split_level = atoi(level_str);
521 parse_convert(tinfo, ptr, &p->convert);
526 yaz_log(YLOG_WARN, "%s: dom filter: bad input type %s",
527 tinfo->fname, ptr->name);
534 static ZEBRA_RES parse_dom(struct filter_info *tinfo, const char *fname)
536 char tmp_full_name[1024];
540 tinfo->fname = odr_strdup(tinfo->odr_config, fname);
542 if (yaz_filepath_resolve(tinfo->fname, tinfo->profile_path,
543 NULL, tmp_full_name))
544 tinfo->full_name = odr_strdup(tinfo->odr_config, tmp_full_name);
546 tinfo->full_name = odr_strdup(tinfo->odr_config, tinfo->fname);
548 yaz_log(YLOG_LOG, "dom filter: loading config file %s", tinfo->full_name);
550 doc = xmlParseFile(tinfo->full_name);
553 yaz_log(YLOG_WARN, "%s: dom filter: failed to parse config file %s",
554 tinfo->fname, tinfo->full_name);
557 /* save because we store ptrs to the content */
558 tinfo->doc_config = doc;
560 ptr = xmlDocGetRootElement(doc);
561 if (!ptr || ptr->type != XML_ELEMENT_NODE
562 || XML_STRCMP(ptr->name, "dom"))
565 "%s: dom filter: expected root element <dom>",
570 for (ptr = ptr->children; ptr; ptr = ptr->next)
572 if (ptr->type != XML_ELEMENT_NODE)
574 if (!XML_STRCMP(ptr->name, "extract"))
577 <extract name="index">
578 <xslt stylesheet="first.xsl"/>
579 <xslt stylesheet="second.xsl"/>
582 struct _xmlAttr *attr;
583 struct filter_extract *f =
584 odr_malloc(tinfo->odr_config, sizeof(*f));
589 for (attr = ptr->properties; attr; attr = attr->next)
591 if (attr_content(attr, "name", &f->name))
594 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
596 tinfo->fname, attr->name);
599 parse_convert(tinfo, ptr->children, &f->convert);
601 else if (!XML_STRCMP(ptr->name, "retrieve"))
605 <xslt stylesheet="some.xsl"/>
606 <xslt stylesheet="some.xsl"/>
609 struct _xmlAttr *attr;
610 struct filter_retrieve **fp = &tinfo->retrieve_list;
611 struct filter_retrieve *f =
612 odr_malloc(tinfo->odr_config, sizeof(*f));
623 for (attr = ptr->properties; attr; attr = attr->next)
625 if (attr_content(attr, "identifier", &f->identifier))
627 else if (attr_content(attr, "name", &f->name))
630 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
632 tinfo->fname, attr->name);
634 parse_convert(tinfo, ptr->children, &f->convert);
636 else if (!XML_STRCMP(ptr->name, "store"))
640 <xslt stylesheet="some.xsl"/>
641 <xslt stylesheet="some.xsl"/>
644 struct filter_store *f =
645 odr_malloc(tinfo->odr_config, sizeof(*f));
649 parse_convert(tinfo, ptr->children, &f->convert);
651 else if (!XML_STRCMP(ptr->name, "input"))
655 <xmlreader level="1"/>
657 <input syntax="usmarc">
658 <marc inputcharset="marc-8"/>
661 struct _xmlAttr *attr;
662 const char *syntax = 0;
663 const char *name = 0;
664 for (attr = ptr->properties; attr; attr = attr->next)
666 if (attr_content(attr, "syntax", &syntax))
668 else if (attr_content(attr, "name", &name))
671 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
673 tinfo->fname, attr->name);
675 parse_input(tinfo, ptr->children, syntax, name);
679 yaz_log(YLOG_WARN, "%s: dom filter: bad element %s",
680 tinfo->fname, ptr->name);
687 static struct filter_retrieve *lookup_retrieve(struct filter_info *tinfo,
690 struct filter_retrieve *f = tinfo->retrieve_list;
692 /* return first schema if no est is provided */
695 for (; f; f = f->next)
697 /* find requested schema */
700 if (f->identifier && !strcmp(f->identifier, est))
702 if (f->name && !strcmp(f->name, est))
709 static ZEBRA_RES filter_config(void *clientData, Res res, const char *args)
711 struct filter_info *tinfo = clientData;
714 yaz_log(YLOG_WARN, "dom filter: need config file");
718 if (tinfo->fname && !strcmp(args, tinfo->fname))
721 tinfo->profile_path = res_get(res, "profilePath");
724 return parse_dom(tinfo, args);
727 static void filter_destroy(void *clientData)
729 struct filter_info *tinfo = clientData;
731 odr_destroy(tinfo->odr_config);
732 odr_destroy(tinfo->odr_record);
736 static int ioread_ex(void *context, char *buffer, int len)
738 struct recExtractCtrl *p = context;
739 return p->stream->readf(p->stream, buffer, len);
742 static int ioclose_ex(void *context)
747 static void index_cdata(struct filter_info *tinfo, struct recExtractCtrl *ctrl,
748 xmlNodePtr ptr, RecWord *recWord)
750 for(; ptr; ptr = ptr->next)
752 index_cdata(tinfo, ctrl, ptr->children, recWord);
753 if (ptr->type != XML_TEXT_NODE)
755 recWord->term_buf = (const char *)ptr->content;
756 recWord->term_len = XML_STRLEN(ptr->content);
757 (*ctrl->tokenAdd)(recWord);
761 #define ZEBRA_SCHEMA_XSLT_NS "http://indexdata.dk/zebra/xslt/1"
764 static const char *zebra_xslt_ns = ZEBRA_SCHEMA_XSLT_NS;
766 static void index_node(struct filter_info *tinfo, struct recExtractCtrl *ctrl,
767 xmlNodePtr ptr, RecWord *recWord)
769 for(; ptr; ptr = ptr->next)
771 index_node(tinfo, ctrl, ptr->children, recWord);
772 if (ptr->type != XML_ELEMENT_NODE || !ptr->ns ||
773 XML_STRCMP(ptr->ns->href, zebra_xslt_ns))
775 if (!XML_STRCMP(ptr->name, "index"))
777 const char *name_str = 0;
778 const char *type_str = 0;
779 const char *xpath_str = 0;
780 struct _xmlAttr *attr;
781 for (attr = ptr->properties; attr; attr = attr->next)
783 if (attr_content(attr, "name", &name_str))
785 else if (attr_content(attr, "xpath", &xpath_str))
787 else if (attr_content(attr, "type", &type_str))
790 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
792 tinfo->fname, attr->name);
796 int prev_type = recWord->index_type; /* save default type */
798 if (type_str && *type_str)
799 recWord->index_type = *type_str; /* type was given */
800 recWord->index_name = name_str;
801 index_cdata(tinfo, ctrl, ptr->children, recWord);
803 recWord->index_type = prev_type; /* restore it again */
809 static void index_record(struct filter_info *tinfo,struct recExtractCtrl *ctrl,
810 xmlNodePtr ptr, RecWord *recWord)
812 const char *type_str = "update";
814 if (ptr && ptr->type == XML_ELEMENT_NODE && ptr->ns &&
815 !XML_STRCMP(ptr->ns->href, zebra_xslt_ns)
816 && !XML_STRCMP(ptr->name, "record"))
818 const char *id_str = 0;
819 const char *rank_str = 0;
820 struct _xmlAttr *attr;
821 for (attr = ptr->properties; attr; attr = attr->next)
823 if (attr_content(attr, "type", &type_str))
825 else if (attr_content(attr, "id", &id_str))
827 else if (attr_content(attr, "rank", &rank_str))
830 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
832 tinfo->fname, attr->name);
835 sscanf(id_str, "%255s", ctrl->match_criteria);
838 ctrl->staticrank = atozint(rank_str);
842 if (!strcmp("update", type_str))
843 index_node(tinfo, ctrl, ptr, recWord);
844 else if (!strcmp("delete", type_str))
845 yaz_log(YLOG_WARN, "dom filter delete: to be implemented");
847 yaz_log(YLOG_WARN, "dom filter: unknown record type '%s'",
851 static int extract_doc(struct filter_info *tinfo, struct filter_input *input,
852 struct recExtractCtrl *p, xmlDocPtr doc)
855 const char *params[10];
858 xsltStylesheetPtr last_xsp = 0;
859 xmlDocPtr store_doc = 0;
862 set_param_str(params, "schema", zebra_xslt_ns, tinfo->odr_record);
864 /* input conversion */
865 perform_convert(tinfo, input->convert, params, &doc, 0);
867 (*p->init)(p, &recWord);
871 /* store conversion */
872 store_doc = xmlCopyDoc(doc, 1);
873 perform_convert(tinfo, tinfo->store->convert,
874 params, &store_doc, &last_xsp);
878 xsltSaveResultToString(&buf_out, &len_out,
879 store_doc ? store_doc : doc, last_xsp);
881 xmlDocDumpMemory(store_doc ? store_doc : doc, &buf_out, &len_out);
882 if (p->flagShowRecords)
883 fwrite(buf_out, len_out, 1, stdout);
884 (*p->setStoreData)(p, buf_out, len_out);
888 xmlFreeDoc(store_doc);
890 /* extract conversion */
891 perform_convert(tinfo, tinfo->extract->convert, params, &doc, 0);
895 if (p->flagShowRecords)
897 xmlDocDumpMemory(doc, &buf_out, &len_out);
898 fwrite(buf_out, len_out, 1, stdout);
901 root_ptr = xmlDocGetRootElement(doc);
903 index_record(tinfo, p, root_ptr, &recWord);
906 yaz_log(YLOG_WARN, "No root for index XML record");
910 return RECCTRL_EXTRACT_OK;
913 static int extract_xml_split(struct filter_info *tinfo,
914 struct filter_input *input,
915 struct recExtractCtrl *p)
921 if (input->u.xmlreader.reader)
922 xmlFreeTextReader(input->u.xmlreader.reader);
923 input->u.xmlreader.reader = xmlReaderForIO(ioread_ex, ioclose_ex,
930 if (!input->u.xmlreader.reader)
931 return RECCTRL_EXTRACT_ERROR_GENERIC;
933 ret = xmlTextReaderRead(input->u.xmlreader.reader);
936 int type = xmlTextReaderNodeType(input->u.xmlreader.reader);
937 int depth = xmlTextReaderDepth(input->u.xmlreader.reader);
938 if (type == XML_READER_TYPE_ELEMENT &&
939 input->u.xmlreader.split_level == depth)
941 xmlNodePtr ptr = xmlTextReaderExpand(input->u.xmlreader.reader);
944 xmlNodePtr ptr2 = xmlCopyNode(ptr, 1);
945 xmlDocPtr doc = xmlNewDoc((const xmlChar*) "1.0");
947 xmlDocSetRootElement(doc, ptr2);
949 return extract_doc(tinfo, input, p, doc);
953 xmlFreeTextReader(input->u.xmlreader.reader);
954 input->u.xmlreader.reader = 0;
955 return RECCTRL_EXTRACT_ERROR_GENERIC;
958 ret = xmlTextReaderRead(input->u.xmlreader.reader);
960 xmlFreeTextReader(input->u.xmlreader.reader);
961 input->u.xmlreader.reader = 0;
962 return RECCTRL_EXTRACT_EOF;
965 static int extract_xml_full(struct filter_info *tinfo,
966 struct filter_input *input,
967 struct recExtractCtrl *p)
969 if (p->first_record) /* only one record per stream */
971 xmlDocPtr doc = xmlReadIO(ioread_ex, ioclose_ex, p /* I/O handler */,
974 XML_PARSE_XINCLUDE|XML_PARSE_NOENT);
977 return RECCTRL_EXTRACT_ERROR_GENERIC;
979 return extract_doc(tinfo, input, p, doc);
982 return RECCTRL_EXTRACT_EOF;
985 static int extract_iso2709(struct filter_info *tinfo,
986 struct filter_input *input,
987 struct recExtractCtrl *p)
993 if (p->stream->readf(p->stream, buf, 5) != 5)
994 return RECCTRL_EXTRACT_EOF;
995 while (*buf < '0' || *buf > '9')
999 yaz_log(YLOG_WARN, "MARC: Skipping bad byte %d (0x%02X)",
1000 *buf & 0xff, *buf & 0xff);
1001 for (i = 0; i<4; i++)
1004 if (p->stream->readf(p->stream, buf+4, 1) != 1)
1005 return RECCTRL_EXTRACT_EOF;
1007 record_length = atoi_n (buf, 5);
1008 if (record_length < 25)
1010 yaz_log (YLOG_WARN, "MARC record length < 25, is %d", record_length);
1011 return RECCTRL_EXTRACT_ERROR_GENERIC;
1013 read_bytes = p->stream->readf(p->stream, buf+5, record_length-5);
1014 if (read_bytes < record_length-5)
1016 yaz_log (YLOG_WARN, "Couldn't read whole MARC record");
1017 return RECCTRL_EXTRACT_ERROR_GENERIC;
1019 r = yaz_marc_read_iso2709(input->u.marc.handle, buf, record_length);
1020 if (r < record_length)
1022 yaz_log (YLOG_WARN, "Parsing of MARC record failed r=%d length=%d",
1024 return RECCTRL_EXTRACT_ERROR_GENERIC;
1030 yaz_marc_write_xml(input->u.marc.handle, &root_ptr, 0, 0, 0);
1031 rdoc = xmlNewDoc((const xmlChar*) "1.0");
1032 xmlDocSetRootElement(rdoc, root_ptr);
1033 return extract_doc(tinfo, input, p, rdoc);
1035 return RECCTRL_EXTRACT_OK;
1038 static int filter_extract(void *clientData, struct recExtractCtrl *p)
1040 struct filter_info *tinfo = clientData;
1041 struct filter_input *input = tinfo->input_list;
1044 return RECCTRL_EXTRACT_ERROR_GENERIC;
1046 odr_reset(tinfo->odr_record);
1049 case DOM_INPUT_XMLREADER:
1050 if (input->u.xmlreader.split_level == 0)
1051 return extract_xml_full(tinfo, input, p);
1053 return extract_xml_split(tinfo, input, p);
1055 case DOM_INPUT_MARC:
1056 return extract_iso2709(tinfo, input, p);
1058 return RECCTRL_EXTRACT_ERROR_GENERIC;
1061 static int ioread_ret(void *context, char *buffer, int len)
1063 struct recRetrieveCtrl *p = context;
1064 return p->stream->readf(p->stream, buffer, len);
1067 static int ioclose_ret(void *context)
1072 static int filter_retrieve (void *clientData, struct recRetrieveCtrl *p)
1074 /* const char *esn = zebra_xslt_ns; */
1075 const char *esn = 0;
1076 const char *params[32];
1077 struct filter_info *tinfo = clientData;
1079 struct filter_retrieve *retrieve;
1080 xsltStylesheetPtr last_xsp = 0;
1084 if (p->comp->which == Z_RecordComp_simple
1085 && p->comp->u.simple->which == Z_ElementSetNames_generic)
1087 esn = p->comp->u.simple->u.generic;
1089 else if (p->comp->which == Z_RecordComp_complex
1090 && p->comp->u.complex->generic->elementSpec
1091 && p->comp->u.complex->generic->elementSpec->which ==
1092 Z_ElementSpec_elementSetName)
1094 esn = p->comp->u.complex->generic->elementSpec->u.elementSetName;
1097 retrieve = lookup_retrieve(tinfo, esn);
1101 YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
1106 set_param_int(params, "id", p->localno, p->odr);
1108 set_param_str(params, "filename", p->fname, p->odr);
1109 if (p->staticrank >= 0)
1110 set_param_int(params, "rank", p->staticrank, p->odr);
1113 set_param_str(params, "schema", esn, p->odr);
1116 set_param_str(params, "schema", retrieve->name, p->odr);
1117 else if (retrieve->identifier)
1118 set_param_str(params, "schema", retrieve->identifier, p->odr);
1120 set_param_str(params, "schema", "", p->odr);
1123 set_param_int(params, "score", p->score, p->odr);
1124 set_param_int(params, "size", p->recordSize, p->odr);
1126 doc = xmlReadIO(ioread_ret, ioclose_ret, p /* I/O handler */,
1129 XML_PARSE_XINCLUDE|XML_PARSE_NOENT);
1132 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1136 /* retrieve conversion */
1137 perform_convert(tinfo, retrieve->convert, params, &doc, &last_xsp);
1140 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1142 else if (p->input_format == VAL_NONE || p->input_format == VAL_TEXT_XML)
1148 xsltSaveResultToString(&buf_out, &len_out, doc, last_xsp);
1150 xmlDocDumpMemory(doc, &buf_out, &len_out);
1152 p->output_format = VAL_TEXT_XML;
1153 p->rec_len = len_out;
1154 p->rec_buf = odr_malloc(p->odr, p->rec_len);
1155 memcpy(p->rec_buf, buf_out, p->rec_len);
1158 else if (p->output_format == VAL_SUTRS)
1164 xsltSaveResultToString(&buf_out, &len_out, doc, last_xsp);
1166 xmlDocDumpMemory(doc, &buf_out, &len_out);
1168 p->output_format = VAL_SUTRS;
1169 p->rec_len = len_out;
1170 p->rec_buf = odr_malloc(p->odr, p->rec_len);
1171 memcpy(p->rec_buf, buf_out, p->rec_len);
1177 p->diagnostic = YAZ_BIB1_RECORD_SYNTAX_UNSUPP;
1183 static struct recType filter_type = {
1194 #ifdef IDZEBRA_STATIC_DOM
1207 * indent-tabs-mode: nil
1209 * vim: shiftwidth=4 tabstop=8 expandtab