blob: 61097115d2457c0036ec2417d9ac1ffc77c1c03f [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * debugXML.c : This is a set of routines used for debugging the tree
3 * produced by the XML parser.
4 *
5 * See Copyright for the status of this software.
6 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00007 * Daniel Veillard <daniel@veillard.com>
Owen Taylor3473f882001-02-23 17:55:21 +00008 */
9
Daniel Veillard34ce8be2002-03-18 19:37:11 +000010#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +000011#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000012#ifdef LIBXML_DEBUG_ENABLED
13
Owen Taylor3473f882001-02-23 17:55:21 +000014#include <string.h>
15#ifdef HAVE_STDLIB_H
16#include <stdlib.h>
17#endif
18#ifdef HAVE_STRING_H
19#include <string.h>
20#endif
21#include <libxml/xmlmemory.h>
22#include <libxml/tree.h>
23#include <libxml/parser.h>
Daniel Veillard567e1b42001-08-01 15:53:47 +000024#include <libxml/parserInternals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000025#include <libxml/valid.h>
26#include <libxml/debugXML.h>
27#include <libxml/HTMLtree.h>
28#include <libxml/HTMLparser.h>
29#include <libxml/xmlerror.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000030#include <libxml/globals.h>
Daniel Veillard0ba59232002-02-10 13:20:39 +000031#include <libxml/xpathInternals.h>
Igor Zlatkovicc06bb622003-04-27 15:59:00 +000032#include <libxml/uri.h>
Owen Taylor3473f882001-02-23 17:55:21 +000033
Daniel Veillard5e2dace2001-07-18 19:30:27 +000034/**
35 * xmlDebugDumpString:
36 * @output: the FILE * for the output
37 * @str: the string
38 *
39 * Dumps informations about the string, shorten it if necessary
40 */
41void
42xmlDebugDumpString(FILE * output, const xmlChar * str)
43{
Owen Taylor3473f882001-02-23 17:55:21 +000044 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000045
Daniel Veillard7db38712002-02-07 16:39:11 +000046 if (output == NULL)
47 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +000048 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000049 fprintf(output, "(NULL)");
50 return;
Owen Taylor3473f882001-02-23 17:55:21 +000051 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000052 for (i = 0; i < 40; i++)
53 if (str[i] == 0)
54 return;
55 else if (IS_BLANK(str[i]))
56 fputc(' ', output);
57 else if (str[i] >= 0x80)
58 fprintf(output, "#%X", str[i]);
59 else
60 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000061 fprintf(output, "...");
62}
63
Daniel Veillard56a4cb82001-03-24 17:00:36 +000064static void
65xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000066 int i;
67 char shift[100];
68
69 for (i = 0;((i < depth) && (i < 25));i++)
70 shift[2 * i] = shift[2 * i + 1] = ' ';
71 shift[2 * i] = shift[2 * i + 1] = 0;
72
73 fprintf(output, shift);
74
Daniel Veillard5e926fa2002-01-22 21:44:25 +000075 if (dtd == NULL) {
76 fprintf(output, "DTD node is NULL\n");
77 return;
78 }
79
Owen Taylor3473f882001-02-23 17:55:21 +000080 if (dtd->type != XML_DTD_NODE) {
81 fprintf(output, "PBM: not a DTD\n");
82 return;
83 }
84 if (dtd->name != NULL)
85 fprintf(output, "DTD(%s)", dtd->name);
86 else
87 fprintf(output, "DTD");
88 if (dtd->ExternalID != NULL)
89 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
90 if (dtd->SystemID != NULL)
91 fprintf(output, ", SYSTEM %s", dtd->SystemID);
92 fprintf(output, "\n");
93 /*
94 * Do a bit of checking
95 */
96 if (dtd->parent == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000097 fprintf(output, "PBM: DTD has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +000098 if (dtd->doc == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000099 fprintf(output, "PBM: DTD has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000100 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000101 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000102 if (dtd->prev == NULL) {
103 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000104 fprintf(output, "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000105 } else {
106 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000107 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000108 }
109 if (dtd->next == NULL) {
110 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000111 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000112 } else {
113 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000114 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000115 }
116}
117
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000118static void
119xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000120 int i;
121 char shift[100];
122
123 for (i = 0;((i < depth) && (i < 25));i++)
124 shift[2 * i] = shift[2 * i + 1] = ' ';
125 shift[2 * i] = shift[2 * i + 1] = 0;
126
127 fprintf(output, shift);
128
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000129 if (attr == NULL) {
130 fprintf(output, "Attribute declaration is NULL\n");
131 return;
132 }
Owen Taylor3473f882001-02-23 17:55:21 +0000133 if (attr->type != XML_ATTRIBUTE_DECL) {
134 fprintf(output, "PBM: not a Attr\n");
135 return;
136 }
137 if (attr->name != NULL)
138 fprintf(output, "ATTRDECL(%s)", attr->name);
139 else
140 fprintf(output, "PBM ATTRDECL noname!!!");
141 if (attr->elem != NULL)
142 fprintf(output, " for %s", attr->elem);
143 else
144 fprintf(output, " PBM noelem!!!");
145 switch (attr->atype) {
146 case XML_ATTRIBUTE_CDATA:
147 fprintf(output, " CDATA");
148 break;
149 case XML_ATTRIBUTE_ID:
150 fprintf(output, " ID");
151 break;
152 case XML_ATTRIBUTE_IDREF:
153 fprintf(output, " IDREF");
154 break;
155 case XML_ATTRIBUTE_IDREFS:
156 fprintf(output, " IDREFS");
157 break;
158 case XML_ATTRIBUTE_ENTITY:
159 fprintf(output, " ENTITY");
160 break;
161 case XML_ATTRIBUTE_ENTITIES:
162 fprintf(output, " ENTITIES");
163 break;
164 case XML_ATTRIBUTE_NMTOKEN:
165 fprintf(output, " NMTOKEN");
166 break;
167 case XML_ATTRIBUTE_NMTOKENS:
168 fprintf(output, " NMTOKENS");
169 break;
170 case XML_ATTRIBUTE_ENUMERATION:
171 fprintf(output, " ENUMERATION");
172 break;
173 case XML_ATTRIBUTE_NOTATION:
174 fprintf(output, " NOTATION ");
175 break;
176 }
177 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000178 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000179 xmlEnumerationPtr cur = attr->tree;
180
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000181 for (indx = 0;indx < 5; indx++) {
182 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000183 fprintf(output, "|%s", cur->name);
184 else
185 fprintf(output, " (%s", cur->name);
186 cur = cur->next;
187 if (cur == NULL) break;
188 }
189 if (cur == NULL)
190 fprintf(output, ")");
191 else
192 fprintf(output, "...)");
193 }
194 switch (attr->def) {
195 case XML_ATTRIBUTE_NONE:
196 break;
197 case XML_ATTRIBUTE_REQUIRED:
198 fprintf(output, " REQUIRED");
199 break;
200 case XML_ATTRIBUTE_IMPLIED:
201 fprintf(output, " IMPLIED");
202 break;
203 case XML_ATTRIBUTE_FIXED:
204 fprintf(output, " FIXED");
205 break;
206 }
207 if (attr->defaultValue != NULL) {
208 fprintf(output, "\"");
209 xmlDebugDumpString(output, attr->defaultValue);
210 fprintf(output, "\"");
211 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000212 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000213
214 /*
215 * Do a bit of checking
216 */
217 if (attr->parent == NULL)
218 fprintf(output, "PBM: Attr has no parent\n");
219 if (attr->doc == NULL)
220 fprintf(output, "PBM: Attr has no doc\n");
221 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
222 fprintf(output, "PBM: Attr doc differs from parent's one\n");
223 if (attr->prev == NULL) {
224 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
225 fprintf(output, "PBM: Attr has no prev and not first of list\n");
226 } else {
227 if (attr->prev->next != (xmlNodePtr) attr)
228 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
229 }
230 if (attr->next == NULL) {
231 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
232 fprintf(output, "PBM: Attr has no next and not last of list\n");
233 } else {
234 if (attr->next->prev != (xmlNodePtr) attr)
235 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
236 }
237}
238
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000239static void
240xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000241 int i;
242 char shift[100];
243
244 for (i = 0;((i < depth) && (i < 25));i++)
245 shift[2 * i] = shift[2 * i + 1] = ' ';
246 shift[2 * i] = shift[2 * i + 1] = 0;
247
248 fprintf(output, shift);
249
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000250 if (elem == NULL) {
251 fprintf(output, "Element declaration is NULL\n");
252 return;
253 }
Owen Taylor3473f882001-02-23 17:55:21 +0000254 if (elem->type != XML_ELEMENT_DECL) {
255 fprintf(output, "PBM: not a Elem\n");
256 return;
257 }
258 if (elem->name != NULL) {
259 fprintf(output, "ELEMDECL(");
260 xmlDebugDumpString(output, elem->name);
261 fprintf(output, ")");
262 } else
263 fprintf(output, "PBM ELEMDECL noname!!!");
264 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000265 case XML_ELEMENT_TYPE_UNDEFINED:
266 fprintf(output, ", UNDEFINED");
267 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000268 case XML_ELEMENT_TYPE_EMPTY:
269 fprintf(output, ", EMPTY");
270 break;
271 case XML_ELEMENT_TYPE_ANY:
272 fprintf(output, ", ANY");
273 break;
274 case XML_ELEMENT_TYPE_MIXED:
275 fprintf(output, ", MIXED ");
276 break;
277 case XML_ELEMENT_TYPE_ELEMENT:
278 fprintf(output, ", MIXED ");
279 break;
280 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000281 if ((elem->type != XML_ELEMENT_NODE) &&
282 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000283 char buf[5001];
284
285 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000286 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000287 buf[5000] = 0;
288 fprintf(output, "%s", buf);
289 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000290 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000291
292 /*
293 * Do a bit of checking
294 */
295 if (elem->parent == NULL)
296 fprintf(output, "PBM: Elem has no parent\n");
297 if (elem->doc == NULL)
298 fprintf(output, "PBM: Elem has no doc\n");
299 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
300 fprintf(output, "PBM: Elem doc differs from parent's one\n");
301 if (elem->prev == NULL) {
302 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
303 fprintf(output, "PBM: Elem has no prev and not first of list\n");
304 } else {
305 if (elem->prev->next != (xmlNodePtr) elem)
306 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
307 }
308 if (elem->next == NULL) {
309 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
310 fprintf(output, "PBM: Elem has no next and not last of list\n");
311 } else {
312 if (elem->next->prev != (xmlNodePtr) elem)
313 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
314 }
315}
316
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000317static void
318xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000319 int i;
320 char shift[100];
321
322 for (i = 0;((i < depth) && (i < 25));i++)
323 shift[2 * i] = shift[2 * i + 1] = ' ';
324 shift[2 * i] = shift[2 * i + 1] = 0;
325
326 fprintf(output, shift);
327
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000328 if (ent == NULL) {
329 fprintf(output, "Entity declaration is NULL\n");
330 return;
331 }
Owen Taylor3473f882001-02-23 17:55:21 +0000332 if (ent->type != XML_ENTITY_DECL) {
333 fprintf(output, "PBM: not a Entity decl\n");
334 return;
335 }
336 if (ent->name != NULL) {
337 fprintf(output, "ENTITYDECL(");
338 xmlDebugDumpString(output, ent->name);
339 fprintf(output, ")");
340 } else
341 fprintf(output, "PBM ENTITYDECL noname!!!");
342 switch (ent->etype) {
343 case XML_INTERNAL_GENERAL_ENTITY:
344 fprintf(output, ", internal\n");
345 break;
346 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
347 fprintf(output, ", external parsed\n");
348 break;
349 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
350 fprintf(output, ", unparsed\n");
351 break;
352 case XML_INTERNAL_PARAMETER_ENTITY:
353 fprintf(output, ", parameter\n");
354 break;
355 case XML_EXTERNAL_PARAMETER_ENTITY:
356 fprintf(output, ", external parameter\n");
357 break;
358 case XML_INTERNAL_PREDEFINED_ENTITY:
359 fprintf(output, ", predefined\n");
360 break;
361 }
362 if (ent->ExternalID) {
363 fprintf(output, shift);
364 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
365 }
366 if (ent->SystemID) {
367 fprintf(output, shift);
368 fprintf(output, " SystemID=%s\n", ent->SystemID);
369 }
370 if (ent->URI != NULL) {
371 fprintf(output, shift);
372 fprintf(output, " URI=%s\n", ent->URI);
373 }
374 if (ent->content) {
375 fprintf(output, shift);
376 fprintf(output, " content=");
377 xmlDebugDumpString(output, ent->content);
378 fprintf(output, "\n");
379 }
380
381 /*
382 * Do a bit of checking
383 */
384 if (ent->parent == NULL)
385 fprintf(output, "PBM: Ent has no parent\n");
386 if (ent->doc == NULL)
387 fprintf(output, "PBM: Ent has no doc\n");
388 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
389 fprintf(output, "PBM: Ent doc differs from parent's one\n");
390 if (ent->prev == NULL) {
391 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
392 fprintf(output, "PBM: Ent has no prev and not first of list\n");
393 } else {
394 if (ent->prev->next != (xmlNodePtr) ent)
395 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
396 }
397 if (ent->next == NULL) {
398 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
399 fprintf(output, "PBM: Ent has no next and not last of list\n");
400 } else {
401 if (ent->next->prev != (xmlNodePtr) ent)
402 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
403 }
404}
405
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000406static void
407xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000408 int i;
409 char shift[100];
410
411 for (i = 0;((i < depth) && (i < 25));i++)
412 shift[2 * i] = shift[2 * i + 1] = ' ';
413 shift[2 * i] = shift[2 * i + 1] = 0;
414
415 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000416
417 if (ns == NULL) {
418 fprintf(output, "namespace node is NULL\n");
419 return;
420 }
Owen Taylor3473f882001-02-23 17:55:21 +0000421 if (ns->type != XML_NAMESPACE_DECL) {
422 fprintf(output, "invalid namespace node %d\n", ns->type);
423 return;
424 }
425 if (ns->href == NULL) {
426 if (ns->prefix != NULL)
427 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
428 else
429 fprintf(output, "incomplete default namespace href=NULL\n");
430 } else {
431 if (ns->prefix != NULL)
432 fprintf(output, "namespace %s href=", ns->prefix);
433 else
434 fprintf(output, "default namespace href=");
435
436 xmlDebugDumpString(output, ns->href);
437 fprintf(output, "\n");
438 }
439}
440
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000441static void
442xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000443 while (ns != NULL) {
444 xmlDebugDumpNamespace(output, ns, depth);
445 ns = ns->next;
446 }
447}
448
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000449static void
450xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000451 int i;
452 char shift[100];
453
454 for (i = 0;((i < depth) && (i < 25));i++)
455 shift[2 * i] = shift[2 * i + 1] = ' ';
456 shift[2 * i] = shift[2 * i + 1] = 0;
457
458 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000459
460 if (ent == NULL) {
461 fprintf(output, "Entity is NULL\n");
462 return;
463 }
Owen Taylor3473f882001-02-23 17:55:21 +0000464 switch (ent->etype) {
465 case XML_INTERNAL_GENERAL_ENTITY:
466 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
467 break;
468 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
469 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
470 break;
471 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
472 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
473 break;
474 case XML_INTERNAL_PARAMETER_ENTITY:
475 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
476 break;
477 case XML_EXTERNAL_PARAMETER_ENTITY:
478 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
479 break;
480 default:
481 fprintf(output, "ENTITY_%d ! ", ent->etype);
482 }
483 fprintf(output, "%s\n", ent->name);
484 if (ent->ExternalID) {
485 fprintf(output, shift);
486 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
487 }
488 if (ent->SystemID) {
489 fprintf(output, shift);
490 fprintf(output, "SystemID=%s\n", ent->SystemID);
491 }
492 if (ent->URI) {
493 fprintf(output, shift);
494 fprintf(output, "URI=%s\n", ent->URI);
495 }
496 if (ent->content) {
497 fprintf(output, shift);
498 fprintf(output, "content=");
499 xmlDebugDumpString(output, ent->content);
500 fprintf(output, "\n");
501 }
502}
503
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000504/**
505 * xmlDebugDumpAttr:
506 * @output: the FILE * for the output
507 * @attr: the attribute
508 * @depth: the indentation level.
509 *
510 * Dumps debug information for the attribute
511 */
512void
513xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000514 int i;
515 char shift[100];
516
517 for (i = 0;((i < depth) && (i < 25));i++)
518 shift[2 * i] = shift[2 * i + 1] = ' ';
519 shift[2 * i] = shift[2 * i + 1] = 0;
520
521 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000522
523 if (attr == NULL) {
524 fprintf(output, "Attr is NULL");
525 return;
526 }
Owen Taylor3473f882001-02-23 17:55:21 +0000527 fprintf(output, "ATTRIBUTE ");
528 xmlDebugDumpString(output, attr->name);
529 fprintf(output, "\n");
530 if (attr->children != NULL)
531 xmlDebugDumpNodeList(output, attr->children, depth + 1);
532
533 /*
534 * Do a bit of checking
535 */
536 if (attr->parent == NULL)
537 fprintf(output, "PBM: Attr has no parent\n");
538 if (attr->doc == NULL)
539 fprintf(output, "PBM: Attr has no doc\n");
540 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
541 fprintf(output, "PBM: Attr doc differs from parent's one\n");
542 if (attr->prev == NULL) {
543 if ((attr->parent != NULL) && (attr->parent->properties != attr))
544 fprintf(output, "PBM: Attr has no prev and not first of list\n");
545 } else {
546 if (attr->prev->next != attr)
547 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
548 }
549 if (attr->next != NULL) {
550 if (attr->next->prev != attr)
551 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
552 }
553}
554
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000555/**
556 * xmlDebugDumpAttrList:
557 * @output: the FILE * for the output
558 * @attr: the attribute list
559 * @depth: the indentation level.
560 *
561 * Dumps debug information for the attribute list
562 */
563void
564xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
565{
Daniel Veillard7db38712002-02-07 16:39:11 +0000566 if (output == NULL)
567 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000568 while (attr != NULL) {
569 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000570 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000571 }
572}
573
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000574/**
575 * xmlDebugDumpOneNode:
576 * @output: the FILE * for the output
577 * @node: the node
578 * @depth: the indentation level.
579 *
580 * Dumps debug information for the element node, it is not recursive
581 */
582void
583xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
584{
Owen Taylor3473f882001-02-23 17:55:21 +0000585 int i;
586 char shift[100];
587
Daniel Veillard7db38712002-02-07 16:39:11 +0000588 if (output == NULL)
589 output = stdout;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000590 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000591 shift[2 * i] = shift[2 * i + 1] = ' ';
592 shift[2 * i] = shift[2 * i + 1] = 0;
593
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000594 if (node == NULL) {
595 fprintf(output, shift);
596 fprintf(output, "node is NULL\n");
597 return;
598 }
Owen Taylor3473f882001-02-23 17:55:21 +0000599 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000600 case XML_ELEMENT_NODE:
601 fprintf(output, shift);
602 fprintf(output, "ELEMENT ");
603 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
604 xmlDebugDumpString(output, node->ns->prefix);
605 fprintf(output, ":");
606 }
607 xmlDebugDumpString(output, node->name);
608 fprintf(output, "\n");
609 break;
610 case XML_ATTRIBUTE_NODE:
611 fprintf(output, shift);
612 fprintf(output, "Error, ATTRIBUTE found here\n");
613 break;
614 case XML_TEXT_NODE:
615 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000616 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000617 fprintf(output, "TEXT no enc\n");
618 else
619 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000620 break;
621 case XML_CDATA_SECTION_NODE:
622 fprintf(output, shift);
623 fprintf(output, "CDATA_SECTION\n");
624 break;
625 case XML_ENTITY_REF_NODE:
626 fprintf(output, shift);
627 fprintf(output, "ENTITY_REF(%s)\n", node->name);
628 break;
629 case XML_ENTITY_NODE:
630 fprintf(output, shift);
631 fprintf(output, "ENTITY\n");
632 break;
633 case XML_PI_NODE:
634 fprintf(output, shift);
635 fprintf(output, "PI %s\n", node->name);
636 break;
637 case XML_COMMENT_NODE:
638 fprintf(output, shift);
639 fprintf(output, "COMMENT\n");
640 break;
641 case XML_DOCUMENT_NODE:
642 case XML_HTML_DOCUMENT_NODE:
643 fprintf(output, shift);
644 fprintf(output, "Error, DOCUMENT found here\n");
645 break;
646 case XML_DOCUMENT_TYPE_NODE:
647 fprintf(output, shift);
648 fprintf(output, "DOCUMENT_TYPE\n");
649 break;
650 case XML_DOCUMENT_FRAG_NODE:
651 fprintf(output, shift);
652 fprintf(output, "DOCUMENT_FRAG\n");
653 break;
654 case XML_NOTATION_NODE:
655 fprintf(output, shift);
656 fprintf(output, "NOTATION\n");
657 break;
658 case XML_DTD_NODE:
659 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
660 return;
661 case XML_ELEMENT_DECL:
662 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
663 return;
664 case XML_ATTRIBUTE_DECL:
665 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
666 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000667 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000668 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
669 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000670 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000671 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
672 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000673 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000674 fprintf(output, shift);
675 fprintf(output, "INCLUDE START\n");
676 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000677 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000678 fprintf(output, shift);
679 fprintf(output, "INCLUDE END\n");
680 return;
681 default:
682 fprintf(output, shift);
683 fprintf(output, "NODE_%d !!!\n", node->type);
684 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000685 }
686 if (node->doc == NULL) {
687 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000688 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000689 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000690 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000691 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
692 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000693 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000694 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000695 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
696 shift[2 * i] = shift[2 * i + 1] = ' ';
697 shift[2 * i + 2] = shift[2 * i + 3] = 0;
698 fprintf(output, shift);
699 fprintf(output, "content=");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000700 xmlDebugDumpString(output, node->content);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000701 fprintf(output, "\n");
702 }
Owen Taylor3473f882001-02-23 17:55:21 +0000703 } else {
704 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000705
706 ent = xmlGetDocEntity(node->doc, node->name);
707 if (ent != NULL)
708 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000709 }
710 /*
711 * Do a bit of checking
712 */
713 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000714 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000715 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000716 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000717 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000718 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000719 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000720 if ((node->parent != NULL) && (node->parent->children != node))
721 fprintf(output,
722 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000723 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000724 if (node->prev->next != node)
725 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000726 }
727 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000728 if ((node->parent != NULL) && (node->parent->last != node))
729 fprintf(output,
730 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000731 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000732 if (node->next->prev != node)
733 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000734 }
735}
736
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000737/**
738 * xmlDebugDumpNode:
739 * @output: the FILE * for the output
740 * @node: the node
741 * @depth: the indentation level.
742 *
743 * Dumps debug information for the element node, it is recursive
744 */
745void
746xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
747{
Daniel Veillard7db38712002-02-07 16:39:11 +0000748 if (output == NULL)
749 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000750 if (node == NULL) {
751 int i;
752 char shift[100];
753
754 for (i = 0; ((i < depth) && (i < 25)); i++)
755 shift[2 * i] = shift[2 * i + 1] = ' ';
756 shift[2 * i] = shift[2 * i + 1] = 0;
757
758 fprintf(output, shift);
759 fprintf(output, "node is NULL\n");
760 return;
761 }
Owen Taylor3473f882001-02-23 17:55:21 +0000762 xmlDebugDumpOneNode(output, node, depth);
763 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000764 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000765}
766
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000767/**
768 * xmlDebugDumpNodeList:
769 * @output: the FILE * for the output
770 * @node: the node list
771 * @depth: the indentation level.
772 *
773 * Dumps debug information for the list of element node, it is recursive
774 */
775void
776xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
777{
Daniel Veillard7db38712002-02-07 16:39:11 +0000778 if (output == NULL)
779 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000780 while (node != NULL) {
781 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000782 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000783 }
784}
785
786
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000787/**
788 * xmlDebugDumpDocumentHead:
789 * @output: the FILE * for the output
790 * @doc: the document
791 *
792 * Dumps debug information cncerning the document, not recursive
793 */
794void
795xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
796{
797 if (output == NULL)
798 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000799 if (doc == NULL) {
800 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000801 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000802 }
803
804 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000805 case XML_ELEMENT_NODE:
806 fprintf(output, "Error, ELEMENT found here ");
807 break;
808 case XML_ATTRIBUTE_NODE:
809 fprintf(output, "Error, ATTRIBUTE found here\n");
810 break;
811 case XML_TEXT_NODE:
812 fprintf(output, "Error, TEXT\n");
813 break;
814 case XML_CDATA_SECTION_NODE:
815 fprintf(output, "Error, CDATA_SECTION\n");
816 break;
817 case XML_ENTITY_REF_NODE:
818 fprintf(output, "Error, ENTITY_REF\n");
819 break;
820 case XML_ENTITY_NODE:
821 fprintf(output, "Error, ENTITY\n");
822 break;
823 case XML_PI_NODE:
824 fprintf(output, "Error, PI\n");
825 break;
826 case XML_COMMENT_NODE:
827 fprintf(output, "Error, COMMENT\n");
828 break;
829 case XML_DOCUMENT_NODE:
830 fprintf(output, "DOCUMENT\n");
831 break;
832 case XML_HTML_DOCUMENT_NODE:
833 fprintf(output, "HTML DOCUMENT\n");
834 break;
835 case XML_DOCUMENT_TYPE_NODE:
836 fprintf(output, "Error, DOCUMENT_TYPE\n");
837 break;
838 case XML_DOCUMENT_FRAG_NODE:
839 fprintf(output, "Error, DOCUMENT_FRAG\n");
840 break;
841 case XML_NOTATION_NODE:
842 fprintf(output, "Error, NOTATION\n");
843 break;
844 default:
845 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000846 }
847 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000848 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000849 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000850 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000851 }
852 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000853 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000854 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000855 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000856 }
857 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000858 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000859 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000860 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000861 }
862 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000863 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000864 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000865 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000866 }
867 if (doc->standalone)
868 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000869 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000870 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
871}
872
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000873/**
874 * xmlDebugDumpDocument:
875 * @output: the FILE * for the output
876 * @doc: the document
877 *
878 * Dumps debug information for the document, it's recursive
879 */
880void
881xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
882{
883 if (output == NULL)
884 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000885 if (doc == NULL) {
886 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000887 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000888 }
889 xmlDebugDumpDocumentHead(output, doc);
890 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000891 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000892 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000893}
Owen Taylor3473f882001-02-23 17:55:21 +0000894
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000895/**
896 * xmlDebugDumpDTD:
897 * @output: the FILE * for the output
898 * @dtd: the DTD
899 *
900 * Dumps debug information for the DTD
901 */
902void
903xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
904{
Daniel Veillard7db38712002-02-07 16:39:11 +0000905 if (output == NULL)
906 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000907 if (dtd == NULL) {
908 fprintf(output, "DTD is NULL\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000909 return;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000910 }
Owen Taylor3473f882001-02-23 17:55:21 +0000911 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000912 fprintf(output, "PBM: not a DTD\n");
913 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000914 }
915 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000916 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000917 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000918 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000919 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000920 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000921 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000922 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000923 fprintf(output, "\n");
924 /*
925 * Do a bit of checking
926 */
927 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000928 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000929 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000930 if ((dtd->parent != NULL)
931 && (dtd->parent->children != (xmlNodePtr) dtd))
932 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000933 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000934 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000935 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000936 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000937 }
938 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000939 if ((dtd->parent != NULL)
940 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000941 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000942 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000943 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000944 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000945 }
946 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000947 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000948 else
949 xmlDebugDumpNodeList(output, dtd->children, 1);
950}
951
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000952static void
953xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000954 if (cur == NULL) {
955 fprintf(output, "Entity is NULL");
956 return;
957 }
Owen Taylor3473f882001-02-23 17:55:21 +0000958 fprintf(output, "%s : ", cur->name);
959 switch (cur->etype) {
960 case XML_INTERNAL_GENERAL_ENTITY:
961 fprintf(output, "INTERNAL GENERAL, ");
962 break;
963 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
964 fprintf(output, "EXTERNAL PARSED, ");
965 break;
966 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
967 fprintf(output, "EXTERNAL UNPARSED, ");
968 break;
969 case XML_INTERNAL_PARAMETER_ENTITY:
970 fprintf(output, "INTERNAL PARAMETER, ");
971 break;
972 case XML_EXTERNAL_PARAMETER_ENTITY:
973 fprintf(output, "EXTERNAL PARAMETER, ");
974 break;
975 default:
976 fprintf(output, "UNKNOWN TYPE %d",
977 cur->etype);
978 }
979 if (cur->ExternalID != NULL)
980 fprintf(output, "ID \"%s\"", cur->ExternalID);
981 if (cur->SystemID != NULL)
982 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
983 if (cur->orig != NULL)
984 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000985 if ((cur->type != XML_ELEMENT_NODE) &&
986 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000987 fprintf(output, "\n content \"%s\"", cur->content);
988 fprintf(output, "\n");
989}
990
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000991/**
992 * xmlDebugDumpEntities:
993 * @output: the FILE * for the output
994 * @doc: the document
995 *
996 * Dumps debug information for all the entities in use by the document
997 */
998void
999xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1000{
1001 if (output == NULL)
1002 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001003 if (doc == NULL) {
1004 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001005 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001006 }
1007
1008 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001009 case XML_ELEMENT_NODE:
1010 fprintf(output, "Error, ELEMENT found here ");
1011 break;
1012 case XML_ATTRIBUTE_NODE:
1013 fprintf(output, "Error, ATTRIBUTE found here\n");
1014 break;
1015 case XML_TEXT_NODE:
1016 fprintf(output, "Error, TEXT\n");
1017 break;
1018 case XML_CDATA_SECTION_NODE:
1019 fprintf(output, "Error, CDATA_SECTION\n");
1020 break;
1021 case XML_ENTITY_REF_NODE:
1022 fprintf(output, "Error, ENTITY_REF\n");
1023 break;
1024 case XML_ENTITY_NODE:
1025 fprintf(output, "Error, ENTITY\n");
1026 break;
1027 case XML_PI_NODE:
1028 fprintf(output, "Error, PI\n");
1029 break;
1030 case XML_COMMENT_NODE:
1031 fprintf(output, "Error, COMMENT\n");
1032 break;
1033 case XML_DOCUMENT_NODE:
1034 fprintf(output, "DOCUMENT\n");
1035 break;
1036 case XML_HTML_DOCUMENT_NODE:
1037 fprintf(output, "HTML DOCUMENT\n");
1038 break;
1039 case XML_DOCUMENT_TYPE_NODE:
1040 fprintf(output, "Error, DOCUMENT_TYPE\n");
1041 break;
1042 case XML_DOCUMENT_FRAG_NODE:
1043 fprintf(output, "Error, DOCUMENT_FRAG\n");
1044 break;
1045 case XML_NOTATION_NODE:
1046 fprintf(output, "Error, NOTATION\n");
1047 break;
1048 default:
1049 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +00001050 }
1051 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001052 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1053 doc->intSubset->entities;
1054
1055 fprintf(output, "Entities in internal subset\n");
1056 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1057 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001058 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001059 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001060 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001061 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1062 doc->extSubset->entities;
1063
1064 fprintf(output, "Entities in external subset\n");
1065 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1066 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001067 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001068 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001069}
1070
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001071/**
1072 * xmlLsCountNode:
1073 * @node: the node to count
1074 *
1075 * Count the children of @node.
1076 *
1077 * Returns the number of children of @node.
1078 */
1079int
1080xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001081 int ret = 0;
1082 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001083
1084 if (node == NULL)
1085 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001086
1087 switch (node->type) {
1088 case XML_ELEMENT_NODE:
1089 list = node->children;
1090 break;
1091 case XML_DOCUMENT_NODE:
1092 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001093#ifdef LIBXML_DOCB_ENABLED
1094 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001095#endif
1096 list = ((xmlDocPtr) node)->children;
1097 break;
1098 case XML_ATTRIBUTE_NODE:
1099 list = ((xmlAttrPtr) node)->children;
1100 break;
1101 case XML_TEXT_NODE:
1102 case XML_CDATA_SECTION_NODE:
1103 case XML_PI_NODE:
1104 case XML_COMMENT_NODE:
1105 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001106 ret = xmlStrlen(node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001107 }
1108 break;
1109 case XML_ENTITY_REF_NODE:
1110 case XML_DOCUMENT_TYPE_NODE:
1111 case XML_ENTITY_NODE:
1112 case XML_DOCUMENT_FRAG_NODE:
1113 case XML_NOTATION_NODE:
1114 case XML_DTD_NODE:
1115 case XML_ELEMENT_DECL:
1116 case XML_ATTRIBUTE_DECL:
1117 case XML_ENTITY_DECL:
1118 case XML_NAMESPACE_DECL:
1119 case XML_XINCLUDE_START:
1120 case XML_XINCLUDE_END:
1121 ret = 1;
1122 break;
1123 }
1124 for (;list != NULL;ret++)
1125 list = list->next;
1126 return(ret);
1127}
1128
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001129/**
1130 * xmlLsOneNode:
1131 * @output: the FILE * for the output
1132 * @node: the node to dump
1133 *
1134 * Dump to @output the type and name of @node.
1135 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001136void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001137xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001138 if (node == NULL) {
1139 fprintf(output, "NULL\n");
1140 return;
1141 }
Owen Taylor3473f882001-02-23 17:55:21 +00001142 switch (node->type) {
1143 case XML_ELEMENT_NODE:
1144 fprintf(output, "-");
1145 break;
1146 case XML_ATTRIBUTE_NODE:
1147 fprintf(output, "a");
1148 break;
1149 case XML_TEXT_NODE:
1150 fprintf(output, "t");
1151 break;
1152 case XML_CDATA_SECTION_NODE:
Daniel Veillard75be0132002-03-13 10:03:35 +00001153 fprintf(output, "C");
Owen Taylor3473f882001-02-23 17:55:21 +00001154 break;
1155 case XML_ENTITY_REF_NODE:
1156 fprintf(output, "e");
1157 break;
1158 case XML_ENTITY_NODE:
1159 fprintf(output, "E");
1160 break;
1161 case XML_PI_NODE:
1162 fprintf(output, "p");
1163 break;
1164 case XML_COMMENT_NODE:
1165 fprintf(output, "c");
1166 break;
1167 case XML_DOCUMENT_NODE:
1168 fprintf(output, "d");
1169 break;
1170 case XML_HTML_DOCUMENT_NODE:
1171 fprintf(output, "h");
1172 break;
1173 case XML_DOCUMENT_TYPE_NODE:
1174 fprintf(output, "T");
1175 break;
1176 case XML_DOCUMENT_FRAG_NODE:
1177 fprintf(output, "F");
1178 break;
1179 case XML_NOTATION_NODE:
1180 fprintf(output, "N");
1181 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001182 case XML_NAMESPACE_DECL:
1183 fprintf(output, "n");
1184 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001185 default:
1186 fprintf(output, "?");
1187 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001188 if (node->type != XML_NAMESPACE_DECL) {
1189 if (node->properties != NULL)
1190 fprintf(output, "a");
1191 else
1192 fprintf(output, "-");
1193 if (node->nsDef != NULL)
1194 fprintf(output, "n");
1195 else
1196 fprintf(output, "-");
1197 }
Owen Taylor3473f882001-02-23 17:55:21 +00001198
1199 fprintf(output, " %8d ", xmlLsCountNode(node));
1200
1201 switch (node->type) {
1202 case XML_ELEMENT_NODE:
1203 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001204 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001205 break;
1206 case XML_ATTRIBUTE_NODE:
1207 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001208 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001209 break;
1210 case XML_TEXT_NODE:
1211 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001212 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001213 }
1214 break;
1215 case XML_CDATA_SECTION_NODE:
1216 break;
1217 case XML_ENTITY_REF_NODE:
1218 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001219 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001220 break;
1221 case XML_ENTITY_NODE:
1222 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001223 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001224 break;
1225 case XML_PI_NODE:
1226 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001227 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001228 break;
1229 case XML_COMMENT_NODE:
1230 break;
1231 case XML_DOCUMENT_NODE:
1232 break;
1233 case XML_HTML_DOCUMENT_NODE:
1234 break;
1235 case XML_DOCUMENT_TYPE_NODE:
1236 break;
1237 case XML_DOCUMENT_FRAG_NODE:
1238 break;
1239 case XML_NOTATION_NODE:
1240 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001241 case XML_NAMESPACE_DECL: {
1242 xmlNsPtr ns = (xmlNsPtr) node;
1243
1244 if (ns->prefix == NULL)
1245 fprintf(output, "default -> %s", ns->href);
1246 else
1247 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1248 break;
1249 }
Owen Taylor3473f882001-02-23 17:55:21 +00001250 default:
1251 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001252 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001253 }
1254 fprintf(output, "\n");
1255}
1256
Daniel Veillard78d12092001-10-11 09:12:24 +00001257/**
1258 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001259 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001260 *
1261 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001262 *
1263 * Returns a pointer to either "True" or "False"
1264 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001265const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001266xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001267{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001268 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001269 return("True");
1270 else
1271 return("False");
1272}
1273
Owen Taylor3473f882001-02-23 17:55:21 +00001274/****************************************************************
1275 * *
1276 * The XML shell related functions *
1277 * *
1278 ****************************************************************/
1279
Daniel Veillard78d12092001-10-11 09:12:24 +00001280
1281
Owen Taylor3473f882001-02-23 17:55:21 +00001282/*
1283 * TODO: Improvement/cleanups for the XML shell
1284 * - allow to shell out an editor on a subpart
1285 * - cleanup function registrations (with help) and calling
1286 * - provide registration routines
1287 */
1288
1289/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001290 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001291 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001292 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001293 *
1294 * Print the xpath error to libxml default error channel
1295 */
1296void
1297xmlShellPrintXPathError(int errorType, const char *arg)
1298{
1299 const char *default_arg = "Result";
1300
1301 if (!arg)
1302 arg = default_arg;
1303
1304 switch (errorType) {
1305 case XPATH_UNDEFINED:
1306 xmlGenericError(xmlGenericErrorContext,
1307 "%s: no such node\n", arg);
1308 break;
1309
1310 case XPATH_BOOLEAN:
1311 xmlGenericError(xmlGenericErrorContext,
1312 "%s is a Boolean\n", arg);
1313 break;
1314 case XPATH_NUMBER:
1315 xmlGenericError(xmlGenericErrorContext,
1316 "%s is a number\n", arg);
1317 break;
1318 case XPATH_STRING:
1319 xmlGenericError(xmlGenericErrorContext,
1320 "%s is a string\n", arg);
1321 break;
1322 case XPATH_POINT:
1323 xmlGenericError(xmlGenericErrorContext,
1324 "%s is a point\n", arg);
1325 break;
1326 case XPATH_RANGE:
1327 xmlGenericError(xmlGenericErrorContext,
1328 "%s is a range\n", arg);
1329 break;
1330 case XPATH_LOCATIONSET:
1331 xmlGenericError(xmlGenericErrorContext,
1332 "%s is a range\n", arg);
1333 break;
1334 case XPATH_USERS:
1335 xmlGenericError(xmlGenericErrorContext,
1336 "%s is user-defined\n", arg);
1337 break;
1338 case XPATH_XSLT_TREE:
1339 xmlGenericError(xmlGenericErrorContext,
1340 "%s is an XSLT value tree\n", arg);
1341 break;
1342 }
1343 xmlGenericError(xmlGenericErrorContext,
1344 "Try casting the result string function (xpath builtin)\n",
1345 arg);
1346}
1347
1348
1349/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001350 * xmlShellPrintNodeCtxt:
1351 * @ctxt : a non-null shell context
1352 * @node : a non-null node to print to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001353 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001354 * Print node to the output FILE
1355 */
1356static void
1357xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1358{
Daniel Veillard01992e02002-10-09 10:20:30 +00001359 FILE *fp;
1360
1361 if (!node)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001362 return;
Daniel Veillard01992e02002-10-09 10:20:30 +00001363 if (ctxt == NULL)
1364 fp = stdout;
1365 else
1366 fp = ctxt->output;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001367
1368 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001369 xmlDocDump(fp, (xmlDocPtr) node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001370 else if (node->type == XML_ATTRIBUTE_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001371 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001372 else
Daniel Veillard01992e02002-10-09 10:20:30 +00001373 xmlElemDump(fp, node->doc, node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001374
Daniel Veillard01992e02002-10-09 10:20:30 +00001375 fprintf(fp, "\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00001376}
1377
1378/**
1379 * xmlShellPrintNode:
1380 * @node : a non-null node to print to the output FILE
1381 *
1382 * Print node to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001383 */
1384void
1385xmlShellPrintNode(xmlNodePtr node)
1386{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001387 xmlShellPrintNodeCtxt(NULL, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001388}
1389
Daniel Veillard78d12092001-10-11 09:12:24 +00001390/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001391 * xmlShellPrintXPathResultCtxt:
1392 * @ctxt: a valid shell context
Daniel Veillard9d06d302002-01-22 18:15:52 +00001393 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001394 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001395 * Prints result to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001396 */
Daniel Veillard321be0c2002-10-08 21:26:42 +00001397static void
1398xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
Daniel Veillard78d12092001-10-11 09:12:24 +00001399{
1400 int i = 0;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001401 if (!ctxt)
1402 return;
Daniel Veillard78d12092001-10-11 09:12:24 +00001403
1404 if (list != NULL) {
1405 switch (list->type) {
1406 case XPATH_NODESET:{
1407 int indx;
1408
1409 if (list->nodesetval) {
1410 for (indx = 0; indx < list->nodesetval->nodeNr;
1411 indx++) {
1412 if (i > 0)
1413 fprintf(stderr, " -------\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00001414 xmlShellPrintNodeCtxt(ctxt,
1415 list->nodesetval->nodeTab[indx]);
Daniel Veillard78d12092001-10-11 09:12:24 +00001416 }
1417 } else {
1418 xmlGenericError(xmlGenericErrorContext,
1419 "Empty node set\n");
1420 }
1421 break;
1422 }
1423 case XPATH_BOOLEAN:
1424 xmlGenericError(xmlGenericErrorContext,
1425 "Is a Boolean:%s\n",
1426 xmlBoolToText(list->boolval));
1427 break;
1428 case XPATH_NUMBER:
1429 xmlGenericError(xmlGenericErrorContext,
1430 "Is a number:%0g\n", list->floatval);
1431 break;
1432 case XPATH_STRING:
1433 xmlGenericError(xmlGenericErrorContext,
1434 "Is a string:%s\n", list->stringval);
1435 break;
1436
1437 default:
1438 xmlShellPrintXPathError(list->type, NULL);
1439 }
1440 }
1441}
1442
1443/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001444 * xmlShellPrintXPathResult:
1445 * @list: a valid result generated by an xpath evaluation
1446 *
1447 * Prints result to the output FILE
1448 */
1449void
1450xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1451{
1452 xmlShellPrintXPathResultCtxt(NULL, list);
1453}
1454
1455/**
Owen Taylor3473f882001-02-23 17:55:21 +00001456 * xmlShellList:
1457 * @ctxt: the shell context
1458 * @arg: unused
1459 * @node: a node
1460 * @node2: unused
1461 *
1462 * Implements the XML shell function "ls"
1463 * Does an Unix like listing of the given node (like a directory)
1464 *
1465 * Returns 0
1466 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001467int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001468xmlShellList(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001469 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1470 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1471{
Owen Taylor3473f882001-02-23 17:55:21 +00001472 xmlNodePtr cur;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001473 if (!ctxt)
1474 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001475 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001476 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001477 return (0);
1478 }
Owen Taylor3473f882001-02-23 17:55:21 +00001479 if ((node->type == XML_DOCUMENT_NODE) ||
1480 (node->type == XML_HTML_DOCUMENT_NODE)) {
1481 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001482 } else if (node->type == XML_NAMESPACE_DECL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001483 xmlLsOneNode(ctxt->output, node);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001484 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001485 } else if (node->children != NULL) {
1486 cur = node->children;
1487 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001488 xmlLsOneNode(ctxt->output, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001489 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001490 }
1491 while (cur != NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001492 xmlLsOneNode(ctxt->output, cur);
Daniel Veillard78d12092001-10-11 09:12:24 +00001493 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001494 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001495 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001496}
1497
1498/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001499 * xmlShellBase:
1500 * @ctxt: the shell context
1501 * @arg: unused
1502 * @node: a node
1503 * @node2: unused
1504 *
1505 * Implements the XML shell function "base"
1506 * dumps the current XML base of the node
1507 *
1508 * Returns 0
1509 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001510int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001511xmlShellBase(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001512 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1513 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1514{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001515 xmlChar *base;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001516 if (!ctxt)
1517 return 0;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001518 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001519 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001520 return (0);
1521 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001522
1523 base = xmlNodeGetBase(node->doc, node);
1524
1525 if (base == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001526 fprintf(ctxt->output, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001527 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001528 fprintf(ctxt->output, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001529 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001530 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001531 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001532}
1533
1534/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001535 * xmlShellSetBase:
1536 * @ctxt: the shell context
1537 * @arg: the new base
1538 * @node: a node
1539 * @node2: unused
1540 *
1541 * Implements the XML shell function "setbase"
1542 * change the current XML base of the node
1543 *
1544 * Returns 0
1545 */
1546static int
1547xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1548 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1549 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1550{
1551 xmlNodeSetBase(node, (xmlChar*) arg);
1552 return (0);
1553}
1554
1555/**
Daniel Veillard1e208222002-10-22 14:25:25 +00001556 * xmlShellGrep:
1557 * @ctxt: the shell context
1558 * @arg: the string or regular expression to find
1559 * @node: a node
1560 * @node2: unused
1561 *
1562 * Implements the XML shell function "grep"
1563 * dumps informations about the node (namespace, attributes, content).
1564 *
1565 * Returns 0
1566 */
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001567static int
Daniel Veillard1e208222002-10-22 14:25:25 +00001568xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1569 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1570{
1571 if (!ctxt)
1572 return (0);
1573 if (node == NULL)
1574 return (0);
1575 if (arg == NULL)
1576 return (0);
1577#ifdef LIBXML_REGEXP_ENABLED
1578 if ((xmlStrchr((xmlChar *) arg, '?')) ||
1579 (xmlStrchr((xmlChar *) arg, '*')) ||
1580 (xmlStrchr((xmlChar *) arg, '.')) ||
1581 (xmlStrchr((xmlChar *) arg, '['))) {
1582 }
1583#endif
1584 while (node != NULL) {
1585 if (node->type == XML_COMMENT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001586 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001587
1588 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
1589 xmlShellList(ctxt, NULL, node, NULL);
1590 }
1591 } else if (node->type == XML_TEXT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001592 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001593
1594 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001595 xmlShellList(ctxt, NULL, node->parent, NULL);
Daniel Veillard1e208222002-10-22 14:25:25 +00001596 }
1597 }
1598
1599 /*
1600 * Browse the full subtree, deep first
1601 */
1602
1603 if ((node->type == XML_DOCUMENT_NODE) ||
1604 (node->type == XML_HTML_DOCUMENT_NODE)) {
1605 node = ((xmlDocPtr) node)->children;
1606 } else if ((node->children != NULL)
1607 && (node->type != XML_ENTITY_REF_NODE)) {
1608 /* deep first */
1609 node = node->children;
1610 } else if (node->next != NULL) {
1611 /* then siblings */
1612 node = node->next;
1613 } else {
1614 /* go up to parents->next if needed */
1615 while (node != NULL) {
1616 if (node->parent != NULL) {
1617 node = node->parent;
1618 }
1619 if (node->next != NULL) {
1620 node = node->next;
1621 break;
1622 }
1623 if (node->parent == NULL) {
1624 node = NULL;
1625 break;
1626 }
1627 }
1628 }
1629 }
1630 return (0);
1631}
1632
1633/**
Owen Taylor3473f882001-02-23 17:55:21 +00001634 * xmlShellDir:
1635 * @ctxt: the shell context
1636 * @arg: unused
1637 * @node: a node
1638 * @node2: unused
1639 *
1640 * Implements the XML shell function "dir"
1641 * dumps informations about the node (namespace, attributes, content).
1642 *
1643 * Returns 0
1644 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001645int
1646xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1647 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1648 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1649{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001650 if (!ctxt)
1651 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001652 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001653 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001654 return (0);
1655 }
Owen Taylor3473f882001-02-23 17:55:21 +00001656 if ((node->type == XML_DOCUMENT_NODE) ||
1657 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001658 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001659 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001660 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001661 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001662 xmlDebugDumpOneNode(ctxt->output, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001663 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001664 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001665}
1666
1667/**
1668 * xmlShellCat:
1669 * @ctxt: the shell context
1670 * @arg: unused
1671 * @node: a node
1672 * @node2: unused
1673 *
1674 * Implements the XML shell function "cat"
1675 * dumps the serialization node content (XML or HTML).
1676 *
1677 * Returns 0
1678 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001679int
1680xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1681 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1682{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001683 if (!ctxt)
1684 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001685 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001686 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001687 return (0);
1688 }
Owen Taylor3473f882001-02-23 17:55:21 +00001689 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1690#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001691 if (node->type == XML_HTML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001692 htmlDocDump(ctxt->output, (htmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001693 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001694 htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001695#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001696 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001697 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001698 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001699 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001700#endif /* LIBXML_HTML_ENABLED */
1701 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001702 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001703 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001704 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001705 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001706 }
Daniel Veillard321be0c2002-10-08 21:26:42 +00001707 fprintf(ctxt->output, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001708 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001709}
1710
1711/**
1712 * xmlShellLoad:
1713 * @ctxt: the shell context
1714 * @filename: the file name
1715 * @node: unused
1716 * @node2: unused
1717 *
1718 * Implements the XML shell function "load"
1719 * loads a new document specified by the filename
1720 *
1721 * Returns 0 or -1 if loading failed
1722 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001723int
1724xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1725 xmlNodePtr node ATTRIBUTE_UNUSED,
1726 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1727{
Owen Taylor3473f882001-02-23 17:55:21 +00001728 xmlDocPtr doc;
1729 int html = 0;
1730
1731 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001732 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001733
1734 if (html) {
1735#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001736 doc = htmlParseFile(filename, NULL);
1737#else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001738 fprintf(ctxt->output, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001739 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001740#endif /* LIBXML_HTML_ENABLED */
1741 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001742 doc = xmlParseFile(filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001743 }
1744 if (doc != NULL) {
1745 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001746 xmlFreeDoc(ctxt->doc);
1747 }
1748 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001749#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001750 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001751#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001752 xmlFree(ctxt->filename);
1753 ctxt->doc = doc;
1754 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001755#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001756 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001757#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard85095e22003-04-23 13:56:44 +00001758 ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001759 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001760 return (-1);
1761 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001762}
1763
1764/**
1765 * xmlShellWrite:
1766 * @ctxt: the shell context
1767 * @filename: the file name
1768 * @node: a node in the tree
1769 * @node2: unused
1770 *
1771 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001772 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001773 * of the subtree under the @node specified
1774 *
1775 * Returns 0 or -1 in case of error
1776 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001777int
Owen Taylor3473f882001-02-23 17:55:21 +00001778xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001779 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1780{
Owen Taylor3473f882001-02-23 17:55:21 +00001781 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001782 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001783 if ((filename == NULL) || (filename[0] == 0)) {
1784 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001785 "Write command requires a filename argument\n");
1786 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001787 }
1788#ifdef W_OK
1789 if (access((char *) filename, W_OK)) {
1790 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001791 "Cannot write to %s\n", filename);
1792 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001793 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001794#endif
1795 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001796 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001797 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1798 xmlGenericError(xmlGenericErrorContext,
1799 "Failed to write to %s\n", filename);
1800 return (-1);
1801 }
1802 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001803 case XML_HTML_DOCUMENT_NODE:
1804#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001805 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1806 xmlGenericError(xmlGenericErrorContext,
1807 "Failed to write to %s\n", filename);
1808 return (-1);
1809 }
Owen Taylor3473f882001-02-23 17:55:21 +00001810#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001811 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1812 xmlGenericError(xmlGenericErrorContext,
1813 "Failed to write to %s\n", filename);
1814 return (-1);
1815 }
Owen Taylor3473f882001-02-23 17:55:21 +00001816#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001817 break;
1818 default:{
1819 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001820
Daniel Veillard78d12092001-10-11 09:12:24 +00001821 f = fopen((char *) filename, "w");
1822 if (f == NULL) {
1823 xmlGenericError(xmlGenericErrorContext,
1824 "Failed to write to %s\n", filename);
1825 return (-1);
1826 }
1827 xmlElemDump(f, ctxt->doc, node);
1828 fclose(f);
1829 }
Owen Taylor3473f882001-02-23 17:55:21 +00001830 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001831 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001832}
1833
1834/**
1835 * xmlShellSave:
1836 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001837 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001838 * @node: unused
1839 * @node2: unused
1840 *
1841 * Implements the XML shell function "save"
1842 * Write the current document to the filename, or it's original name
1843 *
1844 * Returns 0 or -1 in case of error
1845 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001846int
1847xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1848 xmlNodePtr node ATTRIBUTE_UNUSED,
1849 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1850{
Owen Taylor3473f882001-02-23 17:55:21 +00001851 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001852 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001853 if ((filename == NULL) || (filename[0] == 0))
1854 filename = ctxt->filename;
1855#ifdef W_OK
1856 if (access((char *) filename, W_OK)) {
1857 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001858 "Cannot save to %s\n", filename);
1859 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001860 }
1861#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001862 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001863 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001864 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1865 xmlGenericError(xmlGenericErrorContext,
1866 "Failed to save to %s\n", filename);
1867 }
1868 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001869 case XML_HTML_DOCUMENT_NODE:
1870#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001871 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1872 xmlGenericError(xmlGenericErrorContext,
1873 "Failed to save to %s\n", filename);
1874 }
Owen Taylor3473f882001-02-23 17:55:21 +00001875#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001876 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1877 xmlGenericError(xmlGenericErrorContext,
1878 "Failed to save to %s\n", filename);
1879 }
Owen Taylor3473f882001-02-23 17:55:21 +00001880#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001881 break;
1882 default:
1883 xmlGenericError(xmlGenericErrorContext,
1884 "To save to subparts of a document use the 'write' command\n");
1885 return (-1);
1886
Owen Taylor3473f882001-02-23 17:55:21 +00001887 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001888 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001889}
1890
1891/**
1892 * xmlShellValidate:
1893 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001894 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001895 * @node: unused
1896 * @node2: unused
1897 *
1898 * Implements the XML shell function "validate"
1899 * Validate the document, if a DTD path is provided, then the validation
1900 * is done against the given DTD.
1901 *
1902 * Returns 0 or -1 in case of error
1903 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001904int
1905xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1906 xmlNodePtr node ATTRIBUTE_UNUSED,
1907 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1908{
Owen Taylor3473f882001-02-23 17:55:21 +00001909 xmlValidCtxt vctxt;
1910 int res = -1;
1911
1912 vctxt.userData = stderr;
1913 vctxt.error = (xmlValidityErrorFunc) fprintf;
1914 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1915
1916 if ((dtd == NULL) || (dtd[0] == 0)) {
1917 res = xmlValidateDocument(&vctxt, ctxt->doc);
1918 } else {
1919 xmlDtdPtr subset;
1920
Daniel Veillard78d12092001-10-11 09:12:24 +00001921 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1922 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001923 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1924
Daniel Veillard78d12092001-10-11 09:12:24 +00001925 xmlFreeDtd(subset);
1926 }
Owen Taylor3473f882001-02-23 17:55:21 +00001927 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001928 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00001929}
1930
1931/**
1932 * xmlShellDu:
1933 * @ctxt: the shell context
1934 * @arg: unused
1935 * @tree: a node defining a subtree
1936 * @node2: unused
1937 *
1938 * Implements the XML shell function "du"
1939 * show the structure of the subtree under node @tree
1940 * If @tree is null, the command works on the current node.
1941 *
1942 * Returns 0 or -1 in case of error
1943 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001944int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001945xmlShellDu(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001946 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1947 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1948{
Owen Taylor3473f882001-02-23 17:55:21 +00001949 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00001950 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00001951
Daniel Veillard321be0c2002-10-08 21:26:42 +00001952 if (!ctxt)
1953 return (-1);
1954
Daniel Veillard78d12092001-10-11 09:12:24 +00001955 if (tree == NULL)
1956 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001957 node = tree;
1958 while (node != NULL) {
1959 if ((node->type == XML_DOCUMENT_NODE) ||
1960 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001961 fprintf(ctxt->output, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001962 } else if (node->type == XML_ELEMENT_NODE) {
1963 for (i = 0; i < indent; i++)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001964 fprintf(ctxt->output, " ");
1965 fprintf(ctxt->output, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00001966 } else {
1967 }
Owen Taylor3473f882001-02-23 17:55:21 +00001968
Daniel Veillard78d12092001-10-11 09:12:24 +00001969 /*
1970 * Browse the full subtree, deep first
1971 */
Owen Taylor3473f882001-02-23 17:55:21 +00001972
1973 if ((node->type == XML_DOCUMENT_NODE) ||
1974 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001975 node = ((xmlDocPtr) node)->children;
1976 } else if ((node->children != NULL)
1977 && (node->type != XML_ENTITY_REF_NODE)) {
1978 /* deep first */
1979 node = node->children;
1980 indent++;
1981 } else if ((node != tree) && (node->next != NULL)) {
1982 /* then siblings */
1983 node = node->next;
1984 } else if (node != tree) {
1985 /* go up to parents->next if needed */
1986 while (node != tree) {
1987 if (node->parent != NULL) {
1988 node = node->parent;
1989 indent--;
1990 }
1991 if ((node != tree) && (node->next != NULL)) {
1992 node = node->next;
1993 break;
1994 }
1995 if (node->parent == NULL) {
1996 node = NULL;
1997 break;
1998 }
1999 if (node == tree) {
2000 node = NULL;
2001 break;
2002 }
2003 }
2004 /* exit condition */
2005 if (node == tree)
2006 node = NULL;
2007 } else
2008 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002009 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002010 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002011}
2012
2013/**
2014 * xmlShellPwd:
2015 * @ctxt: the shell context
2016 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00002017 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00002018 * @node2: unused
2019 *
2020 * Implements the XML shell function "pwd"
2021 * Show the full path from the root to the node, if needed building
2022 * thumblers when similar elements exists at a given ancestor level.
2023 * The output is compatible with XPath commands.
2024 *
2025 * Returns 0 or -1 in case of error
2026 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002027int
2028xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2029 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2030{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002031 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00002032
Daniel Veillard78d12092001-10-11 09:12:24 +00002033 if (node == NULL)
2034 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002035
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002036 path = xmlGetNodePath(node);
2037 if (path == NULL)
2038 return (-1);
2039
2040 /*
2041 * This test prevents buffer overflow, because this routine
2042 * is only called by xmlShell, in which the second argument is
2043 * 500 chars long.
2044 * It is a dirty hack before a cleaner solution is found.
2045 * Documentation should mention that the second argument must
2046 * be at least 500 chars long, and could be stripped if too long.
2047 */
2048 snprintf(buffer, 499, "%s", path);
2049 buffer[499] = '0';
2050 xmlFree(path);
2051
Daniel Veillard78d12092001-10-11 09:12:24 +00002052 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002053}
2054
2055/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002056 * xmlShell:
Owen Taylor3473f882001-02-23 17:55:21 +00002057 * @doc: the initial document
2058 * @filename: the output buffer
2059 * @input: the line reading function
Daniel Veillard321be0c2002-10-08 21:26:42 +00002060 * @output: the output FILE*, defaults to stdout if NULL
Owen Taylor3473f882001-02-23 17:55:21 +00002061 *
2062 * Implements the XML shell
2063 * This allow to load, validate, view, modify and save a document
2064 * using a environment similar to a UNIX commandline.
2065 */
2066void
2067xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00002068 FILE * output)
2069{
Owen Taylor3473f882001-02-23 17:55:21 +00002070 char prompt[500] = "/ > ";
2071 char *cmdline = NULL, *cur;
2072 int nbargs;
2073 char command[100];
2074 char arg[400];
2075 int i;
2076 xmlShellCtxtPtr ctxt;
2077 xmlXPathObjectPtr list;
2078
2079 if (doc == NULL)
2080 return;
2081 if (filename == NULL)
2082 return;
2083 if (input == NULL)
2084 return;
2085 if (output == NULL)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002086 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00002087 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00002088 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00002089 return;
2090 ctxt->loaded = 0;
2091 ctxt->doc = doc;
2092 ctxt->input = input;
2093 ctxt->output = output;
2094 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00002095 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00002096
2097#ifdef LIBXML_XPATH_ENABLED
2098 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2099 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002100 xmlFree(ctxt);
2101 return;
Owen Taylor3473f882001-02-23 17:55:21 +00002102 }
2103#endif /* LIBXML_XPATH_ENABLED */
2104 while (1) {
2105 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002106 snprintf(prompt, sizeof(prompt), "%s > ", "/");
Daniel Veillard7a985a12003-07-06 17:57:42 +00002107 else if ((ctxt->node != NULL) && (ctxt->node->name))
Daniel Veillard78d12092001-10-11 09:12:24 +00002108 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00002109 else
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002110 snprintf(prompt, sizeof(prompt), "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00002111 prompt[sizeof(prompt) - 1] = 0;
2112
Daniel Veillard78d12092001-10-11 09:12:24 +00002113 /*
2114 * Get a new command line
2115 */
Owen Taylor3473f882001-02-23 17:55:21 +00002116 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00002117 if (cmdline == NULL)
2118 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002119
Daniel Veillard78d12092001-10-11 09:12:24 +00002120 /*
2121 * Parse the command itself
2122 */
2123 cur = cmdline;
2124 nbargs = 0;
2125 while ((*cur == ' ') || (*cur == '\t'))
2126 cur++;
2127 i = 0;
2128 while ((*cur != ' ') && (*cur != '\t') &&
2129 (*cur != '\n') && (*cur != '\r')) {
2130 if (*cur == 0)
2131 break;
2132 command[i++] = *cur++;
2133 }
2134 command[i] = 0;
2135 if (i == 0)
2136 continue;
2137 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002138
Daniel Veillard78d12092001-10-11 09:12:24 +00002139 /*
2140 * Parse the argument
2141 */
2142 while ((*cur == ' ') || (*cur == '\t'))
2143 cur++;
2144 i = 0;
2145 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2146 if (*cur == 0)
2147 break;
2148 arg[i++] = *cur++;
2149 }
2150 arg[i] = 0;
2151 if (i != 0)
2152 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002153
Daniel Veillard78d12092001-10-11 09:12:24 +00002154 /*
2155 * start interpreting the command
2156 */
Owen Taylor3473f882001-02-23 17:55:21 +00002157 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002158 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002159 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002160 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002161 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002162 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002163 if (!strcmp(command, "help")) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002164 fprintf(ctxt->output, "\tbase display XML base of the node\n");
2165 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2166 fprintf(ctxt->output, "\tbye leave shell\n");
2167 fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2168 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2169 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2170 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2171 fprintf(ctxt->output, "\texit leave shell\n");
2172 fprintf(ctxt->output, "\thelp display this help\n");
2173 fprintf(ctxt->output, "\tfree display memory usage\n");
2174 fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2175 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002176#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002177 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002178#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard321be0c2002-10-08 21:26:42 +00002179 fprintf(ctxt->output, "\tpwd display current working directory\n");
2180 fprintf(ctxt->output, "\tquit leave shell\n");
2181 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
2182 fprintf(ctxt->output, "\tvalidate check the document for errors\n");
2183 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
Daniel Veillard1e208222002-10-22 14:25:25 +00002184 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
Daniel Veillard5004f422001-11-08 13:53:05 +00002185 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002186 xmlShellValidate(ctxt, arg, NULL, NULL);
2187 } else if (!strcmp(command, "load")) {
2188 xmlShellLoad(ctxt, arg, NULL, NULL);
2189 } else if (!strcmp(command, "save")) {
2190 xmlShellSave(ctxt, arg, NULL, NULL);
2191 } else if (!strcmp(command, "write")) {
2192 xmlShellWrite(ctxt, arg, NULL, NULL);
Daniel Veillard1e208222002-10-22 14:25:25 +00002193 } else if (!strcmp(command, "grep")) {
2194 xmlShellGrep(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002195 } else if (!strcmp(command, "free")) {
2196 if (arg[0] == 0) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002197 xmlMemShow(ctxt->output, 0);
Daniel Veillard78d12092001-10-11 09:12:24 +00002198 } else {
2199 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002200
Daniel Veillard78d12092001-10-11 09:12:24 +00002201 sscanf(arg, "%d", &len);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002202 xmlMemShow(ctxt->output, len);
Daniel Veillard78d12092001-10-11 09:12:24 +00002203 }
2204 } else if (!strcmp(command, "pwd")) {
2205 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002206
Daniel Veillard78d12092001-10-11 09:12:24 +00002207 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillard321be0c2002-10-08 21:26:42 +00002208 fprintf(ctxt->output, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002209 } else if (!strcmp(command, "du")) {
2210 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2211 } else if (!strcmp(command, "base")) {
2212 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002213#ifdef LIBXML_XPATH_ENABLED
2214 } else if (!strcmp(command, "xpath")) {
2215 if (arg[0] == 0) {
2216 xmlGenericError(xmlGenericErrorContext,
2217 "xpath: expression required\n");
2218 } else {
2219 ctxt->pctxt->node = ctxt->node;
2220 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002221 xmlXPathDebugDumpObject(ctxt->output, list, 0);
Daniel Veillard2070c482002-01-22 22:12:19 +00002222 xmlXPathFreeObject(list);
2223 }
2224#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002225 } else if (!strcmp(command, "setbase")) {
2226 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002227 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2228 int dir = (!strcmp(command, "dir"));
2229
2230 if (arg[0] == 0) {
2231 if (dir)
2232 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2233 else
2234 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2235 } else {
2236 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002237#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002238 ctxt->pctxt->node = ctxt->node;
2239 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2240#else
2241 list = NULL;
2242#endif /* LIBXML_XPATH_ENABLED */
2243 if (list != NULL) {
2244 switch (list->type) {
2245 case XPATH_UNDEFINED:
2246 xmlGenericError(xmlGenericErrorContext,
2247 "%s: no such node\n", arg);
2248 break;
2249 case XPATH_NODESET:{
2250 int indx;
2251
Daniel Veillarda6825e82001-11-07 13:33:59 +00002252 if (list->nodesetval == NULL)
2253 break;
2254
Daniel Veillard78d12092001-10-11 09:12:24 +00002255 for (indx = 0;
2256 indx < list->nodesetval->nodeNr;
2257 indx++) {
2258 if (dir)
2259 xmlShellDir(ctxt, NULL,
2260 list->nodesetval->
2261 nodeTab[indx], NULL);
2262 else
2263 xmlShellList(ctxt, NULL,
2264 list->nodesetval->
2265 nodeTab[indx], NULL);
2266 }
2267 break;
2268 }
2269 case XPATH_BOOLEAN:
2270 xmlGenericError(xmlGenericErrorContext,
2271 "%s is a Boolean\n", arg);
2272 break;
2273 case XPATH_NUMBER:
2274 xmlGenericError(xmlGenericErrorContext,
2275 "%s is a number\n", arg);
2276 break;
2277 case XPATH_STRING:
2278 xmlGenericError(xmlGenericErrorContext,
2279 "%s is a string\n", arg);
2280 break;
2281 case XPATH_POINT:
2282 xmlGenericError(xmlGenericErrorContext,
2283 "%s is a point\n", arg);
2284 break;
2285 case XPATH_RANGE:
2286 xmlGenericError(xmlGenericErrorContext,
2287 "%s is a range\n", arg);
2288 break;
2289 case XPATH_LOCATIONSET:
2290 xmlGenericError(xmlGenericErrorContext,
2291 "%s is a range\n", arg);
2292 break;
2293 case XPATH_USERS:
2294 xmlGenericError(xmlGenericErrorContext,
2295 "%s is user-defined\n", arg);
2296 break;
2297 case XPATH_XSLT_TREE:
2298 xmlGenericError(xmlGenericErrorContext,
2299 "%s is an XSLT value tree\n",
2300 arg);
2301 break;
2302 }
2303#ifdef LIBXML_XPATH_ENABLED
2304 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002305#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002306 } else {
2307 xmlGenericError(xmlGenericErrorContext,
2308 "%s: no such node\n", arg);
2309 }
2310 ctxt->pctxt->node = NULL;
2311 }
2312 } else if (!strcmp(command, "cd")) {
2313 if (arg[0] == 0) {
2314 ctxt->node = (xmlNodePtr) ctxt->doc;
2315 } else {
2316#ifdef LIBXML_XPATH_ENABLED
2317 ctxt->pctxt->node = ctxt->node;
2318 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2319#else
2320 list = NULL;
2321#endif /* LIBXML_XPATH_ENABLED */
2322 if (list != NULL) {
2323 switch (list->type) {
2324 case XPATH_UNDEFINED:
2325 xmlGenericError(xmlGenericErrorContext,
2326 "%s: no such node\n", arg);
2327 break;
2328 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002329 if (list->nodesetval != NULL) {
2330 if (list->nodesetval->nodeNr == 1) {
2331 ctxt->node = list->nodesetval->nodeTab[0];
Daniel Veillard7a985a12003-07-06 17:57:42 +00002332 if ((ctxt->node != NULL) &&
2333 (ctxt->node->type ==
2334 XML_NAMESPACE_DECL)) {
2335 xmlGenericError(xmlGenericErrorContext,
2336 "cannot cd to namespace\n");
2337 ctxt->node = NULL;
2338 }
Daniel Veillarda6825e82001-11-07 13:33:59 +00002339 } else
2340 xmlGenericError(xmlGenericErrorContext,
2341 "%s is a %d Node Set\n",
2342 arg,
2343 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002344 } else
2345 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002346 "%s is an empty Node Set\n",
2347 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002348 break;
2349 case XPATH_BOOLEAN:
2350 xmlGenericError(xmlGenericErrorContext,
2351 "%s is a Boolean\n", arg);
2352 break;
2353 case XPATH_NUMBER:
2354 xmlGenericError(xmlGenericErrorContext,
2355 "%s is a number\n", arg);
2356 break;
2357 case XPATH_STRING:
2358 xmlGenericError(xmlGenericErrorContext,
2359 "%s is a string\n", arg);
2360 break;
2361 case XPATH_POINT:
2362 xmlGenericError(xmlGenericErrorContext,
2363 "%s is a point\n", arg);
2364 break;
2365 case XPATH_RANGE:
2366 xmlGenericError(xmlGenericErrorContext,
2367 "%s is a range\n", arg);
2368 break;
2369 case XPATH_LOCATIONSET:
2370 xmlGenericError(xmlGenericErrorContext,
2371 "%s is a range\n", arg);
2372 break;
2373 case XPATH_USERS:
2374 xmlGenericError(xmlGenericErrorContext,
2375 "%s is user-defined\n", arg);
2376 break;
2377 case XPATH_XSLT_TREE:
2378 xmlGenericError(xmlGenericErrorContext,
2379 "%s is an XSLT value tree\n",
2380 arg);
2381 break;
2382 }
2383#ifdef LIBXML_XPATH_ENABLED
2384 xmlXPathFreeObject(list);
2385#endif
2386 } else {
2387 xmlGenericError(xmlGenericErrorContext,
2388 "%s: no such node\n", arg);
2389 }
2390 ctxt->pctxt->node = NULL;
2391 }
2392 } else if (!strcmp(command, "cat")) {
2393 if (arg[0] == 0) {
2394 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2395 } else {
2396 ctxt->pctxt->node = ctxt->node;
2397#ifdef LIBXML_XPATH_ENABLED
2398 ctxt->pctxt->node = ctxt->node;
2399 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2400#else
2401 list = NULL;
2402#endif /* LIBXML_XPATH_ENABLED */
2403 if (list != NULL) {
2404 switch (list->type) {
2405 case XPATH_UNDEFINED:
2406 xmlGenericError(xmlGenericErrorContext,
2407 "%s: no such node\n", arg);
2408 break;
2409 case XPATH_NODESET:{
2410 int indx;
2411
Daniel Veillarda6825e82001-11-07 13:33:59 +00002412 if (list->nodesetval == NULL)
2413 break;
2414
Daniel Veillard78d12092001-10-11 09:12:24 +00002415 for (indx = 0;
2416 indx < list->nodesetval->nodeNr;
2417 indx++) {
2418 if (i > 0)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002419 fprintf(ctxt->output, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002420 xmlShellCat(ctxt, NULL,
2421 list->nodesetval->
2422 nodeTab[indx], NULL);
2423 }
2424 break;
2425 }
2426 case XPATH_BOOLEAN:
2427 xmlGenericError(xmlGenericErrorContext,
2428 "%s is a Boolean\n", arg);
2429 break;
2430 case XPATH_NUMBER:
2431 xmlGenericError(xmlGenericErrorContext,
2432 "%s is a number\n", arg);
2433 break;
2434 case XPATH_STRING:
2435 xmlGenericError(xmlGenericErrorContext,
2436 "%s is a string\n", arg);
2437 break;
2438 case XPATH_POINT:
2439 xmlGenericError(xmlGenericErrorContext,
2440 "%s is a point\n", arg);
2441 break;
2442 case XPATH_RANGE:
2443 xmlGenericError(xmlGenericErrorContext,
2444 "%s is a range\n", arg);
2445 break;
2446 case XPATH_LOCATIONSET:
2447 xmlGenericError(xmlGenericErrorContext,
2448 "%s is a range\n", arg);
2449 break;
2450 case XPATH_USERS:
2451 xmlGenericError(xmlGenericErrorContext,
2452 "%s is user-defined\n", arg);
2453 break;
2454 case XPATH_XSLT_TREE:
2455 xmlGenericError(xmlGenericErrorContext,
2456 "%s is an XSLT value tree\n",
2457 arg);
2458 break;
2459 }
2460#ifdef LIBXML_XPATH_ENABLED
2461 xmlXPathFreeObject(list);
2462#endif
2463 } else {
2464 xmlGenericError(xmlGenericErrorContext,
2465 "%s: no such node\n", arg);
2466 }
2467 ctxt->pctxt->node = NULL;
2468 }
2469 } else {
2470 xmlGenericError(xmlGenericErrorContext,
2471 "Unknown command %s\n", command);
2472 }
2473 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002474 }
2475#ifdef LIBXML_XPATH_ENABLED
2476 xmlXPathFreeContext(ctxt->pctxt);
2477#endif /* LIBXML_XPATH_ENABLED */
2478 if (ctxt->loaded) {
2479 xmlFreeDoc(ctxt->doc);
2480 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002481 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002482 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002483 xmlFree(ctxt);
2484 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002485 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002486}
2487
2488#endif /* LIBXML_DEBUG_ENABLED */