This source file includes following definitions.
- freeXpathObject
- getXpathResult
- dedupXpathResults
- xpath_search
- crm_foreach_xpath_result
- get_xpath_object_relative
- get_xpath_object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <crm_internal.h>
20 #include <stdio.h>
21 #include <string.h>
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 void
45 freeXpathObject(xmlXPathObjectPtr xpathObj)
46 {
47 int lpc, max = numXpathResults(xpathObj);
48
49 if (xpathObj == NULL) {
50 return;
51 }
52
53 for (lpc = 0; lpc < max; lpc++) {
54 if (xpathObj->nodesetval->nodeTab[lpc] && xpathObj->nodesetval->nodeTab[lpc]->type != XML_NAMESPACE_DECL) {
55 xpathObj->nodesetval->nodeTab[lpc] = NULL;
56 }
57 }
58
59
60 xmlXPathFreeObject(xpathObj);
61 }
62
63 xmlNode *
64 getXpathResult(xmlXPathObjectPtr xpathObj, int index)
65 {
66 xmlNode *match = NULL;
67 int max = numXpathResults(xpathObj);
68
69 CRM_CHECK(index >= 0, return NULL);
70 CRM_CHECK(xpathObj != NULL, return NULL);
71
72 if (index >= max) {
73 crm_err("Requested index %d of only %d items", index, max);
74 return NULL;
75
76 } else if(xpathObj->nodesetval->nodeTab[index] == NULL) {
77
78 return NULL;
79 }
80
81 match = xpathObj->nodesetval->nodeTab[index];
82 CRM_CHECK(match != NULL, return NULL);
83
84 if (xpathObj->nodesetval->nodeTab[index]->type != XML_NAMESPACE_DECL) {
85
86 xpathObj->nodesetval->nodeTab[index] = NULL;
87 }
88
89 if (match->type == XML_DOCUMENT_NODE) {
90
91 match = match->children;
92
93 } else if (match->type != XML_ELEMENT_NODE
94 && match->parent && match->parent->type == XML_ELEMENT_NODE) {
95
96 match = match->parent;
97
98 } else if (match->type != XML_ELEMENT_NODE) {
99
100 crm_err("We only support %d not %d", XML_ELEMENT_NODE, match->type);
101 match = NULL;
102 }
103 return match;
104 }
105
106 void
107 dedupXpathResults(xmlXPathObjectPtr xpathObj)
108 {
109 int lpc, max = numXpathResults(xpathObj);
110
111 if (xpathObj == NULL) {
112 return;
113 }
114
115 for (lpc = 0; lpc < max; lpc++) {
116 xmlNode *xml = NULL;
117 gboolean dedup = FALSE;
118
119 if (xpathObj->nodesetval->nodeTab[lpc] == NULL) {
120 continue;
121 }
122
123 xml = xpathObj->nodesetval->nodeTab[lpc]->parent;
124
125 for (; xml; xml = xml->parent) {
126 int lpc2 = 0;
127
128 for (lpc2 = 0; lpc2 < max; lpc2++) {
129 if (xpathObj->nodesetval->nodeTab[lpc2] == xml) {
130 xpathObj->nodesetval->nodeTab[lpc] = NULL;
131 dedup = TRUE;
132 break;
133 }
134 }
135
136 if (dedup) {
137 break;
138 }
139 }
140 }
141 }
142
143
144 xmlXPathObjectPtr
145 xpath_search(xmlNode * xml_top, const char *path)
146 {
147 xmlDocPtr doc = NULL;
148 xmlXPathObjectPtr xpathObj = NULL;
149 xmlXPathContextPtr xpathCtx = NULL;
150 const xmlChar *xpathExpr = (const xmlChar *)path;
151
152 CRM_CHECK(path != NULL, return NULL);
153 CRM_CHECK(xml_top != NULL, return NULL);
154 CRM_CHECK(strlen(path) > 0, return NULL);
155
156 doc = getDocPtr(xml_top);
157
158 xpathCtx = xmlXPathNewContext(doc);
159 CRM_ASSERT(xpathCtx != NULL);
160
161 xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
162 xmlXPathFreeContext(xpathCtx);
163 return xpathObj;
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177
178 void
179 crm_foreach_xpath_result(xmlNode *xml, const char *xpath,
180 void (*helper)(xmlNode*, void*), void *user_data)
181 {
182 xmlXPathObjectPtr xpathObj = xpath_search(xml, xpath);
183 int nresults = numXpathResults(xpathObj);
184 int i;
185
186 for (i = 0; i < nresults; i++) {
187 xmlNode *result = getXpathResult(xpathObj, i);
188
189 CRM_LOG_ASSERT(result != NULL);
190 if (result) {
191 (*helper)(result, user_data);
192 }
193 }
194 freeXpathObject(xpathObj);
195 }
196
197 xmlNode *
198 get_xpath_object_relative(const char *xpath, xmlNode * xml_obj, int error_level)
199 {
200 int len = 0;
201 xmlNode *result = NULL;
202 char *xpath_full = NULL;
203 char *xpath_prefix = NULL;
204
205 if (xml_obj == NULL || xpath == NULL) {
206 return NULL;
207 }
208
209 xpath_prefix = (char *)xmlGetNodePath(xml_obj);
210
211 len = strlen(xpath_prefix) + strlen(xpath) + 1;
212 xpath_full = malloc(len);
213 strcpy(xpath_full, xpath_prefix);
214 strcat(xpath_full, xpath);
215
216 result = get_xpath_object(xpath_full, xml_obj, error_level);
217
218 free(xpath_prefix);
219 free(xpath_full);
220 return result;
221 }
222
223 xmlNode *
224 get_xpath_object(const char *xpath, xmlNode * xml_obj, int error_level)
225 {
226 int max;
227 xmlNode *result = NULL;
228 xmlXPathObjectPtr xpathObj = NULL;
229 char *nodePath = NULL;
230 char *matchNodePath = NULL;
231
232 if (xpath == NULL) {
233 return xml_obj;
234 }
235
236 xpathObj = xpath_search(xml_obj, xpath);
237 nodePath = (char *)xmlGetNodePath(xml_obj);
238 max = numXpathResults(xpathObj);
239
240 if (max < 1) {
241 do_crm_log(error_level, "No match for %s in %s", xpath, crm_str(nodePath));
242 crm_log_xml_explicit(xml_obj, "Unexpected Input");
243
244 } else if (max > 1) {
245 int lpc = 0;
246
247 do_crm_log(error_level, "Too many matches for %s in %s", xpath, crm_str(nodePath));
248
249 for (lpc = 0; lpc < max; lpc++) {
250 xmlNode *match = getXpathResult(xpathObj, lpc);
251
252 CRM_LOG_ASSERT(match != NULL);
253 if(match != NULL) {
254 matchNodePath = (char *)xmlGetNodePath(match);
255 do_crm_log(error_level, "%s[%d] = %s", xpath, lpc, crm_str(matchNodePath));
256 free(matchNodePath);
257 }
258 }
259 crm_log_xml_explicit(xml_obj, "Bad Input");
260
261 } else {
262 result = getXpathResult(xpathObj, 0);
263 }
264
265 freeXpathObject(xpathObj);
266 free(nodePath);
267
268 return result;
269 }