1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2013 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SRU 2.0 facets
16 #include <yaz/wrbuf.h>
18 #include <libxml/parser.h>
19 #include <libxml/tree.h>
24 #include <yaz/pquery.h>
25 #include <yaz/facet.h>
27 static void insert_field(WRBUF w, const char *field, size_t length,
30 const char *cp0 = wrbuf_cstr(w);
35 const char *cp2 = strstr(cp, "@attr 1=");
39 if (!strncmp(cp, field, length) &&
40 (cp[length] == ' ' || cp[length] == ',' || cp[length] == '\0'))
45 wrbuf_insert(w, cp - cp0, attr, strlen(attr));
46 wrbuf_insert(w, cp - cp0, " ", 1);
49 while (*cp && *cp != ',')
54 wrbuf_puts(w, "@attr 1=");
55 wrbuf_write(w, field, length);
60 void yaz_sru_facet_request(ODR o, Z_FacetList **facetList, const char **limit,
61 const char **start, const char **sort)
63 if (o->direction == ODR_ENCODE)
65 Z_FacetList *fl = *facetList;
68 WRBUF w_limit = wrbuf_alloc();
69 WRBUF w_start = wrbuf_alloc();
70 WRBUF w_sort = wrbuf_alloc();
72 for (i = 0; i < fl->num; i++)
74 struct yaz_facet_attr av;
75 yaz_facet_attr_init(&av);
76 yaz_facet_attr_get_z_attributes(fl->elements[i]->attributes,
82 wrbuf_printf(w_limit, "%d", av.limit);
84 wrbuf_printf(w_limit, ":%s", av.useattr);
85 wrbuf_puts(w_limit, ",");
87 if (av.start || av.useattr)
89 wrbuf_printf(w_start, "%d",
90 av.start == 0 ? 1 : av.start);
92 wrbuf_printf(w_start, ":%s", av.useattr);
93 wrbuf_puts(w_start, ",");
95 if (av.sortorder == 1)
97 /* allow sorting per field */
98 /* not really according to spec */
99 wrbuf_printf(w_sort, "alphanumeric");
101 wrbuf_printf(w_sort, ":%s", av.useattr);
102 wrbuf_puts(w_sort, ",");
106 if (wrbuf_len(w_limit) > 1)
108 wrbuf_cut_right(w_limit, 1); /* remove , */
109 *limit = odr_strdup(o, wrbuf_cstr(w_limit));
111 if (wrbuf_len(w_start) > 1)
113 wrbuf_cut_right(w_start, 1); /* remove , */
114 *start = odr_strdup(o, wrbuf_cstr(w_start));
116 if (wrbuf_len(w_sort) > 1)
118 wrbuf_cut_right(w_sort, 1); /* remove , */
119 *sort = odr_strdup(o, wrbuf_cstr(w_sort));
121 wrbuf_destroy(w_limit);
122 wrbuf_destroy(w_start);
123 wrbuf_destroy(w_sort);
126 else if (o->direction == ODR_DECODE)
128 WRBUF w = wrbuf_alloc();
132 const char *cp = *limit;
135 while (sscanf(cp, "%d%n", &val, &nor) >= 1 && nor > 0)
138 if (*cp == ':') /* field name follows */
141 const char *cp0 = ++cp;
142 while (*cp && *cp != ',')
144 sprintf(tmp, "@attr 3=%d", val);
145 insert_field(w, cp0, cp - cp0, tmp);
154 const char *cp = *start;
157 while (sscanf(cp, "%d%n", &val, &nor) >= 1 && nor > 0)
160 if (*cp == ':') /* field name follows */
163 const char *cp0 = ++cp;
164 while (*cp && *cp != ',')
166 sprintf(tmp, "@attr 4=%d", val);
167 insert_field(w, cp0, cp - cp0, tmp);
177 const char *cp = *sort;
181 const char *cp0 = cp;
182 while (*cp && *cp != ':' && *cp != ',')
184 if (!strncmp(cp0, "alphanumeric", cp - cp0))
186 if (*cp == ':') /* field name follows */
190 while (*cp && *cp != ',')
192 sprintf(tmp, "@attr 2=%d", val);
193 insert_field(w, cp0, cp - cp0, tmp);
202 *facetList = yaz_pqf_parse_facet_list(o, wrbuf_cstr(w));
210 void yaz_sru_facet_response(ODR o, Z_FacetList **facetList, xmlNodePtr n)
212 if (o->direction == ODR_ENCODE)
214 Z_FacetList *fl = *facetList;
219 "http://docs.oasis-open.org/ns/search-ws/facetedResults";
220 xmlNode *p1 = xmlNewChild(n, 0, BAD_CAST "facetedResults", 0);
221 xmlNsPtr ns_fr = xmlNewNs(p1, BAD_CAST ns, BAD_CAST "fr");
223 for (i = 0; i < fl->num; i++)
225 Z_FacetField *ff = fl->elements[i];
226 xmlNode *p2 = xmlNewChild(p1, 0, BAD_CAST "facet", 0);
229 struct yaz_facet_attr av;
230 yaz_facet_attr_init(&av);
231 yaz_facet_attr_get_z_attributes(ff->attributes, &av);
232 add_xsd_string(p2, "index", av.useattr);
233 p3 = xmlNewChild(p2, 0, BAD_CAST "terms", 0);
234 for (j = 0; j < ff->num_terms; j++)
236 Z_FacetTerm *ft = ff->terms[j];
237 Z_Term *zt = ft->term;
238 xmlNode *p4 = xmlNewChild(p3, 0, BAD_CAST "term", 0);
239 if (zt->which == Z_Term_general)
240 add_xsd_string_n(p4, "actualTerm",
241 (char *) zt->u.general->buf,
244 add_xsd_integer(p4, "count", ft->count);
249 else if (o->direction == ODR_DECODE)
251 Z_FacetList *fl = (Z_FacetList *) odr_malloc(o, sizeof(*fl));
255 for (p1 = n->children; p1; p1 = p1->next)
256 if (yaz_match_xsd_element(p1, "facet"))
262 fl->elements = (Z_FacetField **)
263 odr_malloc(o, sizeof(*fl->elements) * fl->num);
264 for (p1 = n->children; p1; p1 = p1->next)
265 if (yaz_match_xsd_element(p1, "facet"))
267 char *index_name = 0;
268 xmlNode *p_terms = 0;
269 xmlNode *p2 = p1->children;
270 Z_FacetField *ff = (Z_FacetField *)
271 odr_malloc(o, sizeof(*ff));
272 fl->elements[i++] = ff;
276 for (; p2; p2 = p2->next)
278 if (yaz_match_xsd_string(p2, "index", o, &index_name))
280 else if (yaz_match_xsd_element(p2, "terms"))
285 Z_AttributeList *al =
286 (Z_AttributeList*) odr_malloc(o, sizeof(*al));
287 Z_ComplexAttribute *ca =
288 (Z_ComplexAttribute *) odr_malloc(o, sizeof(*ca));
289 Z_AttributeElement *ae =
290 (Z_AttributeElement *) odr_malloc(o, sizeof(*ae));
291 al->num_attributes = 1;
292 al->attributes = (Z_AttributeElement **)
293 odr_malloc(o, sizeof(*al->attributes));
294 al->attributes[0] = ae;
295 ae->attributeSet = 0;
296 ae->attributeType = odr_intdup(o, 1);
297 ae->which = Z_AttributeValue_complex;
298 ae->value.complex = ca;
299 ca->num_semanticAction = 0;
300 ca->semanticAction = 0;
302 ca->list = (Z_StringOrNumeric **)
303 odr_malloc(o, sizeof(*ca->list));
304 ca->list[0] = (Z_StringOrNumeric *)
305 odr_malloc(o, sizeof(**ca->list));
306 ca->list[0]->which = Z_StringOrNumeric_string;
307 ca->list[0]->u.string = index_name;
314 for (p = p_terms->children; p; p = p->next)
316 if (yaz_match_xsd_element(p, "term"))
320 ff->terms = (Z_FacetTerm **)
322 sizeof(*ff->terms) * ff->num_terms);
323 for (p = p_terms->children; p; p = p->next)
325 if (yaz_match_xsd_element(p, "term"))
329 xmlNode *p2 = p->children;
330 for (; p2; p2 = p2->next)
332 if (yaz_match_xsd_string(p2, "actualTerm", o,
335 else if (yaz_match_xsd_integer(p2, "count", o,
342 facet_term_create_cstr(o, cstr, *count);
347 if (ff->num_terms == 0)
362 * c-file-style: "Stroustrup"
363 * indent-tabs-mode: nil
365 * vim: shiftwidth=4 tabstop=8 expandtab