|
1 /** |
|
2 * XML Security Library (http://www.aleksey.com/xmlsec). |
|
3 * |
|
4 * Enchanced nodes set |
|
5 * |
|
6 * This is free software; see Copyright file in the source |
|
7 * distribution for preciese wording. |
|
8 * |
|
9 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> |
|
10 * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
11 */ |
|
12 #include "xmlsec_globals.h" |
|
13 |
|
14 #include <stdlib.h> |
|
15 #include <string.h> |
|
16 |
|
17 #include <libxml2_tree.h> |
|
18 #include <libxml2_xpath.h> |
|
19 #include <libxml2_xpathinternals.h> |
|
20 #include <libxml2_globals.h> |
|
21 |
|
22 #include "xmlsec_xmlsec.h" |
|
23 #include "xmlsec_nodeset.h" |
|
24 #include "xmlsec_errors.h" |
|
25 |
|
26 #define xmlSecGetParent(node) \ |
|
27 (((node)->type != XML_NAMESPACE_DECL) ? \ |
|
28 (node)->parent : \ |
|
29 (xmlNodePtr)((xmlNsPtr)(node))->next) |
|
30 |
|
31 static int xmlSecNodeSetOneContains (xmlSecNodeSetPtr nset, |
|
32 xmlNodePtr node, |
|
33 xmlNodePtr parent); |
|
34 static int xmlSecNodeSetWalkRecursive (xmlSecNodeSetPtr nset, |
|
35 xmlSecNodeSetWalkCallback walkFunc, |
|
36 void* data, |
|
37 xmlNodePtr cur, |
|
38 xmlNodePtr parent); |
|
39 |
|
40 /** |
|
41 * xmlSecNodeSetCreate: |
|
42 * @doc: the pointer to parent XML document. |
|
43 * @nodes: the list of nodes. |
|
44 * @type: the nodes set type. |
|
45 * |
|
46 * Creates new nodes set. Caller is responsible for freeng returend object |
|
47 * by calling #xmlSecNodeSetDestroy function. |
|
48 * |
|
49 * Returns pointer to newly allocated node set or NULL if an error occurs. |
|
50 */ |
|
51 EXPORT_C |
|
52 xmlSecNodeSetPtr |
|
53 xmlSecNodeSetCreate(xmlDocPtr doc, xmlNodeSetPtr nodes, xmlSecNodeSetType type) { |
|
54 xmlSecNodeSetPtr nset; |
|
55 |
|
56 nset = (xmlSecNodeSetPtr)xmlMalloc(sizeof(xmlSecNodeSet)); |
|
57 if(nset == NULL) { |
|
58 xmlSecError(XMLSEC_ERRORS_HERE, |
|
59 NULL, |
|
60 NULL, |
|
61 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
62 "sizeof(xmlSecNodeSet)=%d", |
|
63 sizeof(xmlSecNodeSet)); |
|
64 return(NULL); |
|
65 } |
|
66 memset(nset, 0, sizeof(xmlSecNodeSet)); |
|
67 |
|
68 nset->doc = doc; |
|
69 nset->nodes = nodes; |
|
70 nset->type = type; |
|
71 nset->next = nset->prev = nset; |
|
72 return(nset); |
|
73 } |
|
74 |
|
75 /** |
|
76 * xmlSecNodeSetDestroy: |
|
77 * @nset: the pointer to node set. |
|
78 * |
|
79 * Destroys the nodes set created with #xmlSecNodeSetCreate function. |
|
80 */ |
|
81 EXPORT_C |
|
82 void |
|
83 xmlSecNodeSetDestroy(xmlSecNodeSetPtr nset) { |
|
84 xmlSecNodeSetPtr tmp; |
|
85 |
|
86 xmlSecAssert(nset != NULL); |
|
87 |
|
88 while((tmp = nset) != NULL) { |
|
89 if((nset->next != NULL) && (nset->next != nset)) { |
|
90 nset->next->prev = nset->prev; |
|
91 nset->prev->next = nset->next; |
|
92 nset = nset->next; |
|
93 } else { |
|
94 nset = NULL; |
|
95 } |
|
96 |
|
97 if(tmp->nodes != NULL) { |
|
98 xmlXPathFreeNodeSet(tmp->nodes); |
|
99 } |
|
100 if(tmp->children != NULL) { |
|
101 xmlSecNodeSetDestroy(tmp->children); |
|
102 } |
|
103 if((tmp->doc != NULL) && (tmp->destroyDoc != 0)) { |
|
104 xmlFreeDoc(tmp->doc); |
|
105 } |
|
106 memset(tmp, 0, sizeof(xmlSecNodeSet)); |
|
107 xmlFree(tmp); |
|
108 } |
|
109 } |
|
110 |
|
111 /** |
|
112 * xmlSecNodeSetDocDestroy: |
|
113 * @nset: the pointer to node set. |
|
114 * |
|
115 * Instructs node set to destroy nodes parent doc when node set is destroyed. |
|
116 */ |
|
117 EXPORT_C |
|
118 void |
|
119 xmlSecNodeSetDocDestroy(xmlSecNodeSetPtr nset) { |
|
120 xmlSecAssert(nset != NULL); |
|
121 |
|
122 nset->destroyDoc = 1; |
|
123 } |
|
124 |
|
125 static int |
|
126 xmlSecNodeSetOneContains(xmlSecNodeSetPtr nset, xmlNodePtr node, xmlNodePtr parent) { |
|
127 int in_nodes_set = 1; |
|
128 |
|
129 xmlSecAssert2(nset != NULL, 0); |
|
130 xmlSecAssert2(node != NULL, 0); |
|
131 |
|
132 /* special cases: */ |
|
133 switch(nset->type) { |
|
134 case xmlSecNodeSetTreeWithoutComments: |
|
135 case xmlSecNodeSetTreeWithoutCommentsInvert: |
|
136 if(node->type == XML_COMMENT_NODE) { |
|
137 return(0); |
|
138 } |
|
139 break; |
|
140 case xmlSecNodeSetList: |
|
141 return(xmlSecNodeSetContains(nset->children, node, parent)); |
|
142 default: |
|
143 break; |
|
144 } |
|
145 |
|
146 if(nset->nodes != NULL) { |
|
147 if(node->type != XML_NAMESPACE_DECL) { |
|
148 in_nodes_set = xmlXPathNodeSetContains(nset->nodes, node); |
|
149 } else { |
|
150 xmlNs ns; |
|
151 |
|
152 memcpy(&ns, node, sizeof(ns)); |
|
153 |
|
154 if((parent != NULL) && (parent->type == XML_ATTRIBUTE_NODE)) { |
|
155 ns.next = (xmlNsPtr)parent->parent; |
|
156 } else { |
|
157 ns.next = (xmlNsPtr)parent; |
|
158 } |
|
159 |
|
160 /* |
|
161 * If the input is an XPath node-set, then the node-set must explicitly |
|
162 * contain every node to be rendered to the canonical form. |
|
163 */ |
|
164 in_nodes_set = (xmlXPathNodeSetContains(nset->nodes, (xmlNodePtr)&ns)); |
|
165 } |
|
166 } |
|
167 |
|
168 switch(nset->type) { |
|
169 case xmlSecNodeSetNormal: |
|
170 return(in_nodes_set); |
|
171 case xmlSecNodeSetInvert: |
|
172 return(!in_nodes_set); |
|
173 case xmlSecNodeSetTree: |
|
174 case xmlSecNodeSetTreeWithoutComments: |
|
175 if(in_nodes_set) { |
|
176 return(1); |
|
177 } |
|
178 if((parent != NULL) && (parent->type == XML_ELEMENT_NODE)) { |
|
179 return(xmlSecNodeSetOneContains(nset, parent, parent->parent)); |
|
180 } |
|
181 return(0); |
|
182 case xmlSecNodeSetTreeInvert: |
|
183 case xmlSecNodeSetTreeWithoutCommentsInvert: |
|
184 if(in_nodes_set) { |
|
185 return(0); |
|
186 } |
|
187 if((parent != NULL) && (parent->type == XML_ELEMENT_NODE)) { |
|
188 return(xmlSecNodeSetOneContains(nset, parent, parent->parent)); |
|
189 } |
|
190 return(1); |
|
191 default: |
|
192 xmlSecError(XMLSEC_ERRORS_HERE, |
|
193 NULL, |
|
194 NULL, |
|
195 XMLSEC_ERRORS_R_INVALID_TYPE, |
|
196 "type=%d", nset->type); |
|
197 } |
|
198 |
|
199 return(0); |
|
200 } |
|
201 |
|
202 /** |
|
203 * xmlSecNodeSetContains: |
|
204 * @nset: the pointer to node set. |
|
205 * @node: the pointer to XML node to check. |
|
206 * @parent: the pointer to @node parent node. |
|
207 * |
|
208 * Checks whether the @node is in the nodes set or not. |
|
209 * |
|
210 * Returns 1 if the @node is in the nodes set @nset, 0 if it is not |
|
211 * and a negative value if an error occurs. |
|
212 */ |
|
213 EXPORT_C |
|
214 int |
|
215 xmlSecNodeSetContains(xmlSecNodeSetPtr nset, xmlNodePtr node, xmlNodePtr parent) { |
|
216 int status = 1; |
|
217 xmlSecNodeSetPtr cur; |
|
218 |
|
219 xmlSecAssert2(node != NULL, 0); |
|
220 |
|
221 /* special cases: */ |
|
222 if(nset == NULL) { |
|
223 return(1); |
|
224 } |
|
225 |
|
226 status = 1; |
|
227 cur = nset; |
|
228 do { |
|
229 switch(cur->op) { |
|
230 case xmlSecNodeSetIntersection: |
|
231 if(status && !xmlSecNodeSetOneContains(cur, node, parent)) { |
|
232 status = 0; |
|
233 } |
|
234 break; |
|
235 case xmlSecNodeSetSubtraction: |
|
236 if(status && xmlSecNodeSetOneContains(cur, node, parent)) { |
|
237 status = 0; |
|
238 } |
|
239 break; |
|
240 case xmlSecNodeSetUnion: |
|
241 if(!status && xmlSecNodeSetOneContains(cur, node, parent)) { |
|
242 status = 1; |
|
243 } |
|
244 break; |
|
245 default: |
|
246 xmlSecError(XMLSEC_ERRORS_HERE, |
|
247 NULL, |
|
248 NULL, |
|
249 XMLSEC_ERRORS_R_INVALID_OPERATION, |
|
250 "operation=%d", cur->op); |
|
251 return(-1); |
|
252 } |
|
253 cur = cur->next; |
|
254 } while(cur != nset); |
|
255 |
|
256 return(status); |
|
257 } |
|
258 |
|
259 /** |
|
260 * xmlSecNodeSetAdd: |
|
261 * @nset: the pointer to currrent nodes set (or NULL). |
|
262 * @newNSet: the pointer to new nodes set. |
|
263 * @op: the operation type. |
|
264 * |
|
265 * Adds @newNSet to the @nset using operation @op. |
|
266 * |
|
267 * Returns the pointer to combined nodes set or NULL if an error |
|
268 * occurs. |
|
269 */ |
|
270 EXPORT_C |
|
271 xmlSecNodeSetPtr |
|
272 xmlSecNodeSetAdd(xmlSecNodeSetPtr nset, xmlSecNodeSetPtr newNSet, |
|
273 xmlSecNodeSetOp op) { |
|
274 xmlSecAssert2(newNSet != NULL, NULL); |
|
275 xmlSecAssert2(newNSet->next == newNSet, NULL); |
|
276 |
|
277 newNSet->op = op; |
|
278 if(nset == NULL) { |
|
279 return(newNSet); |
|
280 } |
|
281 |
|
282 newNSet->next = nset; |
|
283 newNSet->prev = nset->prev; |
|
284 nset->prev->next = newNSet; |
|
285 nset->prev = newNSet; |
|
286 return(nset); |
|
287 } |
|
288 |
|
289 /** |
|
290 * xmlSecNodeSetAddList: |
|
291 * @nset: the pointer to currrent nodes set (or NULL). |
|
292 * @newNSet: the pointer to new nodes set. |
|
293 * @op: the operation type. |
|
294 * |
|
295 * Adds @newNSet to the @nset as child using operation @op. |
|
296 * |
|
297 * Returns the pointer to combined nodes set or NULL if an error |
|
298 * occurs. |
|
299 */ |
|
300 EXPORT_C |
|
301 xmlSecNodeSetPtr |
|
302 xmlSecNodeSetAddList(xmlSecNodeSetPtr nset, xmlSecNodeSetPtr newNSet, xmlSecNodeSetOp op) { |
|
303 xmlSecNodeSetPtr tmp1, tmp2; |
|
304 |
|
305 xmlSecAssert2(newNSet != NULL, NULL); |
|
306 |
|
307 tmp1 = xmlSecNodeSetCreate(newNSet->doc, NULL, xmlSecNodeSetList); |
|
308 if(tmp1 == NULL) { |
|
309 xmlSecError(XMLSEC_ERRORS_HERE, |
|
310 NULL, |
|
311 "xmlSecNodeSetCreate", |
|
312 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
313 XMLSEC_ERRORS_NO_MESSAGE); |
|
314 return(NULL); |
|
315 } |
|
316 tmp1->children = newNSet; |
|
317 |
|
318 tmp2 = xmlSecNodeSetAdd(nset, tmp1, op); |
|
319 if(tmp2 == NULL) { |
|
320 xmlSecError(XMLSEC_ERRORS_HERE, |
|
321 NULL, |
|
322 "xmlSecNodeSetAdd", |
|
323 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
324 XMLSEC_ERRORS_NO_MESSAGE); |
|
325 xmlSecNodeSetDestroy(tmp1); |
|
326 return(NULL); |
|
327 } |
|
328 return(tmp2); |
|
329 } |
|
330 |
|
331 |
|
332 /** |
|
333 * xmlSecNodeSetWalk: |
|
334 * @nset: the pointer to node set. |
|
335 * @walkFunc: the callback functions. |
|
336 * @data: the application specific data passed to the @walkFunc. |
|
337 * |
|
338 * Calls the function @walkFunc once per each node in the nodes set @nset. |
|
339 * If the @walkFunc returns a negative value, then the walk procedure |
|
340 * is interrupted. |
|
341 * |
|
342 * Returns 0 on success or a negative value if an error occurs. |
|
343 */ |
|
344 EXPORT_C |
|
345 int |
|
346 xmlSecNodeSetWalk(xmlSecNodeSetPtr nset, xmlSecNodeSetWalkCallback walkFunc, void* data) { |
|
347 xmlNodePtr cur; |
|
348 int ret = 0; |
|
349 |
|
350 xmlSecAssert2(nset != NULL, -1); |
|
351 xmlSecAssert2(nset->doc != NULL, -1); |
|
352 xmlSecAssert2(walkFunc != NULL, -1); |
|
353 |
|
354 /* special cases */ |
|
355 if(nset->nodes != NULL) { |
|
356 int i; |
|
357 |
|
358 switch(nset->type) { |
|
359 case xmlSecNodeSetNormal: |
|
360 case xmlSecNodeSetTree: |
|
361 case xmlSecNodeSetTreeWithoutComments: |
|
362 for(i = 0; (ret >= 0) && (i < nset->nodes->nodeNr); ++i) { |
|
363 ret = xmlSecNodeSetWalkRecursive(nset, walkFunc, data, |
|
364 nset->nodes->nodeTab[i], |
|
365 xmlSecGetParent(nset->nodes->nodeTab[i])); |
|
366 } |
|
367 return(ret); |
|
368 default: |
|
369 break; |
|
370 } |
|
371 } |
|
372 |
|
373 for(cur = nset->doc->children; (cur != NULL) && (ret >= 0); cur = cur->next) { |
|
374 ret = xmlSecNodeSetWalkRecursive(nset, walkFunc, data, cur, xmlSecGetParent(cur)); |
|
375 } |
|
376 return(ret); |
|
377 } |
|
378 |
|
379 static int |
|
380 xmlSecNodeSetWalkRecursive(xmlSecNodeSetPtr nset, xmlSecNodeSetWalkCallback walkFunc, |
|
381 void* data, xmlNodePtr cur, xmlNodePtr parent) { |
|
382 int ret; |
|
383 |
|
384 xmlSecAssert2(nset != NULL, -1); |
|
385 xmlSecAssert2(cur != NULL, -1); |
|
386 xmlSecAssert2(walkFunc != NULL, -1); |
|
387 |
|
388 /* the node itself */ |
|
389 if(xmlSecNodeSetContains(nset, cur, parent)) { |
|
390 ret = walkFunc(nset, cur, parent, data); |
|
391 |
|
392 if(ret < 0) { |
|
393 return(ret); |
|
394 } |
|
395 } |
|
396 |
|
397 /* element node has attributes, namespaces */ |
|
398 if(cur->type == XML_ELEMENT_NODE) { |
|
399 xmlAttrPtr attr; |
|
400 xmlNodePtr node; |
|
401 xmlNsPtr ns, tmp; |
|
402 |
|
403 attr = (xmlAttrPtr)cur->properties; |
|
404 while(attr != NULL) { |
|
405 if(xmlSecNodeSetContains(nset, (xmlNodePtr)attr, cur)) { |
|
406 ret = walkFunc(nset, (xmlNodePtr)attr, cur, data); |
|
407 if(ret < 0) { |
|
408 return(ret); |
|
409 } |
|
410 } |
|
411 attr = attr->next; |
|
412 } |
|
413 |
|
414 node = cur; |
|
415 while(node != NULL) { |
|
416 ns = node->nsDef; |
|
417 while(ns != NULL) { |
|
418 tmp = xmlSearchNs(nset->doc, cur, ns->prefix); |
|
419 if((tmp == ns) && xmlSecNodeSetContains(nset, (xmlNodePtr)ns, cur)) { |
|
420 ret = walkFunc(nset, (xmlNodePtr)ns, cur, data); |
|
421 if(ret < 0) { |
|
422 return(ret); |
|
423 } |
|
424 } |
|
425 ns = ns->next; |
|
426 } |
|
427 node = node->parent; |
|
428 } |
|
429 } |
|
430 |
|
431 /* element and document nodes have children */ |
|
432 if((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_DOCUMENT_NODE)) { |
|
433 xmlNodePtr node; |
|
434 |
|
435 node = cur->children; |
|
436 while(node != NULL) { |
|
437 ret = xmlSecNodeSetWalkRecursive(nset, walkFunc, data, node, cur); |
|
438 if(ret < 0) { |
|
439 return(ret); |
|
440 } |
|
441 node = node->next; |
|
442 } |
|
443 } |
|
444 return(0); |
|
445 } |
|
446 |
|
447 /** |
|
448 * xmlSecNodeSetGetChildren: |
|
449 * @doc: the pointer to an XML document. |
|
450 * @parent: the pointer to parent XML node or NULL if we want to include all document nodes. |
|
451 * @withComments: the flag include comments or not. |
|
452 * @invert: the "invert" flag. |
|
453 * |
|
454 * Creates a new nodes set that contains: |
|
455 * - if @withComments is not 0 and @invert is 0: |
|
456 * all nodes in the @parent subtree; |
|
457 * - if @withComments is 0 and @invert is 0: |
|
458 * all nodes in the @parent subtree except comment nodes; |
|
459 * - if @withComments is not 0 and @invert not is 0: |
|
460 * all nodes in the @doc except nodes in the @parent subtree; |
|
461 * - if @withComments is 0 and @invert is 0: |
|
462 * all nodes in the @doc except nodes in the @parent subtree |
|
463 * and comment nodes. |
|
464 * |
|
465 * Returns pointer to the newly created #xmlSecNodeSet structure |
|
466 * or NULL if an error occurs. |
|
467 */ |
|
468 EXPORT_C |
|
469 xmlSecNodeSetPtr |
|
470 xmlSecNodeSetGetChildren(xmlDocPtr doc, const xmlNodePtr parent, int withComments, int invert) { |
|
471 xmlNodeSetPtr nodes; |
|
472 xmlSecNodeSetType type; |
|
473 xmlSecNodeSetPtr result = NULL; |
|
474 |
|
475 xmlSecAssert2(doc != NULL, NULL); |
|
476 |
|
477 nodes = xmlXPathNodeSetCreate(parent); |
|
478 if(nodes == NULL) { |
|
479 xmlSecError(XMLSEC_ERRORS_HERE, |
|
480 NULL, |
|
481 "xmlXPathNodeSetCreate", |
|
482 XMLSEC_ERRORS_R_XML_FAILED, |
|
483 XMLSEC_ERRORS_NO_MESSAGE); |
|
484 return(NULL); |
|
485 } |
|
486 |
|
487 /* if parent is NULL then we add all the doc children */ |
|
488 if(parent == NULL) { |
|
489 xmlNodePtr cur; |
|
490 for(cur = doc->children; cur != NULL; cur = cur->next) { |
|
491 if(withComments || (cur->type != XML_COMMENT_NODE)) { |
|
492 xmlXPathNodeSetAdd(nodes, cur); |
|
493 } |
|
494 } |
|
495 } |
|
496 |
|
497 if(withComments && invert) { |
|
498 type = xmlSecNodeSetTreeInvert; |
|
499 } else if(withComments && !invert) { |
|
500 type = xmlSecNodeSetTree; |
|
501 } else if(!withComments && invert) { |
|
502 type = xmlSecNodeSetTreeWithoutCommentsInvert; |
|
503 } else { /* if(!withComments && !invert) */ |
|
504 type = xmlSecNodeSetTreeWithoutComments; |
|
505 } |
|
506 |
|
507 result = xmlSecNodeSetCreate(doc, nodes, type); |
|
508 if ( !result ) |
|
509 { |
|
510 xmlXPathFreeNodeSet( nodes ); |
|
511 } |
|
512 return result; |
|
513 } |
|
514 |
|
515 static int |
|
516 xmlSecNodeSetDumpTextNodesWalkCallback(xmlSecNodeSetPtr nset, xmlNodePtr cur, |
|
517 xmlNodePtr parent, |
|
518 void* data) { |
|
519 xmlSecAssert2(nset != NULL, -1); |
|
520 xmlSecAssert2(cur != NULL, -1); |
|
521 xmlSecAssert2(data != NULL, -1); |
|
522 |
|
523 if(cur->type == XML_TEXT_NODE) { |
|
524 xmlOutputBufferWriteString((xmlOutputBufferPtr)data, |
|
525 (char*)(cur->content)); |
|
526 } |
|
527 return(0); |
|
528 } |
|
529 |
|
530 /** |
|
531 * xmlSecNodeSetDumpTextNodes: |
|
532 * @nset: the pointer to node set. |
|
533 * @out: the output buffer. |
|
534 * |
|
535 * Dumps content of all the text nodes from @nset to @out. |
|
536 * |
|
537 * Returns 0 on success or a negative value otherwise. |
|
538 */ |
|
539 EXPORT_C |
|
540 int |
|
541 xmlSecNodeSetDumpTextNodes(xmlSecNodeSetPtr nset, xmlOutputBufferPtr out) { |
|
542 xmlSecAssert2(nset != NULL, -1); |
|
543 xmlSecAssert2(out != NULL, -1); |
|
544 |
|
545 return(xmlSecNodeSetWalk(nset, xmlSecNodeSetDumpTextNodesWalkCallback, out)); |
|
546 } |
|
547 |
|
548 /** |
|
549 * xmlSecNodeSetDebugDump: |
|
550 * @nset: the pointer to node set. |
|
551 * @output: the pointer to output FILE. |
|
552 * |
|
553 * Prints information about @nset to the @output. |
|
554 */ |
|
555 EXPORT_C |
|
556 void |
|
557 xmlSecNodeSetDebugDump(xmlSecNodeSetPtr nset, FILE *output) { |
|
558 int i, l; |
|
559 xmlNodePtr cur; |
|
560 |
|
561 xmlSecAssert(nset != NULL); |
|
562 xmlSecAssert(output != NULL); |
|
563 |
|
564 fprintf(output, "== Nodes set "); |
|
565 switch(nset->type) { |
|
566 case xmlSecNodeSetNormal: |
|
567 fprintf(output, "(xmlSecNodeSetNormal)\n"); |
|
568 break; |
|
569 case xmlSecNodeSetInvert: |
|
570 fprintf(output, "(xmlSecNodeSetInvert)\n"); |
|
571 break; |
|
572 case xmlSecNodeSetTree: |
|
573 fprintf(output, "(xmlSecNodeSetTree)\n"); |
|
574 break; |
|
575 case xmlSecNodeSetTreeWithoutComments: |
|
576 fprintf(output, "(xmlSecNodeSetTreeWithoutComments)\n"); |
|
577 break; |
|
578 case xmlSecNodeSetTreeInvert: |
|
579 fprintf(output, "(xmlSecNodeSetTreeInvert)\n"); |
|
580 break; |
|
581 case xmlSecNodeSetTreeWithoutCommentsInvert: |
|
582 fprintf(output, "(xmlSecNodeSetTreeWithoutCommentsInvert)\n"); |
|
583 break; |
|
584 case xmlSecNodeSetList: |
|
585 fprintf(output, "(xmlSecNodeSetList)\n"); |
|
586 fprintf(output, ">>>\n"); |
|
587 xmlSecNodeSetDebugDump(nset->children, output); |
|
588 fprintf(output, "<<<\n"); |
|
589 return; |
|
590 default: |
|
591 fprintf(output, "(unknown=%d)\n", nset->type); |
|
592 xmlSecError(XMLSEC_ERRORS_HERE, |
|
593 NULL, |
|
594 NULL, |
|
595 XMLSEC_ERRORS_R_INVALID_TYPE, |
|
596 "type=%d", nset->type); |
|
597 } |
|
598 |
|
599 l = xmlXPathNodeSetGetLength(nset->nodes); |
|
600 for(i = 0; i < l; ++i) { |
|
601 cur = xmlXPathNodeSetItem(nset->nodes, i); |
|
602 if(cur->type != XML_NAMESPACE_DECL) { |
|
603 fprintf(output, "%d: %s\n", cur->type, |
|
604 (cur->name) ? cur->name : BAD_CAST "null"); |
|
605 } else { |
|
606 xmlNsPtr ns = (xmlNsPtr)cur; |
|
607 fprintf(output, "%d: %s=%s (%s:%s)\n", cur->type, |
|
608 (ns->prefix) ? ns->prefix : BAD_CAST "null", |
|
609 (ns->href) ? ns->href : BAD_CAST "null", |
|
610 (((xmlNodePtr)ns->next)->ns && |
|
611 ((xmlNodePtr)ns->next)->ns->prefix) ? |
|
612 ((xmlNodePtr)ns->next)->ns->prefix : BAD_CAST "null", |
|
613 ((xmlNodePtr)ns->next)->name); |
|
614 } |
|
615 } |
|
616 } |