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