+ xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "version",
+ 0);
+ yaz_srw_version(o, rptr, (*vers)+i, client_data, ns);
+ }
+ }
+ return 0;
+}
+
+Z_FacetTerm *yaz_sru_proxy_get_facet_term_count(ODR odr, xmlNodePtr node)
+{
+ int freq;
+ xmlNodePtr child;
+ WRBUF wrbuf = wrbuf_alloc();
+ const char *freq_string = yaz_element_attribute_value_get(
+ node, "facetvalue", "est_representation");
+ Z_Term *term;
+ if (freq_string)
+ freq = atoi(freq_string);
+ else
+ freq = -1;
+
+ for (child = node->children; child ; child = child->next)
+ {
+ if (child->type == XML_TEXT_NODE)
+ wrbuf_puts(wrbuf, (const char *) child->content);
+ }
+ term = term_create(odr, wrbuf_cstr(wrbuf));
+ yaz_log(YLOG_DEBUG, "sru-proxy facet: %s %d", wrbuf_cstr(wrbuf), freq);
+ wrbuf_destroy(wrbuf);
+ return facet_term_create(odr, term, freq);
+};
+
+static Z_FacetField *yaz_sru_proxy_decode_facet_field(ODR odr, xmlNodePtr ptr)
+{
+ Z_AttributeList *list;
+ Z_FacetField *facet_field;
+ int num_terms = 0;
+ int index = 0;
+ xmlNodePtr node;
+ /* USE attribute */
+ const char* name = yaz_element_attribute_value_get(ptr, "facet", "code");
+ yaz_log(YLOG_DEBUG, "sru-proxy facet type: %s", name);
+
+ list = yaz_use_attribute_create(odr, name);
+ for (node = ptr->children; node; node = node->next) {
+ if (match_element(node, "facetvalue"))
+ num_terms++;
+ }
+ facet_field = facet_field_create(odr, list, num_terms);
+ index = 0;
+ for (node = ptr->children; node; node = node->next)
+ {
+ if (match_element(node, "facetvalue"))
+ {
+ facet_field_term_set(odr, facet_field,
+ yaz_sru_proxy_get_facet_term_count(odr, node),
+ index);
+ index++;
+ }
+ }
+ return facet_field;
+}
+
+static int yaz_sru_proxy_decode_facets(ODR o, xmlNodePtr root,
+ Z_FacetList **facetList)
+{
+ xmlNodePtr ptr;
+
+ for (ptr = root->children; ptr; ptr = ptr->next)
+ {
+ if (match_element(ptr, "facets"))
+ {
+ xmlNodePtr node;
+ Z_FacetList *facet_list;
+ int num_facets = 0;
+ for (node = ptr->children; node; node= node->next)
+ {
+ if (node->type == XML_ELEMENT_NODE)
+ num_facets++;
+ }
+ facet_list = facet_list_create(o, num_facets);
+ num_facets = 0;
+ for (node = ptr->children; node; node= node->next)
+ {
+ if (match_element(node, "facet")) {
+ facet_list_field_set(o, facet_list, yaz_sru_proxy_decode_facet_field(o, node), num_facets);
+ num_facets++;
+ }
+ }
+ *facetList = facet_list;
+ break;
+ }
+ }
+ return 0;
+}
+
+
+
+static int yaz_srw_decode_diagnostics(ODR o, xmlNodePtr pptr,
+ Z_SRW_diagnostic **recs, int *num,
+ void *client_data, const char *ns)
+{
+ int i;
+ xmlNodePtr ptr;
+ *num = 0;
+ for (ptr = pptr; ptr; ptr = ptr->next)
+ {
+ if (ptr->type == XML_ELEMENT_NODE &&
+ !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
+ (*num)++;
+ }
+ if (!*num)
+ return 1;
+ *recs = (Z_SRW_diagnostic *) odr_malloc(o, *num * sizeof(**recs));
+ for (i = 0; i < *num; i++)
+ {
+ (*recs)[i].uri = 0;
+ (*recs)[i].details = 0;
+ (*recs)[i].message = 0;
+ }
+ for (i = 0, ptr = pptr; ptr; ptr = ptr->next)
+ {
+ if (ptr->type == XML_ELEMENT_NODE &&
+ !xmlStrcmp(ptr->name, BAD_CAST "diagnostic"))
+ {
+ xmlNodePtr rptr;
+ (*recs)[i].uri = 0;
+ (*recs)[i].details = 0;
+ (*recs)[i].message = 0;
+ for (rptr = ptr->children; rptr; rptr = rptr->next)
+ {
+ if (match_xsd_string(rptr, "uri", o,
+ &(*recs)[i].uri))
+ ;
+ else if (match_xsd_string(rptr, "details", o,
+ &(*recs)[i].details))
+ ;
+ else
+ match_xsd_string(rptr, "message", o, &(*recs)[i].message);
+ }
+ i++;
+ }
+ }
+ return 0;
+}
+
+int sru_decode_surrogate_diagnostics(const char *buf, size_t len,
+ Z_SRW_diagnostic **diag,
+ int *num, ODR odr)
+{
+ int ret = 0;
+ xmlDocPtr doc = xmlParseMemory(buf, len);
+ if (doc)
+ {
+ xmlNodePtr ptr = xmlDocGetRootElement(doc);
+ while (ptr && ptr->type != XML_ELEMENT_NODE)
+ ptr = ptr->next;
+ if (ptr && ptr->ns
+ && !xmlStrcmp(ptr->ns->href,
+ BAD_CAST "http://www.loc.gov/zing/srw/diagnostic/"))
+ {
+ ret = yaz_srw_decode_diagnostics(odr, ptr, diag, num, 0, 0);
+ }
+ xmlFreeDoc(doc);
+ }
+ return ret;
+}
+
+static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs,
+ int *num, void *client_data, const char *ns)
+{
+ if (o->direction == ODR_DECODE)
+ {
+ return yaz_srw_decode_diagnostics(o, pptr->children, recs, num, client_data, ns);
+ }
+ else if (o->direction == ODR_ENCODE)
+ {
+ int i;
+ xmlNsPtr ns_diag =
+ xmlNewNs(pptr, BAD_CAST YAZ_XMLNS_DIAG_v1_1, BAD_CAST "diag" );
+ for (i = 0; i < *num; i++)
+ {
+ const char *std_diag = "info:srw/diagnostic/1/";
+ const char *ucp_diag = "info:srw/diagnostic/12/";
+ xmlNodePtr rptr = xmlNewChild(pptr, ns_diag,
+ BAD_CAST "diagnostic", 0);
+ add_xsd_string(rptr, "uri", (*recs)[i].uri);
+ if ((*recs)[i].message)
+ add_xsd_string(rptr, "message", (*recs)[i].message);
+ else if ((*recs)[i].uri )
+ {
+ if (!strncmp((*recs)[i].uri, std_diag, strlen(std_diag)))
+ {
+ int no = atoi((*recs)[i].uri + strlen(std_diag));
+ const char *message = yaz_diag_srw_str(no);
+ if (message)
+ add_xsd_string(rptr, "message", message);
+ }
+ else if (!strncmp((*recs)[i].uri, ucp_diag, strlen(ucp_diag)))
+ {
+ int no = atoi((*recs)[i].uri + strlen(ucp_diag));
+ const char *message = yaz_diag_sru_update_str(no);
+ if (message)
+ add_xsd_string(rptr, "message", message);
+ }
+ }