blob: cbb74c04b177369d62a15cee1c571ab9b39b6b63 [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>
Owen Taylor3473f882001-02-23 17:55:21 +000032
Daniel Veillard5e2dace2001-07-18 19:30:27 +000033/**
34 * xmlDebugDumpString:
35 * @output: the FILE * for the output
36 * @str: the string
37 *
38 * Dumps informations about the string, shorten it if necessary
39 */
40void
41xmlDebugDumpString(FILE * output, const xmlChar * str)
42{
Owen Taylor3473f882001-02-23 17:55:21 +000043 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000044
Daniel Veillard7db38712002-02-07 16:39:11 +000045 if (output == NULL)
46 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +000047 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000048 fprintf(output, "(NULL)");
49 return;
Owen Taylor3473f882001-02-23 17:55:21 +000050 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000051 for (i = 0; i < 40; i++)
52 if (str[i] == 0)
53 return;
54 else if (IS_BLANK(str[i]))
55 fputc(' ', output);
56 else if (str[i] >= 0x80)
57 fprintf(output, "#%X", str[i]);
58 else
59 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000060 fprintf(output, "...");
61}
62
Daniel Veillard56a4cb82001-03-24 17:00:36 +000063static void
64xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000065 int i;
66 char shift[100];
67
68 for (i = 0;((i < depth) && (i < 25));i++)
69 shift[2 * i] = shift[2 * i + 1] = ' ';
70 shift[2 * i] = shift[2 * i + 1] = 0;
71
72 fprintf(output, shift);
73
Daniel Veillard5e926fa2002-01-22 21:44:25 +000074 if (dtd == NULL) {
75 fprintf(output, "DTD node is NULL\n");
76 return;
77 }
78
Owen Taylor3473f882001-02-23 17:55:21 +000079 if (dtd->type != XML_DTD_NODE) {
80 fprintf(output, "PBM: not a DTD\n");
81 return;
82 }
83 if (dtd->name != NULL)
84 fprintf(output, "DTD(%s)", dtd->name);
85 else
86 fprintf(output, "DTD");
87 if (dtd->ExternalID != NULL)
88 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
89 if (dtd->SystemID != NULL)
90 fprintf(output, ", SYSTEM %s", dtd->SystemID);
91 fprintf(output, "\n");
92 /*
93 * Do a bit of checking
94 */
95 if (dtd->parent == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000096 fprintf(output, "PBM: DTD has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +000097 if (dtd->doc == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000098 fprintf(output, "PBM: DTD has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +000099 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000100 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000101 if (dtd->prev == NULL) {
102 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000103 fprintf(output, "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000104 } else {
105 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000106 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000107 }
108 if (dtd->next == NULL) {
109 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000110 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000111 } else {
112 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000113 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000114 }
115}
116
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000117static void
118xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000119 int i;
120 char shift[100];
121
122 for (i = 0;((i < depth) && (i < 25));i++)
123 shift[2 * i] = shift[2 * i + 1] = ' ';
124 shift[2 * i] = shift[2 * i + 1] = 0;
125
126 fprintf(output, shift);
127
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000128 if (attr == NULL) {
129 fprintf(output, "Attribute declaration is NULL\n");
130 return;
131 }
Owen Taylor3473f882001-02-23 17:55:21 +0000132 if (attr->type != XML_ATTRIBUTE_DECL) {
133 fprintf(output, "PBM: not a Attr\n");
134 return;
135 }
136 if (attr->name != NULL)
137 fprintf(output, "ATTRDECL(%s)", attr->name);
138 else
139 fprintf(output, "PBM ATTRDECL noname!!!");
140 if (attr->elem != NULL)
141 fprintf(output, " for %s", attr->elem);
142 else
143 fprintf(output, " PBM noelem!!!");
144 switch (attr->atype) {
145 case XML_ATTRIBUTE_CDATA:
146 fprintf(output, " CDATA");
147 break;
148 case XML_ATTRIBUTE_ID:
149 fprintf(output, " ID");
150 break;
151 case XML_ATTRIBUTE_IDREF:
152 fprintf(output, " IDREF");
153 break;
154 case XML_ATTRIBUTE_IDREFS:
155 fprintf(output, " IDREFS");
156 break;
157 case XML_ATTRIBUTE_ENTITY:
158 fprintf(output, " ENTITY");
159 break;
160 case XML_ATTRIBUTE_ENTITIES:
161 fprintf(output, " ENTITIES");
162 break;
163 case XML_ATTRIBUTE_NMTOKEN:
164 fprintf(output, " NMTOKEN");
165 break;
166 case XML_ATTRIBUTE_NMTOKENS:
167 fprintf(output, " NMTOKENS");
168 break;
169 case XML_ATTRIBUTE_ENUMERATION:
170 fprintf(output, " ENUMERATION");
171 break;
172 case XML_ATTRIBUTE_NOTATION:
173 fprintf(output, " NOTATION ");
174 break;
175 }
176 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000177 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000178 xmlEnumerationPtr cur = attr->tree;
179
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000180 for (indx = 0;indx < 5; indx++) {
181 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000182 fprintf(output, "|%s", cur->name);
183 else
184 fprintf(output, " (%s", cur->name);
185 cur = cur->next;
186 if (cur == NULL) break;
187 }
188 if (cur == NULL)
189 fprintf(output, ")");
190 else
191 fprintf(output, "...)");
192 }
193 switch (attr->def) {
194 case XML_ATTRIBUTE_NONE:
195 break;
196 case XML_ATTRIBUTE_REQUIRED:
197 fprintf(output, " REQUIRED");
198 break;
199 case XML_ATTRIBUTE_IMPLIED:
200 fprintf(output, " IMPLIED");
201 break;
202 case XML_ATTRIBUTE_FIXED:
203 fprintf(output, " FIXED");
204 break;
205 }
206 if (attr->defaultValue != NULL) {
207 fprintf(output, "\"");
208 xmlDebugDumpString(output, attr->defaultValue);
209 fprintf(output, "\"");
210 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000211 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000212
213 /*
214 * Do a bit of checking
215 */
216 if (attr->parent == NULL)
217 fprintf(output, "PBM: Attr has no parent\n");
218 if (attr->doc == NULL)
219 fprintf(output, "PBM: Attr has no doc\n");
220 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
221 fprintf(output, "PBM: Attr doc differs from parent's one\n");
222 if (attr->prev == NULL) {
223 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
224 fprintf(output, "PBM: Attr has no prev and not first of list\n");
225 } else {
226 if (attr->prev->next != (xmlNodePtr) attr)
227 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
228 }
229 if (attr->next == NULL) {
230 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
231 fprintf(output, "PBM: Attr has no next and not last of list\n");
232 } else {
233 if (attr->next->prev != (xmlNodePtr) attr)
234 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
235 }
236}
237
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000238static void
239xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000240 int i;
241 char shift[100];
242
243 for (i = 0;((i < depth) && (i < 25));i++)
244 shift[2 * i] = shift[2 * i + 1] = ' ';
245 shift[2 * i] = shift[2 * i + 1] = 0;
246
247 fprintf(output, shift);
248
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000249 if (elem == NULL) {
250 fprintf(output, "Element declaration is NULL\n");
251 return;
252 }
Owen Taylor3473f882001-02-23 17:55:21 +0000253 if (elem->type != XML_ELEMENT_DECL) {
254 fprintf(output, "PBM: not a Elem\n");
255 return;
256 }
257 if (elem->name != NULL) {
258 fprintf(output, "ELEMDECL(");
259 xmlDebugDumpString(output, elem->name);
260 fprintf(output, ")");
261 } else
262 fprintf(output, "PBM ELEMDECL noname!!!");
263 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000264 case XML_ELEMENT_TYPE_UNDEFINED:
265 fprintf(output, ", UNDEFINED");
266 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000267 case XML_ELEMENT_TYPE_EMPTY:
268 fprintf(output, ", EMPTY");
269 break;
270 case XML_ELEMENT_TYPE_ANY:
271 fprintf(output, ", ANY");
272 break;
273 case XML_ELEMENT_TYPE_MIXED:
274 fprintf(output, ", MIXED ");
275 break;
276 case XML_ELEMENT_TYPE_ELEMENT:
277 fprintf(output, ", MIXED ");
278 break;
279 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000280 if ((elem->type != XML_ELEMENT_NODE) &&
281 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000282 char buf[5001];
283
284 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000285 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000286 buf[5000] = 0;
287 fprintf(output, "%s", buf);
288 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000289 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000290
291 /*
292 * Do a bit of checking
293 */
294 if (elem->parent == NULL)
295 fprintf(output, "PBM: Elem has no parent\n");
296 if (elem->doc == NULL)
297 fprintf(output, "PBM: Elem has no doc\n");
298 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
299 fprintf(output, "PBM: Elem doc differs from parent's one\n");
300 if (elem->prev == NULL) {
301 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
302 fprintf(output, "PBM: Elem has no prev and not first of list\n");
303 } else {
304 if (elem->prev->next != (xmlNodePtr) elem)
305 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
306 }
307 if (elem->next == NULL) {
308 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
309 fprintf(output, "PBM: Elem has no next and not last of list\n");
310 } else {
311 if (elem->next->prev != (xmlNodePtr) elem)
312 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
313 }
314}
315
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000316static void
317xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000318 int i;
319 char shift[100];
320
321 for (i = 0;((i < depth) && (i < 25));i++)
322 shift[2 * i] = shift[2 * i + 1] = ' ';
323 shift[2 * i] = shift[2 * i + 1] = 0;
324
325 fprintf(output, shift);
326
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000327 if (ent == NULL) {
328 fprintf(output, "Entity declaration is NULL\n");
329 return;
330 }
Owen Taylor3473f882001-02-23 17:55:21 +0000331 if (ent->type != XML_ENTITY_DECL) {
332 fprintf(output, "PBM: not a Entity decl\n");
333 return;
334 }
335 if (ent->name != NULL) {
336 fprintf(output, "ENTITYDECL(");
337 xmlDebugDumpString(output, ent->name);
338 fprintf(output, ")");
339 } else
340 fprintf(output, "PBM ENTITYDECL noname!!!");
341 switch (ent->etype) {
342 case XML_INTERNAL_GENERAL_ENTITY:
343 fprintf(output, ", internal\n");
344 break;
345 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
346 fprintf(output, ", external parsed\n");
347 break;
348 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
349 fprintf(output, ", unparsed\n");
350 break;
351 case XML_INTERNAL_PARAMETER_ENTITY:
352 fprintf(output, ", parameter\n");
353 break;
354 case XML_EXTERNAL_PARAMETER_ENTITY:
355 fprintf(output, ", external parameter\n");
356 break;
357 case XML_INTERNAL_PREDEFINED_ENTITY:
358 fprintf(output, ", predefined\n");
359 break;
360 }
361 if (ent->ExternalID) {
362 fprintf(output, shift);
363 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
364 }
365 if (ent->SystemID) {
366 fprintf(output, shift);
367 fprintf(output, " SystemID=%s\n", ent->SystemID);
368 }
369 if (ent->URI != NULL) {
370 fprintf(output, shift);
371 fprintf(output, " URI=%s\n", ent->URI);
372 }
373 if (ent->content) {
374 fprintf(output, shift);
375 fprintf(output, " content=");
376 xmlDebugDumpString(output, ent->content);
377 fprintf(output, "\n");
378 }
379
380 /*
381 * Do a bit of checking
382 */
383 if (ent->parent == NULL)
384 fprintf(output, "PBM: Ent has no parent\n");
385 if (ent->doc == NULL)
386 fprintf(output, "PBM: Ent has no doc\n");
387 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
388 fprintf(output, "PBM: Ent doc differs from parent's one\n");
389 if (ent->prev == NULL) {
390 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
391 fprintf(output, "PBM: Ent has no prev and not first of list\n");
392 } else {
393 if (ent->prev->next != (xmlNodePtr) ent)
394 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
395 }
396 if (ent->next == NULL) {
397 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
398 fprintf(output, "PBM: Ent has no next and not last of list\n");
399 } else {
400 if (ent->next->prev != (xmlNodePtr) ent)
401 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
402 }
403}
404
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000405static void
406xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000407 int i;
408 char shift[100];
409
410 for (i = 0;((i < depth) && (i < 25));i++)
411 shift[2 * i] = shift[2 * i + 1] = ' ';
412 shift[2 * i] = shift[2 * i + 1] = 0;
413
414 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000415
416 if (ns == NULL) {
417 fprintf(output, "namespace node is NULL\n");
418 return;
419 }
Owen Taylor3473f882001-02-23 17:55:21 +0000420 if (ns->type != XML_NAMESPACE_DECL) {
421 fprintf(output, "invalid namespace node %d\n", ns->type);
422 return;
423 }
424 if (ns->href == NULL) {
425 if (ns->prefix != NULL)
426 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
427 else
428 fprintf(output, "incomplete default namespace href=NULL\n");
429 } else {
430 if (ns->prefix != NULL)
431 fprintf(output, "namespace %s href=", ns->prefix);
432 else
433 fprintf(output, "default namespace href=");
434
435 xmlDebugDumpString(output, ns->href);
436 fprintf(output, "\n");
437 }
438}
439
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000440static void
441xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000442 while (ns != NULL) {
443 xmlDebugDumpNamespace(output, ns, depth);
444 ns = ns->next;
445 }
446}
447
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000448static void
449xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000450 int i;
451 char shift[100];
452
453 for (i = 0;((i < depth) && (i < 25));i++)
454 shift[2 * i] = shift[2 * i + 1] = ' ';
455 shift[2 * i] = shift[2 * i + 1] = 0;
456
457 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000458
459 if (ent == NULL) {
460 fprintf(output, "Entity is NULL\n");
461 return;
462 }
Owen Taylor3473f882001-02-23 17:55:21 +0000463 switch (ent->etype) {
464 case XML_INTERNAL_GENERAL_ENTITY:
465 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
466 break;
467 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
468 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
469 break;
470 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
471 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
472 break;
473 case XML_INTERNAL_PARAMETER_ENTITY:
474 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
475 break;
476 case XML_EXTERNAL_PARAMETER_ENTITY:
477 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
478 break;
479 default:
480 fprintf(output, "ENTITY_%d ! ", ent->etype);
481 }
482 fprintf(output, "%s\n", ent->name);
483 if (ent->ExternalID) {
484 fprintf(output, shift);
485 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
486 }
487 if (ent->SystemID) {
488 fprintf(output, shift);
489 fprintf(output, "SystemID=%s\n", ent->SystemID);
490 }
491 if (ent->URI) {
492 fprintf(output, shift);
493 fprintf(output, "URI=%s\n", ent->URI);
494 }
495 if (ent->content) {
496 fprintf(output, shift);
497 fprintf(output, "content=");
498 xmlDebugDumpString(output, ent->content);
499 fprintf(output, "\n");
500 }
501}
502
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000503/**
504 * xmlDebugDumpAttr:
505 * @output: the FILE * for the output
506 * @attr: the attribute
507 * @depth: the indentation level.
508 *
509 * Dumps debug information for the attribute
510 */
511void
512xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000513 int i;
514 char shift[100];
515
516 for (i = 0;((i < depth) && (i < 25));i++)
517 shift[2 * i] = shift[2 * i + 1] = ' ';
518 shift[2 * i] = shift[2 * i + 1] = 0;
519
520 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000521
522 if (attr == NULL) {
523 fprintf(output, "Attr is NULL");
524 return;
525 }
Owen Taylor3473f882001-02-23 17:55:21 +0000526 fprintf(output, "ATTRIBUTE ");
527 xmlDebugDumpString(output, attr->name);
528 fprintf(output, "\n");
529 if (attr->children != NULL)
530 xmlDebugDumpNodeList(output, attr->children, depth + 1);
531
532 /*
533 * Do a bit of checking
534 */
535 if (attr->parent == NULL)
536 fprintf(output, "PBM: Attr has no parent\n");
537 if (attr->doc == NULL)
538 fprintf(output, "PBM: Attr has no doc\n");
539 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
540 fprintf(output, "PBM: Attr doc differs from parent's one\n");
541 if (attr->prev == NULL) {
542 if ((attr->parent != NULL) && (attr->parent->properties != attr))
543 fprintf(output, "PBM: Attr has no prev and not first of list\n");
544 } else {
545 if (attr->prev->next != attr)
546 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
547 }
548 if (attr->next != NULL) {
549 if (attr->next->prev != attr)
550 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
551 }
552}
553
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000554/**
555 * xmlDebugDumpAttrList:
556 * @output: the FILE * for the output
557 * @attr: the attribute list
558 * @depth: the indentation level.
559 *
560 * Dumps debug information for the attribute list
561 */
562void
563xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
564{
Daniel Veillard7db38712002-02-07 16:39:11 +0000565 if (output == NULL)
566 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000567 while (attr != NULL) {
568 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000569 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000570 }
571}
572
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000573/**
574 * xmlDebugDumpOneNode:
575 * @output: the FILE * for the output
576 * @node: the node
577 * @depth: the indentation level.
578 *
579 * Dumps debug information for the element node, it is not recursive
580 */
581void
582xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
583{
Owen Taylor3473f882001-02-23 17:55:21 +0000584 int i;
585 char shift[100];
586
Daniel Veillard7db38712002-02-07 16:39:11 +0000587 if (output == NULL)
588 output = stdout;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000589 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000590 shift[2 * i] = shift[2 * i + 1] = ' ';
591 shift[2 * i] = shift[2 * i + 1] = 0;
592
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000593 if (node == NULL) {
594 fprintf(output, shift);
595 fprintf(output, "node is NULL\n");
596 return;
597 }
Owen Taylor3473f882001-02-23 17:55:21 +0000598 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000599 case XML_ELEMENT_NODE:
600 fprintf(output, shift);
601 fprintf(output, "ELEMENT ");
602 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
603 xmlDebugDumpString(output, node->ns->prefix);
604 fprintf(output, ":");
605 }
606 xmlDebugDumpString(output, node->name);
607 fprintf(output, "\n");
608 break;
609 case XML_ATTRIBUTE_NODE:
610 fprintf(output, shift);
611 fprintf(output, "Error, ATTRIBUTE found here\n");
612 break;
613 case XML_TEXT_NODE:
614 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000615 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000616 fprintf(output, "TEXT no enc\n");
617 else
618 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000619 break;
620 case XML_CDATA_SECTION_NODE:
621 fprintf(output, shift);
622 fprintf(output, "CDATA_SECTION\n");
623 break;
624 case XML_ENTITY_REF_NODE:
625 fprintf(output, shift);
626 fprintf(output, "ENTITY_REF(%s)\n", node->name);
627 break;
628 case XML_ENTITY_NODE:
629 fprintf(output, shift);
630 fprintf(output, "ENTITY\n");
631 break;
632 case XML_PI_NODE:
633 fprintf(output, shift);
634 fprintf(output, "PI %s\n", node->name);
635 break;
636 case XML_COMMENT_NODE:
637 fprintf(output, shift);
638 fprintf(output, "COMMENT\n");
639 break;
640 case XML_DOCUMENT_NODE:
641 case XML_HTML_DOCUMENT_NODE:
642 fprintf(output, shift);
643 fprintf(output, "Error, DOCUMENT found here\n");
644 break;
645 case XML_DOCUMENT_TYPE_NODE:
646 fprintf(output, shift);
647 fprintf(output, "DOCUMENT_TYPE\n");
648 break;
649 case XML_DOCUMENT_FRAG_NODE:
650 fprintf(output, shift);
651 fprintf(output, "DOCUMENT_FRAG\n");
652 break;
653 case XML_NOTATION_NODE:
654 fprintf(output, shift);
655 fprintf(output, "NOTATION\n");
656 break;
657 case XML_DTD_NODE:
658 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
659 return;
660 case XML_ELEMENT_DECL:
661 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
662 return;
663 case XML_ATTRIBUTE_DECL:
664 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
665 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000666 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000667 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
668 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000669 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000670 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
671 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000672 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000673 fprintf(output, shift);
674 fprintf(output, "INCLUDE START\n");
675 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000676 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000677 fprintf(output, shift);
678 fprintf(output, "INCLUDE END\n");
679 return;
680 default:
681 fprintf(output, shift);
682 fprintf(output, "NODE_%d !!!\n", node->type);
683 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000684 }
685 if (node->doc == NULL) {
686 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000687 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000688 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000689 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000690 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
691 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000692 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000693 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000694 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
695 shift[2 * i] = shift[2 * i + 1] = ' ';
696 shift[2 * i + 2] = shift[2 * i + 3] = 0;
697 fprintf(output, shift);
698 fprintf(output, "content=");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000699 xmlDebugDumpString(output, node->content);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000700 fprintf(output, "\n");
701 }
Owen Taylor3473f882001-02-23 17:55:21 +0000702 } else {
703 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000704
705 ent = xmlGetDocEntity(node->doc, node->name);
706 if (ent != NULL)
707 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000708 }
709 /*
710 * Do a bit of checking
711 */
712 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000713 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000714 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000715 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000716 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000717 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000718 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000719 if ((node->parent != NULL) && (node->parent->children != node))
720 fprintf(output,
721 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000722 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000723 if (node->prev->next != node)
724 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000725 }
726 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000727 if ((node->parent != NULL) && (node->parent->last != node))
728 fprintf(output,
729 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000730 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000731 if (node->next->prev != node)
732 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000733 }
734}
735
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000736/**
737 * xmlDebugDumpNode:
738 * @output: the FILE * for the output
739 * @node: the node
740 * @depth: the indentation level.
741 *
742 * Dumps debug information for the element node, it is recursive
743 */
744void
745xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
746{
Daniel Veillard7db38712002-02-07 16:39:11 +0000747 if (output == NULL)
748 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000749 if (node == NULL) {
750 int i;
751 char shift[100];
752
753 for (i = 0; ((i < depth) && (i < 25)); i++)
754 shift[2 * i] = shift[2 * i + 1] = ' ';
755 shift[2 * i] = shift[2 * i + 1] = 0;
756
757 fprintf(output, shift);
758 fprintf(output, "node is NULL\n");
759 return;
760 }
Owen Taylor3473f882001-02-23 17:55:21 +0000761 xmlDebugDumpOneNode(output, node, depth);
762 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000763 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000764}
765
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000766/**
767 * xmlDebugDumpNodeList:
768 * @output: the FILE * for the output
769 * @node: the node list
770 * @depth: the indentation level.
771 *
772 * Dumps debug information for the list of element node, it is recursive
773 */
774void
775xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
776{
Daniel Veillard7db38712002-02-07 16:39:11 +0000777 if (output == NULL)
778 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000779 while (node != NULL) {
780 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000781 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000782 }
783}
784
785
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000786/**
787 * xmlDebugDumpDocumentHead:
788 * @output: the FILE * for the output
789 * @doc: the document
790 *
791 * Dumps debug information cncerning the document, not recursive
792 */
793void
794xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
795{
796 if (output == NULL)
797 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000798 if (doc == NULL) {
799 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000800 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000801 }
802
803 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000804 case XML_ELEMENT_NODE:
805 fprintf(output, "Error, ELEMENT found here ");
806 break;
807 case XML_ATTRIBUTE_NODE:
808 fprintf(output, "Error, ATTRIBUTE found here\n");
809 break;
810 case XML_TEXT_NODE:
811 fprintf(output, "Error, TEXT\n");
812 break;
813 case XML_CDATA_SECTION_NODE:
814 fprintf(output, "Error, CDATA_SECTION\n");
815 break;
816 case XML_ENTITY_REF_NODE:
817 fprintf(output, "Error, ENTITY_REF\n");
818 break;
819 case XML_ENTITY_NODE:
820 fprintf(output, "Error, ENTITY\n");
821 break;
822 case XML_PI_NODE:
823 fprintf(output, "Error, PI\n");
824 break;
825 case XML_COMMENT_NODE:
826 fprintf(output, "Error, COMMENT\n");
827 break;
828 case XML_DOCUMENT_NODE:
829 fprintf(output, "DOCUMENT\n");
830 break;
831 case XML_HTML_DOCUMENT_NODE:
832 fprintf(output, "HTML DOCUMENT\n");
833 break;
834 case XML_DOCUMENT_TYPE_NODE:
835 fprintf(output, "Error, DOCUMENT_TYPE\n");
836 break;
837 case XML_DOCUMENT_FRAG_NODE:
838 fprintf(output, "Error, DOCUMENT_FRAG\n");
839 break;
840 case XML_NOTATION_NODE:
841 fprintf(output, "Error, NOTATION\n");
842 break;
843 default:
844 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000845 }
846 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000847 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000848 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000849 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000850 }
851 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000852 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000853 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000854 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000855 }
856 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000857 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000858 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000859 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000860 }
861 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000862 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000863 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000864 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000865 }
866 if (doc->standalone)
867 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000868 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000869 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
870}
871
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000872/**
873 * xmlDebugDumpDocument:
874 * @output: the FILE * for the output
875 * @doc: the document
876 *
877 * Dumps debug information for the document, it's recursive
878 */
879void
880xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
881{
882 if (output == NULL)
883 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000884 if (doc == NULL) {
885 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000886 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000887 }
888 xmlDebugDumpDocumentHead(output, doc);
889 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000890 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000891 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000892}
Owen Taylor3473f882001-02-23 17:55:21 +0000893
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000894/**
895 * xmlDebugDumpDTD:
896 * @output: the FILE * for the output
897 * @dtd: the DTD
898 *
899 * Dumps debug information for the DTD
900 */
901void
902xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
903{
Daniel Veillard7db38712002-02-07 16:39:11 +0000904 if (output == NULL)
905 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000906 if (dtd == NULL) {
907 fprintf(output, "DTD is NULL\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000908 return;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000909 }
Owen Taylor3473f882001-02-23 17:55:21 +0000910 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000911 fprintf(output, "PBM: not a DTD\n");
912 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000913 }
914 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000915 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000916 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000917 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000918 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000919 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000920 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000921 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000922 fprintf(output, "\n");
923 /*
924 * Do a bit of checking
925 */
926 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000927 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000928 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000929 if ((dtd->parent != NULL)
930 && (dtd->parent->children != (xmlNodePtr) dtd))
931 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000932 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000933 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000934 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000935 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000936 }
937 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000938 if ((dtd->parent != NULL)
939 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000940 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000941 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000942 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000943 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000944 }
945 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000946 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000947 else
948 xmlDebugDumpNodeList(output, dtd->children, 1);
949}
950
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000951static void
952xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000953 if (cur == NULL) {
954 fprintf(output, "Entity is NULL");
955 return;
956 }
Owen Taylor3473f882001-02-23 17:55:21 +0000957 fprintf(output, "%s : ", cur->name);
958 switch (cur->etype) {
959 case XML_INTERNAL_GENERAL_ENTITY:
960 fprintf(output, "INTERNAL GENERAL, ");
961 break;
962 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
963 fprintf(output, "EXTERNAL PARSED, ");
964 break;
965 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
966 fprintf(output, "EXTERNAL UNPARSED, ");
967 break;
968 case XML_INTERNAL_PARAMETER_ENTITY:
969 fprintf(output, "INTERNAL PARAMETER, ");
970 break;
971 case XML_EXTERNAL_PARAMETER_ENTITY:
972 fprintf(output, "EXTERNAL PARAMETER, ");
973 break;
974 default:
975 fprintf(output, "UNKNOWN TYPE %d",
976 cur->etype);
977 }
978 if (cur->ExternalID != NULL)
979 fprintf(output, "ID \"%s\"", cur->ExternalID);
980 if (cur->SystemID != NULL)
981 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
982 if (cur->orig != NULL)
983 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000984 if ((cur->type != XML_ELEMENT_NODE) &&
985 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000986 fprintf(output, "\n content \"%s\"", cur->content);
987 fprintf(output, "\n");
988}
989
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000990/**
991 * xmlDebugDumpEntities:
992 * @output: the FILE * for the output
993 * @doc: the document
994 *
995 * Dumps debug information for all the entities in use by the document
996 */
997void
998xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
999{
1000 if (output == NULL)
1001 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001002 if (doc == NULL) {
1003 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001004 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001005 }
1006
1007 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001008 case XML_ELEMENT_NODE:
1009 fprintf(output, "Error, ELEMENT found here ");
1010 break;
1011 case XML_ATTRIBUTE_NODE:
1012 fprintf(output, "Error, ATTRIBUTE found here\n");
1013 break;
1014 case XML_TEXT_NODE:
1015 fprintf(output, "Error, TEXT\n");
1016 break;
1017 case XML_CDATA_SECTION_NODE:
1018 fprintf(output, "Error, CDATA_SECTION\n");
1019 break;
1020 case XML_ENTITY_REF_NODE:
1021 fprintf(output, "Error, ENTITY_REF\n");
1022 break;
1023 case XML_ENTITY_NODE:
1024 fprintf(output, "Error, ENTITY\n");
1025 break;
1026 case XML_PI_NODE:
1027 fprintf(output, "Error, PI\n");
1028 break;
1029 case XML_COMMENT_NODE:
1030 fprintf(output, "Error, COMMENT\n");
1031 break;
1032 case XML_DOCUMENT_NODE:
1033 fprintf(output, "DOCUMENT\n");
1034 break;
1035 case XML_HTML_DOCUMENT_NODE:
1036 fprintf(output, "HTML DOCUMENT\n");
1037 break;
1038 case XML_DOCUMENT_TYPE_NODE:
1039 fprintf(output, "Error, DOCUMENT_TYPE\n");
1040 break;
1041 case XML_DOCUMENT_FRAG_NODE:
1042 fprintf(output, "Error, DOCUMENT_FRAG\n");
1043 break;
1044 case XML_NOTATION_NODE:
1045 fprintf(output, "Error, NOTATION\n");
1046 break;
1047 default:
1048 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +00001049 }
1050 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001051 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1052 doc->intSubset->entities;
1053
1054 fprintf(output, "Entities in internal subset\n");
1055 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1056 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001057 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001058 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001059 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001060 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1061 doc->extSubset->entities;
1062
1063 fprintf(output, "Entities in external subset\n");
1064 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1065 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001066 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001067 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001068}
1069
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001070/**
1071 * xmlLsCountNode:
1072 * @node: the node to count
1073 *
1074 * Count the children of @node.
1075 *
1076 * Returns the number of children of @node.
1077 */
1078int
1079xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001080 int ret = 0;
1081 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001082
1083 if (node == NULL)
1084 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001085
1086 switch (node->type) {
1087 case XML_ELEMENT_NODE:
1088 list = node->children;
1089 break;
1090 case XML_DOCUMENT_NODE:
1091 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001092#ifdef LIBXML_DOCB_ENABLED
1093 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001094#endif
1095 list = ((xmlDocPtr) node)->children;
1096 break;
1097 case XML_ATTRIBUTE_NODE:
1098 list = ((xmlAttrPtr) node)->children;
1099 break;
1100 case XML_TEXT_NODE:
1101 case XML_CDATA_SECTION_NODE:
1102 case XML_PI_NODE:
1103 case XML_COMMENT_NODE:
1104 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001105 ret = xmlStrlen(node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001106 }
1107 break;
1108 case XML_ENTITY_REF_NODE:
1109 case XML_DOCUMENT_TYPE_NODE:
1110 case XML_ENTITY_NODE:
1111 case XML_DOCUMENT_FRAG_NODE:
1112 case XML_NOTATION_NODE:
1113 case XML_DTD_NODE:
1114 case XML_ELEMENT_DECL:
1115 case XML_ATTRIBUTE_DECL:
1116 case XML_ENTITY_DECL:
1117 case XML_NAMESPACE_DECL:
1118 case XML_XINCLUDE_START:
1119 case XML_XINCLUDE_END:
1120 ret = 1;
1121 break;
1122 }
1123 for (;list != NULL;ret++)
1124 list = list->next;
1125 return(ret);
1126}
1127
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001128/**
1129 * xmlLsOneNode:
1130 * @output: the FILE * for the output
1131 * @node: the node to dump
1132 *
1133 * Dump to @output the type and name of @node.
1134 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001135void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001136xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001137 if (node == NULL) {
1138 fprintf(output, "NULL\n");
1139 return;
1140 }
Owen Taylor3473f882001-02-23 17:55:21 +00001141 switch (node->type) {
1142 case XML_ELEMENT_NODE:
1143 fprintf(output, "-");
1144 break;
1145 case XML_ATTRIBUTE_NODE:
1146 fprintf(output, "a");
1147 break;
1148 case XML_TEXT_NODE:
1149 fprintf(output, "t");
1150 break;
1151 case XML_CDATA_SECTION_NODE:
Daniel Veillard75be0132002-03-13 10:03:35 +00001152 fprintf(output, "C");
Owen Taylor3473f882001-02-23 17:55:21 +00001153 break;
1154 case XML_ENTITY_REF_NODE:
1155 fprintf(output, "e");
1156 break;
1157 case XML_ENTITY_NODE:
1158 fprintf(output, "E");
1159 break;
1160 case XML_PI_NODE:
1161 fprintf(output, "p");
1162 break;
1163 case XML_COMMENT_NODE:
1164 fprintf(output, "c");
1165 break;
1166 case XML_DOCUMENT_NODE:
1167 fprintf(output, "d");
1168 break;
1169 case XML_HTML_DOCUMENT_NODE:
1170 fprintf(output, "h");
1171 break;
1172 case XML_DOCUMENT_TYPE_NODE:
1173 fprintf(output, "T");
1174 break;
1175 case XML_DOCUMENT_FRAG_NODE:
1176 fprintf(output, "F");
1177 break;
1178 case XML_NOTATION_NODE:
1179 fprintf(output, "N");
1180 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001181 case XML_NAMESPACE_DECL:
1182 fprintf(output, "n");
1183 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001184 default:
1185 fprintf(output, "?");
1186 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001187 if (node->type != XML_NAMESPACE_DECL) {
1188 if (node->properties != NULL)
1189 fprintf(output, "a");
1190 else
1191 fprintf(output, "-");
1192 if (node->nsDef != NULL)
1193 fprintf(output, "n");
1194 else
1195 fprintf(output, "-");
1196 }
Owen Taylor3473f882001-02-23 17:55:21 +00001197
1198 fprintf(output, " %8d ", xmlLsCountNode(node));
1199
1200 switch (node->type) {
1201 case XML_ELEMENT_NODE:
1202 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001203 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001204 break;
1205 case XML_ATTRIBUTE_NODE:
1206 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001207 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001208 break;
1209 case XML_TEXT_NODE:
1210 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001211 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001212 }
1213 break;
1214 case XML_CDATA_SECTION_NODE:
1215 break;
1216 case XML_ENTITY_REF_NODE:
1217 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001218 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001219 break;
1220 case XML_ENTITY_NODE:
1221 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001222 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001223 break;
1224 case XML_PI_NODE:
1225 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001226 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001227 break;
1228 case XML_COMMENT_NODE:
1229 break;
1230 case XML_DOCUMENT_NODE:
1231 break;
1232 case XML_HTML_DOCUMENT_NODE:
1233 break;
1234 case XML_DOCUMENT_TYPE_NODE:
1235 break;
1236 case XML_DOCUMENT_FRAG_NODE:
1237 break;
1238 case XML_NOTATION_NODE:
1239 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001240 case XML_NAMESPACE_DECL: {
1241 xmlNsPtr ns = (xmlNsPtr) node;
1242
1243 if (ns->prefix == NULL)
1244 fprintf(output, "default -> %s", ns->href);
1245 else
1246 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1247 break;
1248 }
Owen Taylor3473f882001-02-23 17:55:21 +00001249 default:
1250 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001251 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001252 }
1253 fprintf(output, "\n");
1254}
1255
Daniel Veillard78d12092001-10-11 09:12:24 +00001256/**
1257 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001258 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001259 *
1260 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001261 *
1262 * Returns a pointer to either "True" or "False"
1263 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001264const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001265xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001266{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001267 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001268 return("True");
1269 else
1270 return("False");
1271}
1272
Owen Taylor3473f882001-02-23 17:55:21 +00001273/****************************************************************
1274 * *
1275 * The XML shell related functions *
1276 * *
1277 ****************************************************************/
1278
Daniel Veillard78d12092001-10-11 09:12:24 +00001279
1280
Owen Taylor3473f882001-02-23 17:55:21 +00001281/*
1282 * TODO: Improvement/cleanups for the XML shell
1283 * - allow to shell out an editor on a subpart
1284 * - cleanup function registrations (with help) and calling
1285 * - provide registration routines
1286 */
1287
1288/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001289 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001290 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001291 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001292 *
1293 * Print the xpath error to libxml default error channel
1294 */
1295void
1296xmlShellPrintXPathError(int errorType, const char *arg)
1297{
1298 const char *default_arg = "Result";
1299
1300 if (!arg)
1301 arg = default_arg;
1302
1303 switch (errorType) {
1304 case XPATH_UNDEFINED:
1305 xmlGenericError(xmlGenericErrorContext,
1306 "%s: no such node\n", arg);
1307 break;
1308
1309 case XPATH_BOOLEAN:
1310 xmlGenericError(xmlGenericErrorContext,
1311 "%s is a Boolean\n", arg);
1312 break;
1313 case XPATH_NUMBER:
1314 xmlGenericError(xmlGenericErrorContext,
1315 "%s is a number\n", arg);
1316 break;
1317 case XPATH_STRING:
1318 xmlGenericError(xmlGenericErrorContext,
1319 "%s is a string\n", arg);
1320 break;
1321 case XPATH_POINT:
1322 xmlGenericError(xmlGenericErrorContext,
1323 "%s is a point\n", arg);
1324 break;
1325 case XPATH_RANGE:
1326 xmlGenericError(xmlGenericErrorContext,
1327 "%s is a range\n", arg);
1328 break;
1329 case XPATH_LOCATIONSET:
1330 xmlGenericError(xmlGenericErrorContext,
1331 "%s is a range\n", arg);
1332 break;
1333 case XPATH_USERS:
1334 xmlGenericError(xmlGenericErrorContext,
1335 "%s is user-defined\n", arg);
1336 break;
1337 case XPATH_XSLT_TREE:
1338 xmlGenericError(xmlGenericErrorContext,
1339 "%s is an XSLT value tree\n", arg);
1340 break;
1341 }
1342 xmlGenericError(xmlGenericErrorContext,
1343 "Try casting the result string function (xpath builtin)\n",
1344 arg);
1345}
1346
1347
1348/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001349 * xmlShellPrintNodeCtxt:
1350 * @ctxt : a non-null shell context
1351 * @node : a non-null node to print to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001352 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001353 * Print node to the output FILE
1354 */
1355static void
1356xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1357{
Daniel Veillard01992e02002-10-09 10:20:30 +00001358 FILE *fp;
1359
1360 if (!node)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001361 return;
Daniel Veillard01992e02002-10-09 10:20:30 +00001362 if (ctxt == NULL)
1363 fp = stdout;
1364 else
1365 fp = ctxt->output;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001366
1367 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001368 xmlDocDump(fp, (xmlDocPtr) node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001369 else if (node->type == XML_ATTRIBUTE_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001370 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001371 else
Daniel Veillard01992e02002-10-09 10:20:30 +00001372 xmlElemDump(fp, node->doc, node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001373
Daniel Veillard01992e02002-10-09 10:20:30 +00001374 fprintf(fp, "\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00001375}
1376
1377/**
1378 * xmlShellPrintNode:
1379 * @node : a non-null node to print to the output FILE
1380 *
1381 * Print node to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001382 */
1383void
1384xmlShellPrintNode(xmlNodePtr node)
1385{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001386 xmlShellPrintNodeCtxt(NULL, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001387}
1388
Daniel Veillard78d12092001-10-11 09:12:24 +00001389/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001390 * xmlShellPrintXPathResultCtxt:
1391 * @ctxt: a valid shell context
Daniel Veillard9d06d302002-01-22 18:15:52 +00001392 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001393 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001394 * Prints result to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001395 */
Daniel Veillard321be0c2002-10-08 21:26:42 +00001396static void
1397xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
Daniel Veillard78d12092001-10-11 09:12:24 +00001398{
1399 int i = 0;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001400 if (!ctxt)
1401 return;
Daniel Veillard78d12092001-10-11 09:12:24 +00001402
1403 if (list != NULL) {
1404 switch (list->type) {
1405 case XPATH_NODESET:{
1406 int indx;
1407
1408 if (list->nodesetval) {
1409 for (indx = 0; indx < list->nodesetval->nodeNr;
1410 indx++) {
1411 if (i > 0)
1412 fprintf(stderr, " -------\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00001413 xmlShellPrintNodeCtxt(ctxt,
1414 list->nodesetval->nodeTab[indx]);
Daniel Veillard78d12092001-10-11 09:12:24 +00001415 }
1416 } else {
1417 xmlGenericError(xmlGenericErrorContext,
1418 "Empty node set\n");
1419 }
1420 break;
1421 }
1422 case XPATH_BOOLEAN:
1423 xmlGenericError(xmlGenericErrorContext,
1424 "Is a Boolean:%s\n",
1425 xmlBoolToText(list->boolval));
1426 break;
1427 case XPATH_NUMBER:
1428 xmlGenericError(xmlGenericErrorContext,
1429 "Is a number:%0g\n", list->floatval);
1430 break;
1431 case XPATH_STRING:
1432 xmlGenericError(xmlGenericErrorContext,
1433 "Is a string:%s\n", list->stringval);
1434 break;
1435
1436 default:
1437 xmlShellPrintXPathError(list->type, NULL);
1438 }
1439 }
1440}
1441
1442/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001443 * xmlShellPrintXPathResult:
1444 * @list: a valid result generated by an xpath evaluation
1445 *
1446 * Prints result to the output FILE
1447 */
1448void
1449xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1450{
1451 xmlShellPrintXPathResultCtxt(NULL, list);
1452}
1453
1454/**
Owen Taylor3473f882001-02-23 17:55:21 +00001455 * xmlShellList:
1456 * @ctxt: the shell context
1457 * @arg: unused
1458 * @node: a node
1459 * @node2: unused
1460 *
1461 * Implements the XML shell function "ls"
1462 * Does an Unix like listing of the given node (like a directory)
1463 *
1464 * Returns 0
1465 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001466int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001467xmlShellList(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001468 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1469 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1470{
Owen Taylor3473f882001-02-23 17:55:21 +00001471 xmlNodePtr cur;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001472 if (!ctxt)
1473 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001474 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001475 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001476 return (0);
1477 }
Owen Taylor3473f882001-02-23 17:55:21 +00001478 if ((node->type == XML_DOCUMENT_NODE) ||
1479 (node->type == XML_HTML_DOCUMENT_NODE)) {
1480 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001481 } else if (node->type == XML_NAMESPACE_DECL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001482 xmlLsOneNode(ctxt->output, node);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001483 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001484 } else if (node->children != NULL) {
1485 cur = node->children;
1486 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001487 xmlLsOneNode(ctxt->output, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001488 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001489 }
1490 while (cur != NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001491 xmlLsOneNode(ctxt->output, cur);
Daniel Veillard78d12092001-10-11 09:12:24 +00001492 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001493 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001494 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001495}
1496
1497/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001498 * xmlShellBase:
1499 * @ctxt: the shell context
1500 * @arg: unused
1501 * @node: a node
1502 * @node2: unused
1503 *
1504 * Implements the XML shell function "base"
1505 * dumps the current XML base of the node
1506 *
1507 * Returns 0
1508 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001509int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001510xmlShellBase(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001511 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1512 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1513{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001514 xmlChar *base;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001515 if (!ctxt)
1516 return 0;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001517 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001518 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001519 return (0);
1520 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001521
1522 base = xmlNodeGetBase(node->doc, node);
1523
1524 if (base == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001525 fprintf(ctxt->output, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001526 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001527 fprintf(ctxt->output, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001528 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001529 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001530 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001531}
1532
1533/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001534 * xmlShellSetBase:
1535 * @ctxt: the shell context
1536 * @arg: the new base
1537 * @node: a node
1538 * @node2: unused
1539 *
1540 * Implements the XML shell function "setbase"
1541 * change the current XML base of the node
1542 *
1543 * Returns 0
1544 */
1545static int
1546xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1547 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1548 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1549{
1550 xmlNodeSetBase(node, (xmlChar*) arg);
1551 return (0);
1552}
1553
1554/**
Daniel Veillard1e208222002-10-22 14:25:25 +00001555 * xmlShellGrep:
1556 * @ctxt: the shell context
1557 * @arg: the string or regular expression to find
1558 * @node: a node
1559 * @node2: unused
1560 *
1561 * Implements the XML shell function "grep"
1562 * dumps informations about the node (namespace, attributes, content).
1563 *
1564 * Returns 0
1565 */
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001566static int
Daniel Veillard1e208222002-10-22 14:25:25 +00001567xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1568 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1569{
1570 if (!ctxt)
1571 return (0);
1572 if (node == NULL)
1573 return (0);
1574 if (arg == NULL)
1575 return (0);
1576#ifdef LIBXML_REGEXP_ENABLED
1577 if ((xmlStrchr((xmlChar *) arg, '?')) ||
1578 (xmlStrchr((xmlChar *) arg, '*')) ||
1579 (xmlStrchr((xmlChar *) arg, '.')) ||
1580 (xmlStrchr((xmlChar *) arg, '['))) {
1581 }
1582#endif
1583 while (node != NULL) {
1584 if (node->type == XML_COMMENT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001585 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001586
1587 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
1588 xmlShellList(ctxt, NULL, node, NULL);
1589 }
1590 } else if (node->type == XML_TEXT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001591 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001592
1593 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001594 xmlShellList(ctxt, NULL, node->parent, NULL);
Daniel Veillard1e208222002-10-22 14:25:25 +00001595 }
1596 }
1597
1598 /*
1599 * Browse the full subtree, deep first
1600 */
1601
1602 if ((node->type == XML_DOCUMENT_NODE) ||
1603 (node->type == XML_HTML_DOCUMENT_NODE)) {
1604 node = ((xmlDocPtr) node)->children;
1605 } else if ((node->children != NULL)
1606 && (node->type != XML_ENTITY_REF_NODE)) {
1607 /* deep first */
1608 node = node->children;
1609 } else if (node->next != NULL) {
1610 /* then siblings */
1611 node = node->next;
1612 } else {
1613 /* go up to parents->next if needed */
1614 while (node != NULL) {
1615 if (node->parent != NULL) {
1616 node = node->parent;
1617 }
1618 if (node->next != NULL) {
1619 node = node->next;
1620 break;
1621 }
1622 if (node->parent == NULL) {
1623 node = NULL;
1624 break;
1625 }
1626 }
1627 }
1628 }
1629 return (0);
1630}
1631
1632/**
Owen Taylor3473f882001-02-23 17:55:21 +00001633 * xmlShellDir:
1634 * @ctxt: the shell context
1635 * @arg: unused
1636 * @node: a node
1637 * @node2: unused
1638 *
1639 * Implements the XML shell function "dir"
1640 * dumps informations about the node (namespace, attributes, content).
1641 *
1642 * Returns 0
1643 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001644int
1645xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1646 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1647 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1648{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001649 if (!ctxt)
1650 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001651 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001652 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001653 return (0);
1654 }
Owen Taylor3473f882001-02-23 17:55:21 +00001655 if ((node->type == XML_DOCUMENT_NODE) ||
1656 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001657 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001658 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001659 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001660 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001661 xmlDebugDumpOneNode(ctxt->output, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001662 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001663 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001664}
1665
1666/**
1667 * xmlShellCat:
1668 * @ctxt: the shell context
1669 * @arg: unused
1670 * @node: a node
1671 * @node2: unused
1672 *
1673 * Implements the XML shell function "cat"
1674 * dumps the serialization node content (XML or HTML).
1675 *
1676 * Returns 0
1677 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001678int
1679xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1680 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1681{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001682 if (!ctxt)
1683 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001684 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001685 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001686 return (0);
1687 }
Owen Taylor3473f882001-02-23 17:55:21 +00001688 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1689#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001690 if (node->type == XML_HTML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001691 htmlDocDump(ctxt->output, (htmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001692 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001693 htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001694#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001695 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001696 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001697 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001698 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001699#endif /* LIBXML_HTML_ENABLED */
1700 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001701 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001702 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001703 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001704 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001705 }
Daniel Veillard321be0c2002-10-08 21:26:42 +00001706 fprintf(ctxt->output, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001707 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001708}
1709
1710/**
1711 * xmlShellLoad:
1712 * @ctxt: the shell context
1713 * @filename: the file name
1714 * @node: unused
1715 * @node2: unused
1716 *
1717 * Implements the XML shell function "load"
1718 * loads a new document specified by the filename
1719 *
1720 * Returns 0 or -1 if loading failed
1721 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001722int
1723xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1724 xmlNodePtr node ATTRIBUTE_UNUSED,
1725 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1726{
Owen Taylor3473f882001-02-23 17:55:21 +00001727 xmlDocPtr doc;
1728 int html = 0;
1729
1730 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001731 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001732
1733 if (html) {
1734#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001735 doc = htmlParseFile(filename, NULL);
1736#else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001737 fprintf(ctxt->output, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001738 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001739#endif /* LIBXML_HTML_ENABLED */
1740 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001741 doc = xmlParseFile(filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001742 }
1743 if (doc != NULL) {
1744 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001745 xmlFreeDoc(ctxt->doc);
1746 }
1747 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001748#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001749 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001750#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001751 xmlFree(ctxt->filename);
1752 ctxt->doc = doc;
1753 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001754#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001755 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001756#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001757 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001758 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001759 return (-1);
1760 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001761}
1762
1763/**
1764 * xmlShellWrite:
1765 * @ctxt: the shell context
1766 * @filename: the file name
1767 * @node: a node in the tree
1768 * @node2: unused
1769 *
1770 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001771 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001772 * of the subtree under the @node specified
1773 *
1774 * Returns 0 or -1 in case of error
1775 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001776int
Owen Taylor3473f882001-02-23 17:55:21 +00001777xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001778 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1779{
Owen Taylor3473f882001-02-23 17:55:21 +00001780 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001781 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001782 if ((filename == NULL) || (filename[0] == 0)) {
1783 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001784 "Write command requires a filename argument\n");
1785 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001786 }
1787#ifdef W_OK
1788 if (access((char *) filename, W_OK)) {
1789 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001790 "Cannot write to %s\n", filename);
1791 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001792 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001793#endif
1794 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001795 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001796 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1797 xmlGenericError(xmlGenericErrorContext,
1798 "Failed to write to %s\n", filename);
1799 return (-1);
1800 }
1801 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001802 case XML_HTML_DOCUMENT_NODE:
1803#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001804 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1805 xmlGenericError(xmlGenericErrorContext,
1806 "Failed to write to %s\n", filename);
1807 return (-1);
1808 }
Owen Taylor3473f882001-02-23 17:55:21 +00001809#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001810 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1811 xmlGenericError(xmlGenericErrorContext,
1812 "Failed to write to %s\n", filename);
1813 return (-1);
1814 }
Owen Taylor3473f882001-02-23 17:55:21 +00001815#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001816 break;
1817 default:{
1818 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001819
Daniel Veillard78d12092001-10-11 09:12:24 +00001820 f = fopen((char *) filename, "w");
1821 if (f == NULL) {
1822 xmlGenericError(xmlGenericErrorContext,
1823 "Failed to write to %s\n", filename);
1824 return (-1);
1825 }
1826 xmlElemDump(f, ctxt->doc, node);
1827 fclose(f);
1828 }
Owen Taylor3473f882001-02-23 17:55:21 +00001829 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001830 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001831}
1832
1833/**
1834 * xmlShellSave:
1835 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001836 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001837 * @node: unused
1838 * @node2: unused
1839 *
1840 * Implements the XML shell function "save"
1841 * Write the current document to the filename, or it's original name
1842 *
1843 * Returns 0 or -1 in case of error
1844 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001845int
1846xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1847 xmlNodePtr node ATTRIBUTE_UNUSED,
1848 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1849{
Owen Taylor3473f882001-02-23 17:55:21 +00001850 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001851 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001852 if ((filename == NULL) || (filename[0] == 0))
1853 filename = ctxt->filename;
1854#ifdef W_OK
1855 if (access((char *) filename, W_OK)) {
1856 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001857 "Cannot save to %s\n", filename);
1858 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001859 }
1860#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001861 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001862 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001863 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1864 xmlGenericError(xmlGenericErrorContext,
1865 "Failed to save to %s\n", filename);
1866 }
1867 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001868 case XML_HTML_DOCUMENT_NODE:
1869#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001870 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1871 xmlGenericError(xmlGenericErrorContext,
1872 "Failed to save to %s\n", filename);
1873 }
Owen Taylor3473f882001-02-23 17:55:21 +00001874#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001875 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1876 xmlGenericError(xmlGenericErrorContext,
1877 "Failed to save to %s\n", filename);
1878 }
Owen Taylor3473f882001-02-23 17:55:21 +00001879#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001880 break;
1881 default:
1882 xmlGenericError(xmlGenericErrorContext,
1883 "To save to subparts of a document use the 'write' command\n");
1884 return (-1);
1885
Owen Taylor3473f882001-02-23 17:55:21 +00001886 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001887 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001888}
1889
1890/**
1891 * xmlShellValidate:
1892 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001893 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001894 * @node: unused
1895 * @node2: unused
1896 *
1897 * Implements the XML shell function "validate"
1898 * Validate the document, if a DTD path is provided, then the validation
1899 * is done against the given DTD.
1900 *
1901 * Returns 0 or -1 in case of error
1902 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001903int
1904xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1905 xmlNodePtr node ATTRIBUTE_UNUSED,
1906 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1907{
Owen Taylor3473f882001-02-23 17:55:21 +00001908 xmlValidCtxt vctxt;
1909 int res = -1;
1910
1911 vctxt.userData = stderr;
1912 vctxt.error = (xmlValidityErrorFunc) fprintf;
1913 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1914
1915 if ((dtd == NULL) || (dtd[0] == 0)) {
1916 res = xmlValidateDocument(&vctxt, ctxt->doc);
1917 } else {
1918 xmlDtdPtr subset;
1919
Daniel Veillard78d12092001-10-11 09:12:24 +00001920 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1921 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001922 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1923
Daniel Veillard78d12092001-10-11 09:12:24 +00001924 xmlFreeDtd(subset);
1925 }
Owen Taylor3473f882001-02-23 17:55:21 +00001926 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001927 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00001928}
1929
1930/**
1931 * xmlShellDu:
1932 * @ctxt: the shell context
1933 * @arg: unused
1934 * @tree: a node defining a subtree
1935 * @node2: unused
1936 *
1937 * Implements the XML shell function "du"
1938 * show the structure of the subtree under node @tree
1939 * If @tree is null, the command works on the current node.
1940 *
1941 * Returns 0 or -1 in case of error
1942 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001943int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001944xmlShellDu(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001945 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1946 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1947{
Owen Taylor3473f882001-02-23 17:55:21 +00001948 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00001949 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00001950
Daniel Veillard321be0c2002-10-08 21:26:42 +00001951 if (!ctxt)
1952 return (-1);
1953
Daniel Veillard78d12092001-10-11 09:12:24 +00001954 if (tree == NULL)
1955 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001956 node = tree;
1957 while (node != NULL) {
1958 if ((node->type == XML_DOCUMENT_NODE) ||
1959 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001960 fprintf(ctxt->output, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001961 } else if (node->type == XML_ELEMENT_NODE) {
1962 for (i = 0; i < indent; i++)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001963 fprintf(ctxt->output, " ");
1964 fprintf(ctxt->output, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00001965 } else {
1966 }
Owen Taylor3473f882001-02-23 17:55:21 +00001967
Daniel Veillard78d12092001-10-11 09:12:24 +00001968 /*
1969 * Browse the full subtree, deep first
1970 */
Owen Taylor3473f882001-02-23 17:55:21 +00001971
1972 if ((node->type == XML_DOCUMENT_NODE) ||
1973 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001974 node = ((xmlDocPtr) node)->children;
1975 } else if ((node->children != NULL)
1976 && (node->type != XML_ENTITY_REF_NODE)) {
1977 /* deep first */
1978 node = node->children;
1979 indent++;
1980 } else if ((node != tree) && (node->next != NULL)) {
1981 /* then siblings */
1982 node = node->next;
1983 } else if (node != tree) {
1984 /* go up to parents->next if needed */
1985 while (node != tree) {
1986 if (node->parent != NULL) {
1987 node = node->parent;
1988 indent--;
1989 }
1990 if ((node != tree) && (node->next != NULL)) {
1991 node = node->next;
1992 break;
1993 }
1994 if (node->parent == NULL) {
1995 node = NULL;
1996 break;
1997 }
1998 if (node == tree) {
1999 node = NULL;
2000 break;
2001 }
2002 }
2003 /* exit condition */
2004 if (node == tree)
2005 node = NULL;
2006 } else
2007 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002008 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002009 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002010}
2011
2012/**
2013 * xmlShellPwd:
2014 * @ctxt: the shell context
2015 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00002016 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00002017 * @node2: unused
2018 *
2019 * Implements the XML shell function "pwd"
2020 * Show the full path from the root to the node, if needed building
2021 * thumblers when similar elements exists at a given ancestor level.
2022 * The output is compatible with XPath commands.
2023 *
2024 * Returns 0 or -1 in case of error
2025 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002026int
2027xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2028 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2029{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002030 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00002031
Daniel Veillard78d12092001-10-11 09:12:24 +00002032 if (node == NULL)
2033 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002034
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002035 path = xmlGetNodePath(node);
2036 if (path == NULL)
2037 return (-1);
2038
2039 /*
2040 * This test prevents buffer overflow, because this routine
2041 * is only called by xmlShell, in which the second argument is
2042 * 500 chars long.
2043 * It is a dirty hack before a cleaner solution is found.
2044 * Documentation should mention that the second argument must
2045 * be at least 500 chars long, and could be stripped if too long.
2046 */
2047 snprintf(buffer, 499, "%s", path);
2048 buffer[499] = '0';
2049 xmlFree(path);
2050
Daniel Veillard78d12092001-10-11 09:12:24 +00002051 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002052}
2053
2054/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002055 * xmlShell:
Owen Taylor3473f882001-02-23 17:55:21 +00002056 * @doc: the initial document
2057 * @filename: the output buffer
2058 * @input: the line reading function
Daniel Veillard321be0c2002-10-08 21:26:42 +00002059 * @output: the output FILE*, defaults to stdout if NULL
Owen Taylor3473f882001-02-23 17:55:21 +00002060 *
2061 * Implements the XML shell
2062 * This allow to load, validate, view, modify and save a document
2063 * using a environment similar to a UNIX commandline.
2064 */
2065void
2066xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00002067 FILE * output)
2068{
Owen Taylor3473f882001-02-23 17:55:21 +00002069 char prompt[500] = "/ > ";
2070 char *cmdline = NULL, *cur;
2071 int nbargs;
2072 char command[100];
2073 char arg[400];
2074 int i;
2075 xmlShellCtxtPtr ctxt;
2076 xmlXPathObjectPtr list;
2077
2078 if (doc == NULL)
2079 return;
2080 if (filename == NULL)
2081 return;
2082 if (input == NULL)
2083 return;
2084 if (output == NULL)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002085 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00002086 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00002087 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00002088 return;
2089 ctxt->loaded = 0;
2090 ctxt->doc = doc;
2091 ctxt->input = input;
2092 ctxt->output = output;
2093 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00002094 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00002095
2096#ifdef LIBXML_XPATH_ENABLED
2097 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2098 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002099 xmlFree(ctxt);
2100 return;
Owen Taylor3473f882001-02-23 17:55:21 +00002101 }
2102#endif /* LIBXML_XPATH_ENABLED */
2103 while (1) {
2104 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002105 snprintf(prompt, sizeof(prompt), "%s > ", "/");
Daniel Veillard78d12092001-10-11 09:12:24 +00002106 else if (ctxt->node->name)
2107 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00002108 else
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002109 snprintf(prompt, sizeof(prompt), "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00002110 prompt[sizeof(prompt) - 1] = 0;
2111
Daniel Veillard78d12092001-10-11 09:12:24 +00002112 /*
2113 * Get a new command line
2114 */
Owen Taylor3473f882001-02-23 17:55:21 +00002115 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00002116 if (cmdline == NULL)
2117 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002118
Daniel Veillard78d12092001-10-11 09:12:24 +00002119 /*
2120 * Parse the command itself
2121 */
2122 cur = cmdline;
2123 nbargs = 0;
2124 while ((*cur == ' ') || (*cur == '\t'))
2125 cur++;
2126 i = 0;
2127 while ((*cur != ' ') && (*cur != '\t') &&
2128 (*cur != '\n') && (*cur != '\r')) {
2129 if (*cur == 0)
2130 break;
2131 command[i++] = *cur++;
2132 }
2133 command[i] = 0;
2134 if (i == 0)
2135 continue;
2136 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002137
Daniel Veillard78d12092001-10-11 09:12:24 +00002138 /*
2139 * Parse the argument
2140 */
2141 while ((*cur == ' ') || (*cur == '\t'))
2142 cur++;
2143 i = 0;
2144 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2145 if (*cur == 0)
2146 break;
2147 arg[i++] = *cur++;
2148 }
2149 arg[i] = 0;
2150 if (i != 0)
2151 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002152
Daniel Veillard78d12092001-10-11 09:12:24 +00002153 /*
2154 * start interpreting the command
2155 */
Owen Taylor3473f882001-02-23 17:55:21 +00002156 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002157 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002158 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002159 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002160 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002161 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002162 if (!strcmp(command, "help")) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002163 fprintf(ctxt->output, "\tbase display XML base of the node\n");
2164 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2165 fprintf(ctxt->output, "\tbye leave shell\n");
2166 fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2167 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2168 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2169 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2170 fprintf(ctxt->output, "\texit leave shell\n");
2171 fprintf(ctxt->output, "\thelp display this help\n");
2172 fprintf(ctxt->output, "\tfree display memory usage\n");
2173 fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2174 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002175#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002176 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002177#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard321be0c2002-10-08 21:26:42 +00002178 fprintf(ctxt->output, "\tpwd display current working directory\n");
2179 fprintf(ctxt->output, "\tquit leave shell\n");
2180 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
2181 fprintf(ctxt->output, "\tvalidate check the document for errors\n");
2182 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
Daniel Veillard1e208222002-10-22 14:25:25 +00002183 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
Daniel Veillard5004f422001-11-08 13:53:05 +00002184 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002185 xmlShellValidate(ctxt, arg, NULL, NULL);
2186 } else if (!strcmp(command, "load")) {
2187 xmlShellLoad(ctxt, arg, NULL, NULL);
2188 } else if (!strcmp(command, "save")) {
2189 xmlShellSave(ctxt, arg, NULL, NULL);
2190 } else if (!strcmp(command, "write")) {
2191 xmlShellWrite(ctxt, arg, NULL, NULL);
Daniel Veillard1e208222002-10-22 14:25:25 +00002192 } else if (!strcmp(command, "grep")) {
2193 xmlShellGrep(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002194 } else if (!strcmp(command, "free")) {
2195 if (arg[0] == 0) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002196 xmlMemShow(ctxt->output, 0);
Daniel Veillard78d12092001-10-11 09:12:24 +00002197 } else {
2198 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002199
Daniel Veillard78d12092001-10-11 09:12:24 +00002200 sscanf(arg, "%d", &len);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002201 xmlMemShow(ctxt->output, len);
Daniel Veillard78d12092001-10-11 09:12:24 +00002202 }
2203 } else if (!strcmp(command, "pwd")) {
2204 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002205
Daniel Veillard78d12092001-10-11 09:12:24 +00002206 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillard321be0c2002-10-08 21:26:42 +00002207 fprintf(ctxt->output, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002208 } else if (!strcmp(command, "du")) {
2209 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2210 } else if (!strcmp(command, "base")) {
2211 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002212#ifdef LIBXML_XPATH_ENABLED
2213 } else if (!strcmp(command, "xpath")) {
2214 if (arg[0] == 0) {
2215 xmlGenericError(xmlGenericErrorContext,
2216 "xpath: expression required\n");
2217 } else {
2218 ctxt->pctxt->node = ctxt->node;
2219 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002220 xmlXPathDebugDumpObject(ctxt->output, list, 0);
Daniel Veillard2070c482002-01-22 22:12:19 +00002221 xmlXPathFreeObject(list);
2222 }
2223#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002224 } else if (!strcmp(command, "setbase")) {
2225 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002226 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2227 int dir = (!strcmp(command, "dir"));
2228
2229 if (arg[0] == 0) {
2230 if (dir)
2231 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2232 else
2233 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2234 } else {
2235 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002236#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002237 ctxt->pctxt->node = ctxt->node;
2238 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2239#else
2240 list = NULL;
2241#endif /* LIBXML_XPATH_ENABLED */
2242 if (list != NULL) {
2243 switch (list->type) {
2244 case XPATH_UNDEFINED:
2245 xmlGenericError(xmlGenericErrorContext,
2246 "%s: no such node\n", arg);
2247 break;
2248 case XPATH_NODESET:{
2249 int indx;
2250
Daniel Veillarda6825e82001-11-07 13:33:59 +00002251 if (list->nodesetval == NULL)
2252 break;
2253
Daniel Veillard78d12092001-10-11 09:12:24 +00002254 for (indx = 0;
2255 indx < list->nodesetval->nodeNr;
2256 indx++) {
2257 if (dir)
2258 xmlShellDir(ctxt, NULL,
2259 list->nodesetval->
2260 nodeTab[indx], NULL);
2261 else
2262 xmlShellList(ctxt, NULL,
2263 list->nodesetval->
2264 nodeTab[indx], NULL);
2265 }
2266 break;
2267 }
2268 case XPATH_BOOLEAN:
2269 xmlGenericError(xmlGenericErrorContext,
2270 "%s is a Boolean\n", arg);
2271 break;
2272 case XPATH_NUMBER:
2273 xmlGenericError(xmlGenericErrorContext,
2274 "%s is a number\n", arg);
2275 break;
2276 case XPATH_STRING:
2277 xmlGenericError(xmlGenericErrorContext,
2278 "%s is a string\n", arg);
2279 break;
2280 case XPATH_POINT:
2281 xmlGenericError(xmlGenericErrorContext,
2282 "%s is a point\n", arg);
2283 break;
2284 case XPATH_RANGE:
2285 xmlGenericError(xmlGenericErrorContext,
2286 "%s is a range\n", arg);
2287 break;
2288 case XPATH_LOCATIONSET:
2289 xmlGenericError(xmlGenericErrorContext,
2290 "%s is a range\n", arg);
2291 break;
2292 case XPATH_USERS:
2293 xmlGenericError(xmlGenericErrorContext,
2294 "%s is user-defined\n", arg);
2295 break;
2296 case XPATH_XSLT_TREE:
2297 xmlGenericError(xmlGenericErrorContext,
2298 "%s is an XSLT value tree\n",
2299 arg);
2300 break;
2301 }
2302#ifdef LIBXML_XPATH_ENABLED
2303 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002304#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002305 } else {
2306 xmlGenericError(xmlGenericErrorContext,
2307 "%s: no such node\n", arg);
2308 }
2309 ctxt->pctxt->node = NULL;
2310 }
2311 } else if (!strcmp(command, "cd")) {
2312 if (arg[0] == 0) {
2313 ctxt->node = (xmlNodePtr) ctxt->doc;
2314 } else {
2315#ifdef LIBXML_XPATH_ENABLED
2316 ctxt->pctxt->node = ctxt->node;
2317 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2318#else
2319 list = NULL;
2320#endif /* LIBXML_XPATH_ENABLED */
2321 if (list != NULL) {
2322 switch (list->type) {
2323 case XPATH_UNDEFINED:
2324 xmlGenericError(xmlGenericErrorContext,
2325 "%s: no such node\n", arg);
2326 break;
2327 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002328 if (list->nodesetval != NULL) {
2329 if (list->nodesetval->nodeNr == 1) {
2330 ctxt->node = list->nodesetval->nodeTab[0];
2331 } else
2332 xmlGenericError(xmlGenericErrorContext,
2333 "%s is a %d Node Set\n",
2334 arg,
2335 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002336 } else
2337 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002338 "%s is an empty Node Set\n",
2339 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002340 break;
2341 case XPATH_BOOLEAN:
2342 xmlGenericError(xmlGenericErrorContext,
2343 "%s is a Boolean\n", arg);
2344 break;
2345 case XPATH_NUMBER:
2346 xmlGenericError(xmlGenericErrorContext,
2347 "%s is a number\n", arg);
2348 break;
2349 case XPATH_STRING:
2350 xmlGenericError(xmlGenericErrorContext,
2351 "%s is a string\n", arg);
2352 break;
2353 case XPATH_POINT:
2354 xmlGenericError(xmlGenericErrorContext,
2355 "%s is a point\n", arg);
2356 break;
2357 case XPATH_RANGE:
2358 xmlGenericError(xmlGenericErrorContext,
2359 "%s is a range\n", arg);
2360 break;
2361 case XPATH_LOCATIONSET:
2362 xmlGenericError(xmlGenericErrorContext,
2363 "%s is a range\n", arg);
2364 break;
2365 case XPATH_USERS:
2366 xmlGenericError(xmlGenericErrorContext,
2367 "%s is user-defined\n", arg);
2368 break;
2369 case XPATH_XSLT_TREE:
2370 xmlGenericError(xmlGenericErrorContext,
2371 "%s is an XSLT value tree\n",
2372 arg);
2373 break;
2374 }
2375#ifdef LIBXML_XPATH_ENABLED
2376 xmlXPathFreeObject(list);
2377#endif
2378 } else {
2379 xmlGenericError(xmlGenericErrorContext,
2380 "%s: no such node\n", arg);
2381 }
2382 ctxt->pctxt->node = NULL;
2383 }
2384 } else if (!strcmp(command, "cat")) {
2385 if (arg[0] == 0) {
2386 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2387 } else {
2388 ctxt->pctxt->node = ctxt->node;
2389#ifdef LIBXML_XPATH_ENABLED
2390 ctxt->pctxt->node = ctxt->node;
2391 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2392#else
2393 list = NULL;
2394#endif /* LIBXML_XPATH_ENABLED */
2395 if (list != NULL) {
2396 switch (list->type) {
2397 case XPATH_UNDEFINED:
2398 xmlGenericError(xmlGenericErrorContext,
2399 "%s: no such node\n", arg);
2400 break;
2401 case XPATH_NODESET:{
2402 int indx;
2403
Daniel Veillarda6825e82001-11-07 13:33:59 +00002404 if (list->nodesetval == NULL)
2405 break;
2406
Daniel Veillard78d12092001-10-11 09:12:24 +00002407 for (indx = 0;
2408 indx < list->nodesetval->nodeNr;
2409 indx++) {
2410 if (i > 0)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002411 fprintf(ctxt->output, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002412 xmlShellCat(ctxt, NULL,
2413 list->nodesetval->
2414 nodeTab[indx], NULL);
2415 }
2416 break;
2417 }
2418 case XPATH_BOOLEAN:
2419 xmlGenericError(xmlGenericErrorContext,
2420 "%s is a Boolean\n", arg);
2421 break;
2422 case XPATH_NUMBER:
2423 xmlGenericError(xmlGenericErrorContext,
2424 "%s is a number\n", arg);
2425 break;
2426 case XPATH_STRING:
2427 xmlGenericError(xmlGenericErrorContext,
2428 "%s is a string\n", arg);
2429 break;
2430 case XPATH_POINT:
2431 xmlGenericError(xmlGenericErrorContext,
2432 "%s is a point\n", arg);
2433 break;
2434 case XPATH_RANGE:
2435 xmlGenericError(xmlGenericErrorContext,
2436 "%s is a range\n", arg);
2437 break;
2438 case XPATH_LOCATIONSET:
2439 xmlGenericError(xmlGenericErrorContext,
2440 "%s is a range\n", arg);
2441 break;
2442 case XPATH_USERS:
2443 xmlGenericError(xmlGenericErrorContext,
2444 "%s is user-defined\n", arg);
2445 break;
2446 case XPATH_XSLT_TREE:
2447 xmlGenericError(xmlGenericErrorContext,
2448 "%s is an XSLT value tree\n",
2449 arg);
2450 break;
2451 }
2452#ifdef LIBXML_XPATH_ENABLED
2453 xmlXPathFreeObject(list);
2454#endif
2455 } else {
2456 xmlGenericError(xmlGenericErrorContext,
2457 "%s: no such node\n", arg);
2458 }
2459 ctxt->pctxt->node = NULL;
2460 }
2461 } else {
2462 xmlGenericError(xmlGenericErrorContext,
2463 "Unknown command %s\n", command);
2464 }
2465 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002466 }
2467#ifdef LIBXML_XPATH_ENABLED
2468 xmlXPathFreeContext(ctxt->pctxt);
2469#endif /* LIBXML_XPATH_ENABLED */
2470 if (ctxt->loaded) {
2471 xmlFreeDoc(ctxt->doc);
2472 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002473 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002474 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002475 xmlFree(ctxt);
2476 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002477 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002478}
2479
2480#endif /* LIBXML_DEBUG_ENABLED */