1 /* $Id: recgrs.c,v 1.18 2007-04-16 21:54:37 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
25 #include <sys/types.h>
29 #include <yaz/oid_db.h>
30 #include <yaz/diagbib1.h>
33 #include <idzebra/recgrs.h>
35 #define GRS_MAX_WORD 512
37 struct source_parser {
45 static int sp_lex(struct source_parser *sp)
47 while (*sp->src == ' ')
51 while (*sp->src && !strchr("<>();,-: ", *sp->src))
60 sp->lookahead = *sp->src;
67 static int sp_expr(struct source_parser *sp, data1_node *n, RecWord *wrd);
69 static int sp_range(struct source_parser *sp, data1_node *n, RecWord *wrd)
76 if (sp->lookahead != '(')
78 sp_lex(sp); /* skip ( */
81 if (!sp_expr(sp, n, wrd))
84 if (sp->lookahead != ',')
86 sp_lex(sp); /* skip , */
89 if (!sp_expr(sp, n, &tmp_w))
91 start = atoi_n(tmp_w.term_buf, tmp_w.term_len);
93 if (sp->lookahead == ',')
95 sp_lex(sp); /* skip , */
98 if (!sp_expr(sp, n, &tmp_w))
100 len = atoi_n(tmp_w.term_buf, tmp_w.term_len);
106 if (sp->lookahead != ')')
110 if (wrd->term_buf && wrd->term_len)
112 wrd->term_buf += start;
113 wrd->term_len -= start;
114 if (wrd->term_len > len)
120 static int sp_first(struct source_parser *sp, data1_node *n, RecWord *wrd)
125 if (sp->lookahead != '(')
127 sp_lex(sp); /* skip ( */
128 if (!sp_expr(sp, n, wrd))
130 while (sp->lookahead == ',')
134 sp_lex(sp); /* skip , */
136 if (!sp_expr(sp, n, &search_w))
138 for (i = 0; i<wrd->term_len; i++)
141 for (j = 0; j<search_w.term_len && i+j < wrd->term_len; j++)
142 if (wrd->term_buf[i+j] != search_w.term_buf[j])
144 if (j == search_w.term_len) /* match ? */
146 if (min_pos == -1 || i < min_pos)
152 if (sp->lookahead != ')')
156 min_pos = 0; /* the default if not found */
157 sprintf(num_str, "%d", min_pos);
158 wrd->term_buf = nmem_strdup(sp->nmem, num_str);
159 wrd->term_len = strlen(wrd->term_buf);
163 static int sp_expr(struct source_parser *sp, data1_node *n, RecWord *wrd)
165 if (sp->lookahead != 't')
167 if (sp->len == 4 && !memcmp(sp->tok, "data", sp->len))
169 if (n->which == DATA1N_data)
171 wrd->term_buf = n->u.data.data;
172 wrd->term_len = n->u.data.len;
176 else if (sp->len == 3 && !memcmp(sp->tok, "tag", sp->len))
178 if (n->which == DATA1N_tag)
180 wrd->term_buf = n->u.tag.tag;
181 wrd->term_len = strlen(n->u.tag.tag);
185 else if (sp->len == 4 && !memcmp(sp->tok, "attr", sp->len))
189 if (sp->lookahead != '(')
193 if (!sp_expr(sp, n, &tmp_w))
198 if (n->which == DATA1N_tag)
200 data1_xattr *p = n->u.tag.attributes;
201 while (p && strlen(p->name) != tmp_w.term_len &&
202 memcmp (p->name, tmp_w.term_buf, tmp_w.term_len))
206 wrd->term_buf = p->value;
207 wrd->term_len = strlen(p->value);
210 if (sp->lookahead != ')')
214 else if (sp->len == 5 && !memcmp(sp->tok, "first", sp->len))
216 return sp_first(sp, n, wrd);
218 else if (sp->len == 5 && !memcmp(sp->tok, "range", sp->len))
220 return sp_range(sp, n, wrd);
222 else if (sp->len > 0 && isdigit(*(unsigned char *)sp->tok))
225 wrd->term_len = sp->len;
226 b = nmem_malloc(sp->nmem, sp->len);
227 memcpy(b, sp->tok, sp->len);
231 else if (sp->len > 2 && sp->tok[0] == '\'' && sp->tok[sp->len-1] == '\'')
234 wrd->term_len = sp->len - 2;
235 b = nmem_malloc(sp->nmem, wrd->term_len);
236 memcpy(b, sp->tok+1, wrd->term_len);
249 static struct source_parser *source_parser_create(void)
251 struct source_parser *sp = xmalloc(sizeof(*sp));
253 sp->nmem = nmem_create();
257 static void source_parser_destroy(struct source_parser *sp)
261 nmem_destroy(sp->nmem);
265 static int sp_parse(struct source_parser *sp,
266 data1_node *n, RecWord *wrd, const char *src)
272 nmem_reset(sp->nmem);
275 return sp_expr(sp, n, wrd);
278 int d1_check_xpath_predicate(data1_node *n, struct xpath_predicate *p)
287 if (p->which == XPATH_PREDICATE_RELATION) {
288 if (p->u.relation.name[0]) {
289 if (*p->u.relation.name != '@') {
291 " Only attributes (@) are supported in xelm xpath predicates");
292 yaz_log(YLOG_WARN, "predicate %s ignored", p->u.relation.name);
295 attname = p->u.relation.name + 1;
297 /* looking for the attribute with a specified name */
298 for (attr = n->u.tag.attributes; attr; attr = attr->next) {
299 if (!strcmp(attr->name, attname)) {
300 if (p->u.relation.op[0]) {
301 if (*p->u.relation.op != '=') {
303 "Only '=' relation is supported (%s)",p->u.relation.op);
304 yaz_log(YLOG_WARN, "predicate %s ignored", p->u.relation.name);
307 if (!strcmp(attr->value, p->u.relation.value)) {
312 /* attribute exists, no value specified */
322 else if (p->which == XPATH_PREDICATE_BOOLEAN) {
323 if (!strcmp(p->u.boolean.op,"and")) {
324 return d1_check_xpath_predicate(n, p->u.boolean.left)
325 && d1_check_xpath_predicate(n, p->u.boolean.right);
327 else if (!strcmp(p->u.boolean.op,"or")) {
328 return (d1_check_xpath_predicate(n, p->u.boolean.left)
329 || d1_check_xpath_predicate(n, p->u.boolean.right));
331 yaz_log(YLOG_WARN, "Unknown boolean relation %s, ignored",p->u.boolean.op);
340 static int dfa_match_first(struct DFA_state **dfaar, const char *text)
342 struct DFA_state *s = dfaar[0]; /* start state */
345 const char *p = text;
348 for (c = *p++, t = s->trans, i = s->tran_no; --i >= 0; t++)
350 if (c >= t->ch[0] && c <= t->ch[1])
354 /* move to next state and return if we get a match */
362 for (t = s->trans, i = s->tran_no; --i >= 0; t++)
363 if (c >= t->ch[0] && c <= t->ch[1])
373 New function, looking for xpath "element" definitions in abs, by
374 tagpath, using a kind of ugly regxp search.The DFA was built while
375 parsing abs, so here we just go trough them and try to match
376 against the given tagpath. The first matching entry is returned.
380 Added support for enhanced xelm. Now [] predicates are considered
381 as well, when selecting indexing rules... (why the hell it's called
388 data1_termlist *xpath_termlist_by_tagpath(char *tagpath, data1_node *n)
390 data1_absyn *abs = n->root->u.root.absyn;
392 data1_xpelement *xpe = 0;
395 struct xpath_location_step *xp;
397 char *pexpr = xmalloc(strlen(tagpath)+5);
399 sprintf (pexpr, "/%s\n", tagpath);
401 for (xpe = abs->xp_elements; xpe; xpe = xpe->next)
402 xpe->match_state = -1; /* don't know if it matches yet */
404 for (xpe = abs->xp_elements; xpe; xpe = xpe->next)
407 int ok = xpe->match_state;
409 { /* don't know whether there is a match yet */
410 data1_xpelement *xpe1;
413 ok = dfa_match_first(xpe->dfa->states, pexpr);
416 /* mark this and following ones with same regexp */
417 for (xpe1 = xpe; xpe1; xpe1 = xpe1->match_next)
418 xpe1->match_state = ok;
421 assert (ok == 0 || ok == 1);
424 /* we have to check the perdicates up to the root node */
427 /* find the first tag up in the node structure */
428 for (nn = n; nn && nn->which != DATA1N_tag; nn = nn->parent)
431 /* go from inside out in the node structure, while going
432 backwards trough xpath location steps ... */
433 for (i = xpe->xpath_len - 1; i>0; i--)
435 if (!d1_check_xpath_predicate(nn, xp[i].predicate))
441 if (nn->which == DATA1N_tag)
453 yaz_log(YLOG_DEBUG, "Got it");
454 return xpe->termlists;
461 1 start element (tag)
463 3 start attr (and attr-exact)
471 Now, if there is a matching xelm described in abs, for the
472 indexed element or the attribute, then the data is handled according
473 to those definitions...
475 modified by pop, 2002-12-13
478 /* add xpath index for an attribute */
479 static void index_xpath_attr (char *tag_path, char *name, char *value,
480 char *structure, struct recExtractCtrl *p,
483 wrd->index_name = ZEBRA_XPATH_ELM_BEGIN;
484 wrd->index_type = '0';
485 wrd->term_buf = tag_path;
486 wrd->term_len = strlen(tag_path);
490 wrd->index_name = ZEBRA_XPATH_ATTR_CDATA;
491 wrd->index_type = 'w';
492 wrd->term_buf = value;
493 wrd->term_len = strlen(value);
496 wrd->index_name = ZEBRA_XPATH_ELM_END;
497 wrd->index_type = '0';
498 wrd->term_buf = tag_path;
499 wrd->term_len = strlen(tag_path);
504 static void mk_tag_path_full(char *tag_path_full, size_t max, data1_node *n)
509 /* we have to fetch the whole path to the data tag */
510 for (nn = n; nn; nn = nn->parent)
512 if (nn->which == DATA1N_tag)
514 size_t tlen = strlen(nn->u.tag.tag);
515 if (tlen + flen > (max - 2))
517 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
519 tag_path_full[flen++] = '/';
522 if (nn->which == DATA1N_root)
525 tag_path_full[flen] = 0;
529 static void index_xpath(struct source_parser *sp, data1_node *n,
530 struct recExtractCtrl *p,
531 int level, RecWord *wrd,
537 char tag_path_full[1024];
538 int termlist_only = 1;
541 if (!n->root->u.root.absyn
543 n->root->u.root.absyn->xpath_indexing == DATA1_XPATH_INDEXING_ENABLE)
552 wrd->term_buf = n->u.data.data;
553 wrd->term_len = n->u.data.len;
555 mk_tag_path_full(tag_path_full, sizeof(tag_path_full), n);
557 /* If we have a matching termlist... */
558 if (n->root->u.root.absyn &&
559 (tl = xpath_termlist_by_tagpath(tag_path_full, n)))
562 for (; tl; tl = tl->next)
564 /* need to copy recword because it may be changed */
566 wrd->index_type = *tl->structure;
567 memcpy (&wrd_tl, wrd, sizeof(*wrd));
569 sp_parse(sp, n, &wrd_tl, tl->source);
571 /* this is just the old fashioned attribute based index */
572 wrd_tl.index_name = tl->index_name;
573 if (p->flagShowRecords)
576 printf("%*sIdx: [%s]", (level + 1) * 4, "",
578 printf("%s %s", tl->index_name, tl->source);
579 printf (" XData:\"");
580 for (i = 0; i<wrd_tl.term_len && i < 40; i++)
581 fputc (wrd_tl.term_buf[i], stdout);
583 if (wrd_tl.term_len > 40)
585 fputc ('\n', stdout);
589 (*p->tokenAdd)(&wrd_tl);
591 if (wrd_tl.seqno > max_seqno)
592 max_seqno = wrd_tl.seqno;
595 wrd->seqno = max_seqno;
598 /* xpath indexing is done, if there was no termlist given,
599 or no ! in the termlist, and default indexing is enabled... */
600 if (!p->flagShowRecords && !termlist_only)
602 wrd->index_name = xpath_index;
603 wrd->index_type = 'w';
608 mk_tag_path_full(tag_path_full, sizeof(tag_path_full), n);
610 wrd->index_type = '0';
611 wrd->term_buf = tag_path_full;
612 wrd->term_len = strlen(tag_path_full);
613 wrd->index_name = xpath_index;
614 if (p->flagShowRecords)
616 printf("%*s tag=", (level + 1) * 4, "");
617 for (i = 0; i<wrd->term_len && i < 40; i++)
618 fputc (wrd->term_buf[i], stdout);
628 (*p->tokenAdd)(wrd); /* index element pag (AKA tag path) */
630 if (xpath_is_start == 1) /* only for the starting tag... */
632 #define MAX_ATTR_COUNT 50
633 data1_termlist *tll[MAX_ATTR_COUNT];
636 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
638 char attr_tag_path_full[1024];
640 /* this could be cached as well */
641 sprintf (attr_tag_path_full, "@%s/%s",
642 xp->name, tag_path_full);
644 tll[i] = xpath_termlist_by_tagpath(attr_tag_path_full,n);
648 /* attribute (no value) */
649 wrd->index_type = '0';
650 wrd->index_name = ZEBRA_XPATH_ATTR_NAME;
651 wrd->term_buf = xp->name;
652 wrd->term_len = strlen(xp->name);
659 strlen(xp->name) + strlen(xp->value) < sizeof(comb)-2)
661 /* attribute value exact */
662 strcpy (comb, xp->name);
664 strcat (comb, xp->value);
666 wrd->index_name = ZEBRA_XPATH_ATTR_NAME;
667 wrd->index_type = '0';
668 wrd->term_buf = comb;
669 wrd->term_len = strlen(comb);
679 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
681 char attr_tag_path_full[1024];
684 sprintf (attr_tag_path_full, "@%s/%s",
685 xp->name, tag_path_full);
688 /* If there is a termlist given (=xelm directive) */
689 for (; tl; tl = tl->next)
693 /* add xpath index for the attribute */
694 index_xpath_attr (attr_tag_path_full, xp->name,
695 xp->value, tl->structure,
699 /* index attribute value (only path/@attr) */
702 wrd->index_name = tl->index_name;
703 wrd->index_type = *tl->structure;
704 wrd->term_buf = xp->value;
705 wrd->term_len = strlen(xp->value);
711 /* if there was no termlist for the given path,
712 or the termlist didn't have a ! element, index
713 the attribute as "w" */
714 if (!xpdone && !termlist_only)
716 index_xpath_attr (attr_tag_path_full, xp->name,
717 xp->value, "w", p, wrd);
726 static void index_termlist (struct source_parser *sp, data1_node *par,
728 struct recExtractCtrl *p, int level, RecWord *wrd)
730 data1_termlist *tlist = 0;
731 data1_datatype dtype = DATA1K_string;
734 * cycle up towards the root until we find a tag with an att..
735 * this has the effect of indexing locally defined tags with
736 * the attribute of their ancestor in the record.
739 while (!par->u.tag.element)
740 if (!par->parent || !(par=get_parent_tag(p->dh, par->parent)))
742 if (!par || !(tlist = par->u.tag.element->termlists))
744 if (par->u.tag.element->tag)
745 dtype = par->u.tag.element->tag->kind;
747 for (; tlist; tlist = tlist->next)
749 /* consider source */
751 assert(tlist->source);
752 sp_parse(sp, n, wrd, tlist->source);
754 if (wrd->term_buf && wrd->term_len)
756 if (p->flagShowRecords)
759 printf("%*sIdx: [%s]", (level + 1) * 4, "",
761 printf("%s %s", tlist->index_name, tlist->source);
762 printf (" XData:\"");
763 for (i = 0; i<wrd->term_len && i < 40; i++)
764 fputc (wrd->term_buf[i], stdout);
766 if (wrd->term_len > 40)
768 fputc ('\n', stdout);
772 wrd->index_type = *tlist->structure;
773 wrd->index_name = tlist->index_name;
780 static int dumpkeys_r(struct source_parser *sp,
781 data1_node *n, struct recExtractCtrl *p, int level,
784 for (; n; n = n->next)
786 if (p->flagShowRecords) /* display element description to user */
788 if (n->which == DATA1N_root)
790 printf("%*s", level * 4, "");
791 printf("Record type: '%s'\n", n->u.root.type);
793 else if (n->which == DATA1N_tag)
797 printf("%*s", level * 4, "");
798 if (!(e = n->u.tag.element))
799 printf("Local tag: '%s'\n", n->u.tag.tag);
802 printf("Elm: '%s' ", e->name);
805 data1_tag *t = e->tag;
807 printf("TagNam: '%s' ", t->names->name);
810 printf("%s[%d],", t->tagset->name, t->tagset->type);
813 if (t->which == DATA1T_numeric)
814 printf("%d)", t->value.numeric);
816 printf("'%s')", t->value.string);
823 if (n->which == DATA1N_tag)
825 index_termlist(sp, n, n, p, level, wrd);
826 /* index start tag */
827 if (n->root->u.root.absyn)
828 index_xpath(sp, n, p, level, wrd, ZEBRA_XPATH_ELM_BEGIN,
833 if (dumpkeys_r(sp, n->child, p, level + 1, wrd) < 0)
837 if (n->which == DATA1N_data)
839 data1_node *par = get_parent_tag(p->dh, n);
841 if (p->flagShowRecords)
843 printf("%*s", level * 4, "");
845 if (n->u.data.len > 256)
846 printf("'%.170s ... %.70s'\n", n->u.data.data,
847 n->u.data.data + n->u.data.len-70);
848 else if (n->u.data.len > 0)
849 printf("'%.*s'\n", n->u.data.len, n->u.data.data);
855 index_termlist(sp, par, n, p, level, wrd);
857 index_xpath(sp, n, p, level, wrd, ZEBRA_XPATH_CDATA,
861 if (n->which == DATA1N_tag)
864 index_xpath(sp, n, p, level, wrd, ZEBRA_XPATH_ELM_END,
868 if (p->flagShowRecords && n->which == DATA1N_root)
870 printf("%*s-------------\n\n", level * 4, "");
876 static int dumpkeys(data1_node *n, struct recExtractCtrl *p, RecWord *wrd)
878 struct source_parser *sp = source_parser_create();
879 int r = dumpkeys_r(sp, n, p, 0, wrd);
880 source_parser_destroy(sp);
884 int grs_extract_tree(struct recExtractCtrl *p, data1_node *n)
888 if (n->u.root.absyn && n->u.root.absyn->oid)
889 (*p->schemaAdd)(p, n->u.root.absyn->oid);
892 /* data1_pr_tree(p->dh, n, stdout); */
894 return dumpkeys(n, p, &wrd);
897 static int grs_extract_sub(void *clientData, struct recExtractCtrl *p,
899 data1_node *(*grs_read)(struct grs_read_info *))
902 struct grs_read_info gri;
905 gri.stream = p->stream;
908 gri.clientData = clientData;
910 n = (*grs_read)(&gri);
912 return RECCTRL_EXTRACT_EOF;
913 if (n->u.root.absyn && n->u.root.absyn->oid)
914 (*p->schemaAdd)(p, n->u.root.absyn->oid);
915 data1_concat_text(p->dh, mem, n);
917 /* ensure our data1 tree is UTF-8 */
918 data1_iconv (p->dh, mem, n, "UTF-8", data1_get_encoding(p->dh, n));
921 data1_remove_idzebra_subtree (p->dh, n);
924 data1_pr_tree (p->dh, n, stdout);
928 if (dumpkeys(n, p, &wrd) < 0)
930 return RECCTRL_EXTRACT_ERROR_GENERIC;
932 return RECCTRL_EXTRACT_OK;
935 int zebra_grs_extract(void *clientData, struct recExtractCtrl *p,
936 data1_node *(*grs_read)(struct grs_read_info *))
939 NMEM mem = nmem_create ();
940 ret = grs_extract_sub(clientData, p, mem, grs_read);
946 * Return: -1: Nothing done. 0: Ok. >0: Bib-1 diagnostic.
948 static int process_comp(data1_handle dh, data1_node *n, Z_RecordComposition *c,
949 char **addinfo, ODR o)
951 data1_esetname *eset;
957 case Z_RecordComp_simple:
958 if (c->u.simple->which != Z_ElementSetNames_generic)
959 return 26; /* only generic form supported. Fix this later */
960 if (!(eset = data1_getesetbyname(dh, n->u.root.absyn,
961 c->u.simple->u.generic)))
963 yaz_log(YLOG_LOG, "Unknown esetname '%s'", c->u.simple->u.generic);
964 *addinfo = odr_strdup(o, c->u.simple->u.generic);
965 return 25; /* invalid esetname */
967 yaz_log(YLOG_DEBUG, "Esetname '%s' in simple compspec",
968 c->u.simple->u.generic);
971 case Z_RecordComp_complex:
972 if (c->u.complex->generic)
974 /* insert check for schema */
975 if ((p = c->u.complex->generic->elementSpec))
979 case Z_ElementSpec_elementSetName:
981 data1_getesetbyname(dh, n->u.root.absyn,
982 p->u.elementSetName)))
984 yaz_log(YLOG_DEBUG, "Unknown esetname '%s'",
985 p->u.elementSetName);
986 *addinfo = odr_strdup(o, p->u.elementSetName);
987 return 25; /* invalid esetname */
989 yaz_log(YLOG_DEBUG, "Esetname '%s' in complex compspec",
990 p->u.elementSetName);
993 case Z_ElementSpec_externalSpec:
994 if (p->u.externalSpec->which == Z_External_espec1)
996 yaz_log(YLOG_DEBUG, "Got Espec-1");
997 espec = p->u.externalSpec-> u.espec1;
1001 yaz_log(YLOG_LOG, "Unknown external espec.");
1002 return 25; /* bad. what is proper diagnostic? */
1009 return 26; /* fix */
1013 yaz_log(YLOG_DEBUG, "Element: Espec-1 match");
1014 return data1_doespec1(dh, n, espec);
1018 yaz_log(YLOG_DEBUG, "Element: all match");
1023 /* Add Zebra info in separate namespace ...
1026 <metadata xmlns="http://www.indexdata.dk/zebra/">
1028 <localnumber>447</localnumber>
1029 <filename>records/genera.xml</filename>
1034 static void zebra_xml_metadata (struct recRetrieveCtrl *p, data1_node *top,
1037 const char *idzebra_ns[3];
1038 const char *i2 = "\n ";
1039 const char *i4 = "\n ";
1042 idzebra_ns[0] = "xmlns";
1043 idzebra_ns[1] = "http://www.indexdata.dk/zebra/";
1046 data1_mk_text (p->dh, mem, i2, top);
1048 n = data1_mk_tag (p->dh, mem, "idzebra", idzebra_ns, top);
1050 data1_mk_text (p->dh, mem, "\n", top);
1052 data1_mk_text (p->dh, mem, i4, n);
1054 data1_mk_tag_data_int (p->dh, n, "size", p->recordSize, mem);
1058 data1_mk_text (p->dh, mem, i4, n);
1059 data1_mk_tag_data_int (p->dh, n, "score", p->score, mem);
1061 data1_mk_text (p->dh, mem, i4, n);
1062 data1_mk_tag_data_zint (p->dh, n, "localnumber", p->localno, mem);
1065 data1_mk_text (p->dh, mem, i4, n);
1066 data1_mk_tag_data_text(p->dh, n, "filename", p->fname, mem);
1068 data1_mk_text (p->dh, mem, i2, n);
1071 int zebra_grs_retrieve(void *clientData, struct recRetrieveCtrl *p,
1072 data1_node *(*grs_read)(struct grs_read_info *))
1074 data1_node *node = 0, *onode = 0, *top;
1077 int res, selected = 0;
1079 struct grs_read_info gri;
1080 const char *tagname;
1082 const int *requested_schema = 0;
1083 data1_marctab *marctab;
1086 mem = nmem_create();
1087 gri.stream = p->stream;
1090 gri.clientData = clientData;
1092 yaz_log(YLOG_DEBUG, "grs_retrieve");
1093 node = (*grs_read)(&gri);
1096 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1100 data1_concat_text(p->dh, mem, node);
1102 data1_remove_idzebra_subtree (p->dh, node);
1105 data1_pr_tree (p->dh, node, stdout);
1107 top = data1_get_root_tag (p->dh, node);
1109 yaz_log(YLOG_DEBUG, "grs_retrieve: size");
1110 tagname = data1_systag_lookup(node->u.root.absyn, "size", "size");
1112 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1114 dnew->u.data.what = DATA1I_text;
1115 dnew->u.data.data = dnew->lbuf;
1116 sprintf(dnew->u.data.data, "%d", p->recordSize);
1117 dnew->u.data.len = strlen(dnew->u.data.data);
1120 tagname = data1_systag_lookup(node->u.root.absyn, "rank", "rank");
1121 if (tagname && p->score >= 0 &&
1122 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1124 yaz_log(YLOG_DEBUG, "grs_retrieve: %s", tagname);
1125 dnew->u.data.what = DATA1I_num;
1126 dnew->u.data.data = dnew->lbuf;
1127 sprintf(dnew->u.data.data, "%d", p->score);
1128 dnew->u.data.len = strlen(dnew->u.data.data);
1131 tagname = data1_systag_lookup(node->u.root.absyn, "sysno",
1132 "localControlNumber");
1133 if (tagname && p->localno > 0 &&
1134 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1136 yaz_log(YLOG_DEBUG, "grs_retrieve: %s", tagname);
1137 dnew->u.data.what = DATA1I_text;
1138 dnew->u.data.data = dnew->lbuf;
1140 sprintf(dnew->u.data.data, ZINT_FORMAT, p->localno);
1141 dnew->u.data.len = strlen(dnew->u.data.data);
1144 if (!p->input_format)
1145 { /* SUTRS is default input_format */
1146 p->input_format = yaz_oid_recsyn_sutrs;
1148 assert(p->input_format);
1150 if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_xml))
1151 zebra_xml_metadata (p, top, mem);
1154 data1_pr_tree (p->dh, node, stdout);
1156 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1157 p->comp->u.complex->generic &&
1158 p->comp->u.complex->generic->which == Z_Schema_oid &&
1159 p->comp->u.complex->generic->schema.oid)
1161 requested_schema = p->comp->u.complex->generic->schema.oid;
1163 /* If schema has been specified, map if possible, then check that
1164 * we got the right one
1166 if (requested_schema)
1168 yaz_log(YLOG_DEBUG, "grs_retrieve: schema mapping");
1169 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1171 // if (map->target_absyn_ref == requested_schema)
1172 if (!oid_oidcmp(map->oid, requested_schema))
1175 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1177 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1184 if (node->u.root.absyn
1185 && oid_oidcmp(requested_schema, node->u.root.absyn->oid))
1187 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1193 * Does the requested format match a known syntax-mapping? (this reflects
1194 * the overlap of schema and formatting which is inherent in the MARC
1197 yaz_log(YLOG_DEBUG, "grs_retrieve: syntax mapping");
1198 if (node->u.root.absyn)
1199 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1201 if (!oid_oidcmp(map->oid, p->input_format))
1204 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1206 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1213 yaz_log(YLOG_DEBUG, "grs_retrieve: schemaIdentifier");
1214 if (node->u.root.absyn && node->u.root.absyn->oid
1215 && !oid_oidcmp(p->input_format, yaz_oid_recsyn_grs_1))
1217 char oid_str[OID_STR_MAX];
1218 char *dot_str = oid_oid_to_dotstring(node->u.root.absyn->oid, oid_str);
1220 if (dot_str && (dnew = data1_mk_tag_data_wd(p->dh, top,
1221 "schemaIdentifier", mem)))
1223 dnew->u.data.what = DATA1I_oid;
1224 dnew->u.data.data = (char *) nmem_strdup(mem, dot_str);
1225 dnew->u.data.len = strlen(dot_str);
1229 yaz_log(YLOG_DEBUG, "grs_retrieve: element spec");
1230 if (p->comp && (res = process_comp(p->dh, node, p->comp, &p->addinfo,
1233 p->diagnostic = res;
1237 else if (p->comp && !res)
1241 data1_pr_tree (p->dh, node, stdout);
1243 yaz_log(YLOG_DEBUG, "grs_retrieve: transfer syntax mapping");
1245 p->output_format = p->input_format;
1247 assert(p->input_format);
1248 if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_xml))
1251 data1_pr_tree (p->dh, node, stdout);
1253 /* default output encoding for XML is UTF-8 */
1254 data1_iconv (p->dh, mem, node,
1255 p->encoding ? p->encoding : "UTF-8",
1256 data1_get_encoding(p->dh, node));
1258 if (!(p->rec_buf = data1_nodetoidsgml(p->dh, node, selected,
1260 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1263 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1264 memcpy (new_buf, p->rec_buf, p->rec_len);
1265 p->rec_buf = new_buf;
1268 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_grs_1))
1270 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1272 if (!(p->rec_buf = data1_nodetogr(p->dh, node, selected,
1274 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1278 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_explain))
1280 /* ensure our data1 tree is UTF-8 */
1281 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1283 if (!(p->rec_buf = data1_nodetoexplain(p->dh, node, selected,
1285 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1289 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_summary))
1291 /* ensure our data1 tree is UTF-8 */
1292 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1293 if (!(p->rec_buf = data1_nodetosummary(p->dh, node, selected,
1295 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1299 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_sutrs))
1302 data1_iconv (p->dh, mem, node, p->encoding,
1303 data1_get_encoding(p->dh, node));
1304 if (!(p->rec_buf = data1_nodetobuf(p->dh, node, selected,
1306 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1309 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1310 memcpy (new_buf, p->rec_buf, p->rec_len);
1311 p->rec_buf = new_buf;
1314 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_soif))
1317 data1_iconv (p->dh, mem, node, p->encoding,
1318 data1_get_encoding(p->dh, node));
1319 if (!(p->rec_buf = data1_nodetosoif(p->dh, node, selected,
1321 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1324 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1325 memcpy (new_buf, p->rec_buf, p->rec_len);
1326 p->rec_buf = new_buf;
1331 if (!node->u.root.absyn)
1332 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1335 for (marctab = node->u.root.absyn->marc; marctab;
1336 marctab = marctab->next)
1337 if (marctab->oid && !oid_oidcmp(marctab->oid, p->input_format))
1340 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1344 data1_iconv (p->dh, mem, node, p->encoding,
1345 data1_get_encoding(p->dh, node));
1346 if (!(p->rec_buf = data1_nodetomarc(p->dh, marctab, node,
1347 selected, &p->rec_len)))
1348 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1351 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1352 memcpy (new_buf, p->rec_buf, p->rec_len);
1353 p->rec_buf = new_buf;
1365 * indent-tabs-mode: nil
1367 * vim: shiftwidth=4 tabstop=8 expandtab