1 /* $Id: mod_dom.c,v 1.2 2007-02-12 10:33:51 adam 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)
104 static void set_param_str(const char **params, const char *name,
105 const char *value, ODR odr)
107 char *quoted = odr_malloc(odr, 3 + strlen(value));
108 sprintf(quoted, "'%s'", value);
116 static void set_param_int(const char **params, const char *name,
119 char *quoted = odr_malloc(odr, 30); /* 25 digits enough for 2^64 */
122 sprintf(quoted, "'" ZINT_FORMAT "'", value);
128 static void *filter_init(Res res, RecType recType)
130 struct filter_info *tinfo = (struct filter_info *) xmalloc(sizeof(*tinfo));
132 tinfo->full_name = 0;
133 tinfo->profile_path = 0;
134 tinfo->odr_record = odr_createmem(ODR_ENCODE);
135 tinfo->odr_config = odr_createmem(ODR_ENCODE);
137 tinfo->retrieve_list = 0;
138 tinfo->input_list = 0;
140 tinfo->doc_config = 0;
149 static int attr_content(struct _xmlAttr *attr, const char *name,
150 const char **dst_content)
152 if (!XML_STRCMP(attr->name, name) && attr->children
153 && attr->children->type == XML_TEXT_NODE)
155 *dst_content = (const char *)(attr->children->content);
161 static void destroy_xsp(struct convert_s *c)
165 if (c->stylesheet_xsp)
166 xsltFreeStylesheet(c->stylesheet_xsp);
171 static void destroy_dom(struct filter_info *tinfo)
175 destroy_xsp(tinfo->extract->convert);
180 destroy_xsp(tinfo->store->convert);
183 if (tinfo->input_list)
185 struct filter_input *i_ptr;
186 for (i_ptr = tinfo->input_list; i_ptr; i_ptr = i_ptr->next)
190 case DOM_INPUT_XMLREADER:
191 if (i_ptr->u.xmlreader.reader)
192 xmlFreeTextReader(i_ptr->u.xmlreader.reader);
195 yaz_iconv_close(i_ptr->u.marc.iconv);
196 yaz_marc_destroy(i_ptr->u.marc.handle);
199 destroy_xsp(i_ptr->convert);
201 tinfo->input_list = 0;
203 if (tinfo->retrieve_list)
205 struct filter_retrieve *r_ptr;
206 for (r_ptr = tinfo->retrieve_list; r_ptr; r_ptr = r_ptr->next)
207 destroy_xsp(r_ptr->convert);
208 tinfo->retrieve_list = 0;
211 if (tinfo->doc_config)
213 xmlFreeDoc(tinfo->doc_config);
214 tinfo->doc_config = 0;
216 odr_reset(tinfo->odr_config);
219 static ZEBRA_RES parse_convert(struct filter_info *tinfo, xmlNodePtr ptr,
220 struct convert_s **l)
223 for(; ptr; ptr = ptr->next)
225 if (ptr->type != XML_ELEMENT_NODE)
227 if (!XML_STRCMP(ptr->name, "xslt"))
229 struct _xmlAttr *attr;
230 struct convert_s *p = odr_malloc(tinfo->odr_config, sizeof(*p));
234 p->stylesheet_xsp = 0;
236 for (attr = ptr->properties; attr; attr = attr->next)
237 if (attr_content(attr, "stylesheet", &p->stylesheet))
240 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
242 tinfo->fname, attr->name);
245 char tmp_xslt_full_name[1024];
246 if (!yaz_filepath_resolve(p->stylesheet, tinfo->profile_path,
247 NULL, tmp_xslt_full_name))
250 "%s: dom filter: stylesheet %s not found in "
253 p->stylesheet, tinfo->profile_path);
258 = xsltParseStylesheetFile((const xmlChar*) tmp_xslt_full_name);
259 if (!p->stylesheet_xsp)
262 "%s: dom filter: could not parse xslt "
264 tinfo->fname, tmp_xslt_full_name);
271 "%s: dom filter: missing attribute 'stylesheet' "
272 "for element 'xslt'", tinfo->fname);
280 yaz_log(YLOG_LOG, "%s: dom filter: bad node '%s' for <conv>",
281 tinfo->fname, ptr->name);
289 static ZEBRA_RES perform_convert(struct filter_info *tinfo,
290 struct convert_s *convert,
293 xsltStylesheetPtr *last_xsp)
295 for (; convert; convert = convert->next)
297 xmlDocPtr res_doc = xsltApplyStylesheet(convert->stylesheet_xsp,
300 *last_xsp = convert->stylesheet_xsp;
307 static struct filter_input *new_input(struct filter_info *tinfo, int type)
309 struct filter_input *p;
310 struct filter_input **np = &tinfo->input_list;
311 for (;*np; np = &(*np)->next)
313 p = *np = odr_malloc(tinfo->odr_config, sizeof(*p));
322 static ZEBRA_RES parse_input(struct filter_info *tinfo, xmlNodePtr ptr,
326 for (; ptr; ptr = ptr->next)
328 if (ptr->type != XML_ELEMENT_NODE)
330 if (!XML_STRCMP(ptr->name, "marc"))
332 yaz_iconv_t iconv = 0;
333 const char *input_charset = "marc-8";
334 struct _xmlAttr *attr;
336 for (attr = ptr->properties; attr; attr = attr->next)
338 if (attr_content(attr, "charset", &input_charset))
341 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
343 tinfo->fname, attr->name);
345 iconv = yaz_iconv_open("utf-8", input_charset);
348 yaz_log(YLOG_WARN, "%s: dom filter: unsupported charset "
350 tinfo->fname, input_charset);
355 struct filter_input *p = new_input(tinfo, DOM_INPUT_MARC);
356 p->u.marc.handle = yaz_marc_create();
357 p->u.marc.iconv = iconv;
359 yaz_marc_iconv(p->u.marc.handle, p->u.marc.iconv);
363 parse_convert(tinfo, ptr, &p->convert);
368 else if (!XML_STRCMP(ptr->name, "xmlreader"))
370 struct filter_input *p = new_input(tinfo, DOM_INPUT_XMLREADER);
371 struct _xmlAttr *attr;
372 const char *level_str = 0;
374 p->u.xmlreader.split_level = 0;
375 p->u.xmlreader.reader = 0;
377 for (attr = ptr->properties; attr; attr = attr->next)
379 if (attr_content(attr, "level", &level_str))
382 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
384 tinfo->fname, attr->name);
387 p->u.xmlreader.split_level = atoi(level_str);
391 parse_convert(tinfo, ptr, &p->convert);
396 yaz_log(YLOG_WARN, "%s: dom filter: bad input type %s",
397 tinfo->fname, ptr->name);
404 static ZEBRA_RES parse_dom(struct filter_info *tinfo, const char *fname)
406 char tmp_full_name[1024];
410 tinfo->fname = odr_strdup(tinfo->odr_config, fname);
412 if (yaz_filepath_resolve(tinfo->fname, tinfo->profile_path,
413 NULL, tmp_full_name))
414 tinfo->full_name = odr_strdup(tinfo->odr_config, tmp_full_name);
416 tinfo->full_name = odr_strdup(tinfo->odr_config, tinfo->fname);
418 yaz_log(YLOG_LOG, "dom filter: loading config file %s", tinfo->full_name);
420 doc = xmlParseFile(tinfo->full_name);
423 yaz_log(YLOG_WARN, "%s: dom filter: failed to parse config file %s",
424 tinfo->fname, tinfo->full_name);
427 /* save because we store ptrs to the content */
428 tinfo->doc_config = doc;
430 ptr = xmlDocGetRootElement(doc);
431 if (!ptr || ptr->type != XML_ELEMENT_NODE
432 || XML_STRCMP(ptr->name, "dom"))
435 "%s: dom filter: expected root element <dom>",
440 for (ptr = ptr->children; ptr; ptr = ptr->next)
442 if (ptr->type != XML_ELEMENT_NODE)
444 if (!XML_STRCMP(ptr->name, "extract"))
447 <extract name="index">
448 <xslt stylesheet="first.xsl"/>
449 <xslt stylesheet="second.xsl"/>
452 struct _xmlAttr *attr;
453 struct filter_extract *f =
454 odr_malloc(tinfo->odr_config, sizeof(*f));
459 for (attr = ptr->properties; attr; attr = attr->next)
461 if (attr_content(attr, "name", &f->name))
464 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
466 tinfo->fname, attr->name);
469 parse_convert(tinfo, ptr->children, &f->convert);
471 else if (!XML_STRCMP(ptr->name, "retrieve"))
475 <xslt stylesheet="some.xsl"/>
476 <xslt stylesheet="some.xsl"/>
479 struct _xmlAttr *attr;
480 struct filter_retrieve **fp = &tinfo->retrieve_list;
481 struct filter_retrieve *f =
482 odr_malloc(tinfo->odr_config, sizeof(*f));
493 for (attr = ptr->properties; attr; attr = attr->next)
495 if (attr_content(attr, "identifier", &f->identifier))
497 else if (attr_content(attr, "name", &f->name))
500 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
502 tinfo->fname, attr->name);
504 parse_convert(tinfo, ptr->children, &f->convert);
506 else if (!XML_STRCMP(ptr->name, "store"))
510 <xslt stylesheet="some.xsl"/>
511 <xslt stylesheet="some.xsl"/>
514 struct filter_store *f =
515 odr_malloc(tinfo->odr_config, sizeof(*f));
519 parse_convert(tinfo, ptr->children, &f->convert);
521 else if (!XML_STRCMP(ptr->name, "input"))
525 <xmlreader level="1"/>
527 <input syntax="usmarc">
528 <marc inputcharset="marc-8"/>
531 struct _xmlAttr *attr;
532 const char *syntax = 0;
533 const char *name = 0;
534 for (attr = ptr->properties; attr; attr = attr->next)
536 if (attr_content(attr, "syntax", &syntax))
538 else if (attr_content(attr, "name", &name))
541 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
543 tinfo->fname, attr->name);
545 parse_input(tinfo, ptr->children, syntax, name);
549 yaz_log(YLOG_WARN, "%s: dom filter: bad element %s",
550 tinfo->fname, ptr->name);
557 static struct filter_retrieve *lookup_retrieve(struct filter_info *tinfo,
560 struct filter_retrieve *f = tinfo->retrieve_list;
562 /* return first schema if no est is provided */
565 for (; f; f = f->next)
567 /* find requested schema */
570 if (f->identifier && !strcmp(f->identifier, est))
572 if (f->name && !strcmp(f->name, est))
579 static ZEBRA_RES filter_config(void *clientData, Res res, const char *args)
581 struct filter_info *tinfo = clientData;
584 yaz_log(YLOG_WARN, "dom filter: need config file");
588 if (tinfo->fname && !strcmp(args, tinfo->fname))
591 tinfo->profile_path = res_get(res, "profilePath");
594 return parse_dom(tinfo, args);
597 static void filter_destroy(void *clientData)
599 struct filter_info *tinfo = clientData;
601 odr_destroy(tinfo->odr_config);
602 odr_destroy(tinfo->odr_record);
606 static int ioread_ex(void *context, char *buffer, int len)
608 struct recExtractCtrl *p = context;
609 return p->stream->readf(p->stream, buffer, len);
612 static int ioclose_ex(void *context)
617 static void index_cdata(struct filter_info *tinfo, struct recExtractCtrl *ctrl,
618 xmlNodePtr ptr, RecWord *recWord)
620 for(; ptr; ptr = ptr->next)
622 index_cdata(tinfo, ctrl, ptr->children, recWord);
623 if (ptr->type != XML_TEXT_NODE)
625 recWord->term_buf = (const char *)ptr->content;
626 recWord->term_len = XML_STRLEN(ptr->content);
627 (*ctrl->tokenAdd)(recWord);
631 #define ZEBRA_SCHEMA_XSLT_NS "http://indexdata.dk/zebra/xslt/1"
634 static const char *zebra_xslt_ns = ZEBRA_SCHEMA_XSLT_NS;
636 static void index_node(struct filter_info *tinfo, struct recExtractCtrl *ctrl,
637 xmlNodePtr ptr, RecWord *recWord)
639 for(; ptr; ptr = ptr->next)
641 index_node(tinfo, ctrl, ptr->children, recWord);
642 if (ptr->type != XML_ELEMENT_NODE || !ptr->ns ||
643 XML_STRCMP(ptr->ns->href, zebra_xslt_ns))
645 if (!XML_STRCMP(ptr->name, "index"))
647 const char *name_str = 0;
648 const char *type_str = 0;
649 const char *xpath_str = 0;
650 struct _xmlAttr *attr;
651 for (attr = ptr->properties; attr; attr = attr->next)
653 if (attr_content(attr, "name", &name_str))
655 else if (attr_content(attr, "xpath", &xpath_str))
657 else if (attr_content(attr, "type", &type_str))
660 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
662 tinfo->fname, attr->name);
666 int prev_type = recWord->index_type; /* save default type */
668 if (type_str && *type_str)
669 recWord->index_type = *type_str; /* type was given */
670 recWord->index_name = name_str;
671 index_cdata(tinfo, ctrl, ptr->children, recWord);
673 recWord->index_type = prev_type; /* restore it again */
679 static void index_record(struct filter_info *tinfo,struct recExtractCtrl *ctrl,
680 xmlNodePtr ptr, RecWord *recWord)
682 const char *type_str = "update";
684 if (ptr && ptr->type == XML_ELEMENT_NODE && ptr->ns &&
685 !XML_STRCMP(ptr->ns->href, zebra_xslt_ns)
686 && !XML_STRCMP(ptr->name, "record"))
688 const char *id_str = 0;
689 const char *rank_str = 0;
690 struct _xmlAttr *attr;
691 for (attr = ptr->properties; attr; attr = attr->next)
693 if (attr_content(attr, "type", &type_str))
695 else if (attr_content(attr, "id", &id_str))
697 else if (attr_content(attr, "rank", &rank_str))
700 yaz_log(YLOG_WARN, "%s: dom filter: bad attribute %s"
702 tinfo->fname, attr->name);
705 sscanf(id_str, "%255s", ctrl->match_criteria);
708 ctrl->staticrank = atozint(rank_str);
712 if (!strcmp("update", type_str))
713 index_node(tinfo, ctrl, ptr, recWord);
714 else if (!strcmp("delete", type_str))
715 yaz_log(YLOG_WARN, "dom filter delete: to be implemented");
717 yaz_log(YLOG_WARN, "dom filter: unknown record type '%s'",
721 static int extract_doc(struct filter_info *tinfo, struct filter_input *input,
722 struct recExtractCtrl *p, xmlDocPtr doc)
725 const char *params[10];
728 xsltStylesheetPtr last_xsp = 0;
729 xmlDocPtr store_doc = 0;
732 set_param_str(params, "schema", zebra_xslt_ns, tinfo->odr_record);
734 /* input conversion */
735 perform_convert(tinfo, input->convert, params, &doc, 0);
737 (*p->init)(p, &recWord);
741 /* store conversion */
742 store_doc = xmlCopyDoc(doc, 1);
743 perform_convert(tinfo, tinfo->store->convert,
744 params, &store_doc, &last_xsp);
748 xsltSaveResultToString(&buf_out, &len_out,
749 store_doc ? store_doc : doc, last_xsp);
751 xmlDocDumpMemory(store_doc ? store_doc : doc, &buf_out, &len_out);
752 if (p->flagShowRecords)
753 fwrite(buf_out, len_out, 1, stdout);
754 (*p->setStoreData)(p, buf_out, len_out);
758 xmlFreeDoc(store_doc);
760 /* extract conversion */
761 perform_convert(tinfo, tinfo->extract->convert, params, &doc, 0);
765 if (p->flagShowRecords)
767 xmlDocDumpMemory(doc, &buf_out, &len_out);
768 fwrite(buf_out, len_out, 1, stdout);
771 root_ptr = xmlDocGetRootElement(doc);
773 index_record(tinfo, p, root_ptr, &recWord);
776 yaz_log(YLOG_WARN, "No root for index XML record");
780 return RECCTRL_EXTRACT_OK;
783 static int extract_xml_split(struct filter_info *tinfo,
784 struct filter_input *input,
785 struct recExtractCtrl *p)
791 if (input->u.xmlreader.reader)
792 xmlFreeTextReader(input->u.xmlreader.reader);
793 input->u.xmlreader.reader = xmlReaderForIO(ioread_ex, ioclose_ex,
800 if (!input->u.xmlreader.reader)
801 return RECCTRL_EXTRACT_ERROR_GENERIC;
803 ret = xmlTextReaderRead(input->u.xmlreader.reader);
806 int type = xmlTextReaderNodeType(input->u.xmlreader.reader);
807 int depth = xmlTextReaderDepth(input->u.xmlreader.reader);
808 if (type == XML_READER_TYPE_ELEMENT &&
809 input->u.xmlreader.split_level == depth)
811 xmlNodePtr ptr = xmlTextReaderExpand(input->u.xmlreader.reader);
814 xmlNodePtr ptr2 = xmlCopyNode(ptr, 1);
815 xmlDocPtr doc = xmlNewDoc((const xmlChar*) "1.0");
817 xmlDocSetRootElement(doc, ptr2);
819 return extract_doc(tinfo, input, p, doc);
823 xmlFreeTextReader(input->u.xmlreader.reader);
824 input->u.xmlreader.reader = 0;
825 return RECCTRL_EXTRACT_ERROR_GENERIC;
828 ret = xmlTextReaderRead(input->u.xmlreader.reader);
830 xmlFreeTextReader(input->u.xmlreader.reader);
831 input->u.xmlreader.reader = 0;
832 return RECCTRL_EXTRACT_EOF;
835 static int extract_xml_full(struct filter_info *tinfo,
836 struct filter_input *input,
837 struct recExtractCtrl *p)
839 if (p->first_record) /* only one record per stream */
841 xmlDocPtr doc = xmlReadIO(ioread_ex, ioclose_ex, p /* I/O handler */,
844 XML_PARSE_XINCLUDE|XML_PARSE_NOENT);
847 return RECCTRL_EXTRACT_ERROR_GENERIC;
849 return extract_doc(tinfo, input, p, doc);
852 return RECCTRL_EXTRACT_EOF;
855 static int extract_iso2709(struct filter_info *tinfo,
856 struct filter_input *input,
857 struct recExtractCtrl *p)
863 if (p->stream->readf(p->stream, buf, 5) != 5)
864 return RECCTRL_EXTRACT_EOF;
865 while (*buf < '0' || *buf > '9')
869 yaz_log(YLOG_WARN, "MARC: Skipping bad byte %d (0x%02X)",
870 *buf & 0xff, *buf & 0xff);
871 for (i = 0; i<4; i++)
874 if (p->stream->readf(p->stream, buf+4, 1) != 1)
875 return RECCTRL_EXTRACT_EOF;
877 record_length = atoi_n (buf, 5);
878 if (record_length < 25)
880 yaz_log (YLOG_WARN, "MARC record length < 25, is %d", record_length);
881 return RECCTRL_EXTRACT_ERROR_GENERIC;
883 read_bytes = p->stream->readf(p->stream, buf+5, record_length-5);
884 if (read_bytes < record_length-5)
886 yaz_log (YLOG_WARN, "Couldn't read whole MARC record");
887 return RECCTRL_EXTRACT_ERROR_GENERIC;
889 r = yaz_marc_read_iso2709(input->u.marc.handle, buf, record_length);
890 if (r < record_length)
892 yaz_log (YLOG_WARN, "Parsing of MARC record failed r=%d length=%d",
894 return RECCTRL_EXTRACT_ERROR_GENERIC;
900 yaz_marc_write_xml(input->u.marc.handle, &root_ptr, 0, 0, 0);
901 rdoc = xmlNewDoc((const xmlChar*) "1.0");
902 xmlDocSetRootElement(rdoc, root_ptr);
903 return extract_doc(tinfo, input, p, rdoc);
905 return RECCTRL_EXTRACT_OK;
908 static int filter_extract(void *clientData, struct recExtractCtrl *p)
910 struct filter_info *tinfo = clientData;
911 struct filter_input *input = tinfo->input_list;
914 return RECCTRL_EXTRACT_ERROR_GENERIC;
916 odr_reset(tinfo->odr_record);
919 case DOM_INPUT_XMLREADER:
920 if (input->u.xmlreader.split_level == 0)
921 return extract_xml_full(tinfo, input, p);
923 return extract_xml_split(tinfo, input, p);
926 return extract_iso2709(tinfo, input, p);
928 return RECCTRL_EXTRACT_ERROR_GENERIC;
931 static int ioread_ret(void *context, char *buffer, int len)
933 struct recRetrieveCtrl *p = context;
934 return p->stream->readf(p->stream, buffer, len);
937 static int ioclose_ret(void *context)
942 static int filter_retrieve (void *clientData, struct recRetrieveCtrl *p)
944 /* const char *esn = zebra_xslt_ns; */
946 const char *params[32];
947 struct filter_info *tinfo = clientData;
949 struct filter_retrieve *retrieve;
950 xsltStylesheetPtr last_xsp = 0;
954 if (p->comp->which == Z_RecordComp_simple
955 && p->comp->u.simple->which == Z_ElementSetNames_generic)
957 esn = p->comp->u.simple->u.generic;
959 else if (p->comp->which == Z_RecordComp_complex
960 && p->comp->u.complex->generic->elementSpec
961 && p->comp->u.complex->generic->elementSpec->which ==
962 Z_ElementSpec_elementSetName)
964 esn = p->comp->u.complex->generic->elementSpec->u.elementSetName;
967 retrieve = lookup_retrieve(tinfo, esn);
971 YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
976 set_param_int(params, "id", p->localno, p->odr);
978 set_param_str(params, "filename", p->fname, p->odr);
979 if (p->staticrank >= 0)
980 set_param_int(params, "rank", p->staticrank, p->odr);
983 set_param_str(params, "schema", esn, p->odr);
986 set_param_str(params, "schema", retrieve->name, p->odr);
987 else if (retrieve->identifier)
988 set_param_str(params, "schema", retrieve->identifier, p->odr);
990 set_param_str(params, "schema", "", p->odr);
993 set_param_int(params, "score", p->score, p->odr);
994 set_param_int(params, "size", p->recordSize, p->odr);
996 doc = xmlReadIO(ioread_ret, ioclose_ret, p /* I/O handler */,
999 XML_PARSE_XINCLUDE|XML_PARSE_NOENT);
1002 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1006 /* retrieve conversion */
1007 perform_convert(tinfo, retrieve->convert, params, &doc, &last_xsp);
1010 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1012 else if (p->input_format == VAL_NONE || p->input_format == VAL_TEXT_XML)
1018 xsltSaveResultToString(&buf_out, &len_out, doc, last_xsp);
1020 xmlDocDumpMemory(doc, &buf_out, &len_out);
1022 p->output_format = VAL_TEXT_XML;
1023 p->rec_len = len_out;
1024 p->rec_buf = odr_malloc(p->odr, p->rec_len);
1025 memcpy(p->rec_buf, buf_out, p->rec_len);
1028 else if (p->output_format == VAL_SUTRS)
1034 xsltSaveResultToString(&buf_out, &len_out, doc, last_xsp);
1036 xmlDocDumpMemory(doc, &buf_out, &len_out);
1038 p->output_format = VAL_SUTRS;
1039 p->rec_len = len_out;
1040 p->rec_buf = odr_malloc(p->odr, p->rec_len);
1041 memcpy(p->rec_buf, buf_out, p->rec_len);
1047 p->diagnostic = YAZ_BIB1_RECORD_SYNTAX_UNSUPP;
1053 static struct recType filter_type = {
1064 #ifdef IDZEBRA_STATIC_DOM
1077 * indent-tabs-mode: nil
1079 * vim: shiftwidth=4 tabstop=8 expandtab