ZOOM: For redirect, reconnect always YAZ-722
[yaz-moved-to-github.git] / src / xml_match.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file xml_match.c
7  * \brief XML node inspection utilities
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <yaz/srw.h>
14 #if YAZ_HAVE_XML2
15 #include "sru-p.h"
16
17 int yaz_match_xsd_element(xmlNodePtr ptr, const char *elem)
18 {
19     if (ptr->type == XML_ELEMENT_NODE && !xmlStrcmp(ptr->name, BAD_CAST elem))
20     {
21         return 1;
22     }
23     return 0;
24 }
25
26 #define CHECK_TYPE 0
27
28 int yaz_match_xsd_string_n_nmem(xmlNodePtr ptr, const char *elem, NMEM nmem,
29                                 char **val, int *len)
30 {
31 #if CHECK_TYPE
32     struct _xmlAttr *attr;
33 #endif
34     if (!yaz_match_xsd_element(ptr, elem))
35         return 0;
36 #if CHECK_TYPE
37     for (attr = ptr->properties; attr; attr = attr->next)
38         if (!strcmp(attr->name, "type") &&
39             attr->children && attr->children->type == XML_TEXT_NODE)
40         {
41             const char *t = strchr(attr->children->content, ':');
42             if (t)
43                 t = t + 1;
44             else
45                 t = attr->children->content;
46             if (!strcmp(t, "string"))
47                 break;
48         }
49     if (!attr)
50         return 0;
51 #endif
52     ptr = ptr->children;
53     if (!ptr || ptr->type != XML_TEXT_NODE)
54     {
55         *val = "";
56         return 1;
57     }
58     *val = nmem_strdup(nmem, (const char *) ptr->content);
59     if (len)
60         *len = xmlStrlen(ptr->content);
61     return 1;
62 }
63
64 int yaz_match_xsd_string_n(xmlNodePtr ptr, const char *elem, ODR o,
65                            char **val, int *len)
66 {
67     return yaz_match_xsd_string_n_nmem(ptr, elem, o->mem, val, len);
68 }
69
70 int yaz_match_xsd_string(xmlNodePtr ptr, const char *elem, ODR o, char **val)
71 {
72     return yaz_match_xsd_string_n(ptr, elem, o, val, 0);
73 }
74
75 int yaz_match_xsd_XML_n2(xmlNodePtr ptr, const char *elem, ODR o,
76                          char **val, int *len, int fixup_root)
77 {
78     xmlBufferPtr buf;
79     int no_root_nodes = 0;
80
81     if (!yaz_match_xsd_element(ptr, elem))
82         return 0;
83
84     buf = xmlBufferCreate();
85
86     /* Copy each element nodes at top.
87        In most cases there is only one root node.. At least one server
88        http://www.theeuropeanlibrary.org/sru/sru.pl
89        has multiple root nodes in recordData.
90     */
91     for (ptr = ptr->children; ptr; ptr = ptr->next)
92     {
93         if (ptr->type == XML_ELEMENT_NODE)
94         {
95             /* copy node to get NS right (bug #740). */
96             xmlNode *tmp = xmlCopyNode(ptr, 1);
97
98             xmlNodeDump(buf, tmp->doc, tmp, 0, 0);
99
100             xmlFreeNode(tmp);
101             no_root_nodes++;
102         }
103     }
104     if (no_root_nodes != 1 && fixup_root)
105     {
106         /* does not appear to be an XML document. Make it so */
107         xmlBufferAddHead(buf, (const xmlChar *) "<yaz_record>", -1);
108         xmlBufferAdd(buf, (const xmlChar *) "</yaz_record>", -1);
109     }
110     *val = odr_strdupn(o, (const char *) buf->content, buf->use);
111     if (len)
112         *len = buf->use;
113
114     xmlBufferFree(buf);
115
116     return 1;
117 }
118
119 int yaz_match_xsd_XML_n(xmlNodePtr ptr, const char *elem, ODR o,
120                         char **val, int *len)
121 {
122     return yaz_match_xsd_XML_n2(ptr, elem, o, val, len, 0);
123 }
124
125 int yaz_match_xsd_integer(xmlNodePtr ptr, const char *elem, ODR o,
126                           Odr_int **val)
127 {
128 #if CHECK_TYPE
129     struct _xmlAttr *attr;
130 #endif
131     if (!yaz_match_xsd_element(ptr, elem))
132         return 0;
133 #if CHECK_TYPE
134     for (attr = ptr->properties; attr; attr = attr->next)
135         if (!strcmp(attr->name, "type") &&
136             attr->children && attr->children->type == XML_TEXT_NODE)
137         {
138             const char *t = strchr(attr->children->content, ':');
139             if (t)
140                 t = t + 1;
141             else
142                 t = attr->children->content;
143             if (!strcmp(t, "integer"))
144                 break;
145         }
146     if (!attr)
147         return 0;
148 #endif
149     ptr = ptr->children;
150     if (!ptr || ptr->type != XML_TEXT_NODE)
151         return 0;
152     *val = odr_intdup(o, odr_atoi((const char *) ptr->content));
153     return 1;
154 }
155
156
157 #endif
158
159
160 /*
161  * Local variables:
162  * c-basic-offset: 4
163  * c-file-style: "Stroustrup"
164  * indent-tabs-mode: nil
165  * End:
166  * vim: shiftwidth=4 tabstop=8 expandtab
167  */
168