blob: 41dd37fb143155cf19a4270a8aeb5b1131b0356b [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
Bjorn Reese70a9da52001-04-21 16:57:29 +000010#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000011#ifdef LIBXML_DEBUG_ENABLED
12
Owen Taylor3473f882001-02-23 17:55:21 +000013#include <string.h>
14#ifdef HAVE_STDLIB_H
15#include <stdlib.h>
16#endif
17#ifdef HAVE_STRING_H
18#include <string.h>
19#endif
20#include <libxml/xmlmemory.h>
21#include <libxml/tree.h>
22#include <libxml/parser.h>
Daniel Veillard567e1b42001-08-01 15:53:47 +000023#include <libxml/parserInternals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000024#include <libxml/valid.h>
25#include <libxml/debugXML.h>
26#include <libxml/HTMLtree.h>
27#include <libxml/HTMLparser.h>
28#include <libxml/xmlerror.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000029#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000030
Daniel Veillard5e2dace2001-07-18 19:30:27 +000031/**
32 * xmlDebugDumpString:
33 * @output: the FILE * for the output
34 * @str: the string
35 *
36 * Dumps informations about the string, shorten it if necessary
37 */
38void
39xmlDebugDumpString(FILE * output, const xmlChar * str)
40{
Owen Taylor3473f882001-02-23 17:55:21 +000041 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000042
Owen Taylor3473f882001-02-23 17:55:21 +000043 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000044 fprintf(output, "(NULL)");
45 return;
Owen Taylor3473f882001-02-23 17:55:21 +000046 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000047 for (i = 0; i < 40; i++)
48 if (str[i] == 0)
49 return;
50 else if (IS_BLANK(str[i]))
51 fputc(' ', output);
52 else if (str[i] >= 0x80)
53 fprintf(output, "#%X", str[i]);
54 else
55 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000056 fprintf(output, "...");
57}
58
Daniel Veillard56a4cb82001-03-24 17:00:36 +000059static void
60xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000061 int i;
62 char shift[100];
63
64 for (i = 0;((i < depth) && (i < 25));i++)
65 shift[2 * i] = shift[2 * i + 1] = ' ';
66 shift[2 * i] = shift[2 * i + 1] = 0;
67
68 fprintf(output, shift);
69
Daniel Veillard5e926fa2002-01-22 21:44:25 +000070 if (dtd == NULL) {
71 fprintf(output, "DTD node is NULL\n");
72 return;
73 }
74
Owen Taylor3473f882001-02-23 17:55:21 +000075 if (dtd->type != XML_DTD_NODE) {
76 fprintf(output, "PBM: not a DTD\n");
77 return;
78 }
79 if (dtd->name != NULL)
80 fprintf(output, "DTD(%s)", dtd->name);
81 else
82 fprintf(output, "DTD");
83 if (dtd->ExternalID != NULL)
84 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
85 if (dtd->SystemID != NULL)
86 fprintf(output, ", SYSTEM %s", dtd->SystemID);
87 fprintf(output, "\n");
88 /*
89 * Do a bit of checking
90 */
91 if (dtd->parent == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000092 fprintf(output, "PBM: DTD has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +000093 if (dtd->doc == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000094 fprintf(output, "PBM: DTD has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +000095 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +000096 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +000097 if (dtd->prev == NULL) {
98 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +000099 fprintf(output, "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000100 } else {
101 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000102 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000103 }
104 if (dtd->next == NULL) {
105 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000106 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000107 } else {
108 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000109 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000110 }
111}
112
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000113static void
114xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000115 int i;
116 char shift[100];
117
118 for (i = 0;((i < depth) && (i < 25));i++)
119 shift[2 * i] = shift[2 * i + 1] = ' ';
120 shift[2 * i] = shift[2 * i + 1] = 0;
121
122 fprintf(output, shift);
123
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000124 if (attr == NULL) {
125 fprintf(output, "Attribute declaration is NULL\n");
126 return;
127 }
Owen Taylor3473f882001-02-23 17:55:21 +0000128 if (attr->type != XML_ATTRIBUTE_DECL) {
129 fprintf(output, "PBM: not a Attr\n");
130 return;
131 }
132 if (attr->name != NULL)
133 fprintf(output, "ATTRDECL(%s)", attr->name);
134 else
135 fprintf(output, "PBM ATTRDECL noname!!!");
136 if (attr->elem != NULL)
137 fprintf(output, " for %s", attr->elem);
138 else
139 fprintf(output, " PBM noelem!!!");
140 switch (attr->atype) {
141 case XML_ATTRIBUTE_CDATA:
142 fprintf(output, " CDATA");
143 break;
144 case XML_ATTRIBUTE_ID:
145 fprintf(output, " ID");
146 break;
147 case XML_ATTRIBUTE_IDREF:
148 fprintf(output, " IDREF");
149 break;
150 case XML_ATTRIBUTE_IDREFS:
151 fprintf(output, " IDREFS");
152 break;
153 case XML_ATTRIBUTE_ENTITY:
154 fprintf(output, " ENTITY");
155 break;
156 case XML_ATTRIBUTE_ENTITIES:
157 fprintf(output, " ENTITIES");
158 break;
159 case XML_ATTRIBUTE_NMTOKEN:
160 fprintf(output, " NMTOKEN");
161 break;
162 case XML_ATTRIBUTE_NMTOKENS:
163 fprintf(output, " NMTOKENS");
164 break;
165 case XML_ATTRIBUTE_ENUMERATION:
166 fprintf(output, " ENUMERATION");
167 break;
168 case XML_ATTRIBUTE_NOTATION:
169 fprintf(output, " NOTATION ");
170 break;
171 }
172 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000173 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000174 xmlEnumerationPtr cur = attr->tree;
175
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000176 for (indx = 0;indx < 5; indx++) {
177 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000178 fprintf(output, "|%s", cur->name);
179 else
180 fprintf(output, " (%s", cur->name);
181 cur = cur->next;
182 if (cur == NULL) break;
183 }
184 if (cur == NULL)
185 fprintf(output, ")");
186 else
187 fprintf(output, "...)");
188 }
189 switch (attr->def) {
190 case XML_ATTRIBUTE_NONE:
191 break;
192 case XML_ATTRIBUTE_REQUIRED:
193 fprintf(output, " REQUIRED");
194 break;
195 case XML_ATTRIBUTE_IMPLIED:
196 fprintf(output, " IMPLIED");
197 break;
198 case XML_ATTRIBUTE_FIXED:
199 fprintf(output, " FIXED");
200 break;
201 }
202 if (attr->defaultValue != NULL) {
203 fprintf(output, "\"");
204 xmlDebugDumpString(output, attr->defaultValue);
205 fprintf(output, "\"");
206 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000207 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000208
209 /*
210 * Do a bit of checking
211 */
212 if (attr->parent == NULL)
213 fprintf(output, "PBM: Attr has no parent\n");
214 if (attr->doc == NULL)
215 fprintf(output, "PBM: Attr has no doc\n");
216 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
217 fprintf(output, "PBM: Attr doc differs from parent's one\n");
218 if (attr->prev == NULL) {
219 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
220 fprintf(output, "PBM: Attr has no prev and not first of list\n");
221 } else {
222 if (attr->prev->next != (xmlNodePtr) attr)
223 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
224 }
225 if (attr->next == NULL) {
226 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
227 fprintf(output, "PBM: Attr has no next and not last of list\n");
228 } else {
229 if (attr->next->prev != (xmlNodePtr) attr)
230 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
231 }
232}
233
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000234static void
235xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000236 int i;
237 char shift[100];
238
239 for (i = 0;((i < depth) && (i < 25));i++)
240 shift[2 * i] = shift[2 * i + 1] = ' ';
241 shift[2 * i] = shift[2 * i + 1] = 0;
242
243 fprintf(output, shift);
244
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000245 if (elem == NULL) {
246 fprintf(output, "Element declaration is NULL\n");
247 return;
248 }
Owen Taylor3473f882001-02-23 17:55:21 +0000249 if (elem->type != XML_ELEMENT_DECL) {
250 fprintf(output, "PBM: not a Elem\n");
251 return;
252 }
253 if (elem->name != NULL) {
254 fprintf(output, "ELEMDECL(");
255 xmlDebugDumpString(output, elem->name);
256 fprintf(output, ")");
257 } else
258 fprintf(output, "PBM ELEMDECL noname!!!");
259 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000260 case XML_ELEMENT_TYPE_UNDEFINED:
261 fprintf(output, ", UNDEFINED");
262 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000263 case XML_ELEMENT_TYPE_EMPTY:
264 fprintf(output, ", EMPTY");
265 break;
266 case XML_ELEMENT_TYPE_ANY:
267 fprintf(output, ", ANY");
268 break;
269 case XML_ELEMENT_TYPE_MIXED:
270 fprintf(output, ", MIXED ");
271 break;
272 case XML_ELEMENT_TYPE_ELEMENT:
273 fprintf(output, ", MIXED ");
274 break;
275 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000276 if ((elem->type != XML_ELEMENT_NODE) &&
277 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000278 char buf[5001];
279
280 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000281 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000282 buf[5000] = 0;
283 fprintf(output, "%s", buf);
284 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000285 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000286
287 /*
288 * Do a bit of checking
289 */
290 if (elem->parent == NULL)
291 fprintf(output, "PBM: Elem has no parent\n");
292 if (elem->doc == NULL)
293 fprintf(output, "PBM: Elem has no doc\n");
294 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
295 fprintf(output, "PBM: Elem doc differs from parent's one\n");
296 if (elem->prev == NULL) {
297 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
298 fprintf(output, "PBM: Elem has no prev and not first of list\n");
299 } else {
300 if (elem->prev->next != (xmlNodePtr) elem)
301 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
302 }
303 if (elem->next == NULL) {
304 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
305 fprintf(output, "PBM: Elem has no next and not last of list\n");
306 } else {
307 if (elem->next->prev != (xmlNodePtr) elem)
308 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
309 }
310}
311
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000312static void
313xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000314 int i;
315 char shift[100];
316
317 for (i = 0;((i < depth) && (i < 25));i++)
318 shift[2 * i] = shift[2 * i + 1] = ' ';
319 shift[2 * i] = shift[2 * i + 1] = 0;
320
321 fprintf(output, shift);
322
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000323 if (ent == NULL) {
324 fprintf(output, "Entity declaration is NULL\n");
325 return;
326 }
Owen Taylor3473f882001-02-23 17:55:21 +0000327 if (ent->type != XML_ENTITY_DECL) {
328 fprintf(output, "PBM: not a Entity decl\n");
329 return;
330 }
331 if (ent->name != NULL) {
332 fprintf(output, "ENTITYDECL(");
333 xmlDebugDumpString(output, ent->name);
334 fprintf(output, ")");
335 } else
336 fprintf(output, "PBM ENTITYDECL noname!!!");
337 switch (ent->etype) {
338 case XML_INTERNAL_GENERAL_ENTITY:
339 fprintf(output, ", internal\n");
340 break;
341 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
342 fprintf(output, ", external parsed\n");
343 break;
344 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
345 fprintf(output, ", unparsed\n");
346 break;
347 case XML_INTERNAL_PARAMETER_ENTITY:
348 fprintf(output, ", parameter\n");
349 break;
350 case XML_EXTERNAL_PARAMETER_ENTITY:
351 fprintf(output, ", external parameter\n");
352 break;
353 case XML_INTERNAL_PREDEFINED_ENTITY:
354 fprintf(output, ", predefined\n");
355 break;
356 }
357 if (ent->ExternalID) {
358 fprintf(output, shift);
359 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
360 }
361 if (ent->SystemID) {
362 fprintf(output, shift);
363 fprintf(output, " SystemID=%s\n", ent->SystemID);
364 }
365 if (ent->URI != NULL) {
366 fprintf(output, shift);
367 fprintf(output, " URI=%s\n", ent->URI);
368 }
369 if (ent->content) {
370 fprintf(output, shift);
371 fprintf(output, " content=");
372 xmlDebugDumpString(output, ent->content);
373 fprintf(output, "\n");
374 }
375
376 /*
377 * Do a bit of checking
378 */
379 if (ent->parent == NULL)
380 fprintf(output, "PBM: Ent has no parent\n");
381 if (ent->doc == NULL)
382 fprintf(output, "PBM: Ent has no doc\n");
383 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
384 fprintf(output, "PBM: Ent doc differs from parent's one\n");
385 if (ent->prev == NULL) {
386 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
387 fprintf(output, "PBM: Ent has no prev and not first of list\n");
388 } else {
389 if (ent->prev->next != (xmlNodePtr) ent)
390 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
391 }
392 if (ent->next == NULL) {
393 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
394 fprintf(output, "PBM: Ent has no next and not last of list\n");
395 } else {
396 if (ent->next->prev != (xmlNodePtr) ent)
397 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
398 }
399}
400
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000401static void
402xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000403 int i;
404 char shift[100];
405
406 for (i = 0;((i < depth) && (i < 25));i++)
407 shift[2 * i] = shift[2 * i + 1] = ' ';
408 shift[2 * i] = shift[2 * i + 1] = 0;
409
410 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000411
412 if (ns == NULL) {
413 fprintf(output, "namespace node is NULL\n");
414 return;
415 }
Owen Taylor3473f882001-02-23 17:55:21 +0000416 if (ns->type != XML_NAMESPACE_DECL) {
417 fprintf(output, "invalid namespace node %d\n", ns->type);
418 return;
419 }
420 if (ns->href == NULL) {
421 if (ns->prefix != NULL)
422 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
423 else
424 fprintf(output, "incomplete default namespace href=NULL\n");
425 } else {
426 if (ns->prefix != NULL)
427 fprintf(output, "namespace %s href=", ns->prefix);
428 else
429 fprintf(output, "default namespace href=");
430
431 xmlDebugDumpString(output, ns->href);
432 fprintf(output, "\n");
433 }
434}
435
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000436static void
437xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000438 while (ns != NULL) {
439 xmlDebugDumpNamespace(output, ns, depth);
440 ns = ns->next;
441 }
442}
443
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000444static void
445xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000446 int i;
447 char shift[100];
448
449 for (i = 0;((i < depth) && (i < 25));i++)
450 shift[2 * i] = shift[2 * i + 1] = ' ';
451 shift[2 * i] = shift[2 * i + 1] = 0;
452
453 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000454
455 if (ent == NULL) {
456 fprintf(output, "Entity is NULL\n");
457 return;
458 }
Owen Taylor3473f882001-02-23 17:55:21 +0000459 switch (ent->etype) {
460 case XML_INTERNAL_GENERAL_ENTITY:
461 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
462 break;
463 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
464 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
465 break;
466 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
467 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
468 break;
469 case XML_INTERNAL_PARAMETER_ENTITY:
470 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
471 break;
472 case XML_EXTERNAL_PARAMETER_ENTITY:
473 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
474 break;
475 default:
476 fprintf(output, "ENTITY_%d ! ", ent->etype);
477 }
478 fprintf(output, "%s\n", ent->name);
479 if (ent->ExternalID) {
480 fprintf(output, shift);
481 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
482 }
483 if (ent->SystemID) {
484 fprintf(output, shift);
485 fprintf(output, "SystemID=%s\n", ent->SystemID);
486 }
487 if (ent->URI) {
488 fprintf(output, shift);
489 fprintf(output, "URI=%s\n", ent->URI);
490 }
491 if (ent->content) {
492 fprintf(output, shift);
493 fprintf(output, "content=");
494 xmlDebugDumpString(output, ent->content);
495 fprintf(output, "\n");
496 }
497}
498
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000499/**
500 * xmlDebugDumpAttr:
501 * @output: the FILE * for the output
502 * @attr: the attribute
503 * @depth: the indentation level.
504 *
505 * Dumps debug information for the attribute
506 */
507void
508xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000509 int i;
510 char shift[100];
511
512 for (i = 0;((i < depth) && (i < 25));i++)
513 shift[2 * i] = shift[2 * i + 1] = ' ';
514 shift[2 * i] = shift[2 * i + 1] = 0;
515
516 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000517
518 if (attr == NULL) {
519 fprintf(output, "Attr is NULL");
520 return;
521 }
Owen Taylor3473f882001-02-23 17:55:21 +0000522 fprintf(output, "ATTRIBUTE ");
523 xmlDebugDumpString(output, attr->name);
524 fprintf(output, "\n");
525 if (attr->children != NULL)
526 xmlDebugDumpNodeList(output, attr->children, depth + 1);
527
528 /*
529 * Do a bit of checking
530 */
531 if (attr->parent == NULL)
532 fprintf(output, "PBM: Attr has no parent\n");
533 if (attr->doc == NULL)
534 fprintf(output, "PBM: Attr has no doc\n");
535 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
536 fprintf(output, "PBM: Attr doc differs from parent's one\n");
537 if (attr->prev == NULL) {
538 if ((attr->parent != NULL) && (attr->parent->properties != attr))
539 fprintf(output, "PBM: Attr has no prev and not first of list\n");
540 } else {
541 if (attr->prev->next != attr)
542 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
543 }
544 if (attr->next != NULL) {
545 if (attr->next->prev != attr)
546 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
547 }
548}
549
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000550/**
551 * xmlDebugDumpAttrList:
552 * @output: the FILE * for the output
553 * @attr: the attribute list
554 * @depth: the indentation level.
555 *
556 * Dumps debug information for the attribute list
557 */
558void
559xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
560{
Owen Taylor3473f882001-02-23 17:55:21 +0000561 while (attr != NULL) {
562 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000563 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000564 }
565}
566
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000567/**
568 * xmlDebugDumpOneNode:
569 * @output: the FILE * for the output
570 * @node: the node
571 * @depth: the indentation level.
572 *
573 * Dumps debug information for the element node, it is not recursive
574 */
575void
576xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
577{
Owen Taylor3473f882001-02-23 17:55:21 +0000578 int i;
579 char shift[100];
580
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000581 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000582 shift[2 * i] = shift[2 * i + 1] = ' ';
583 shift[2 * i] = shift[2 * i + 1] = 0;
584
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000585 if (node == NULL) {
586 fprintf(output, shift);
587 fprintf(output, "node is NULL\n");
588 return;
589 }
Owen Taylor3473f882001-02-23 17:55:21 +0000590 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000591 case XML_ELEMENT_NODE:
592 fprintf(output, shift);
593 fprintf(output, "ELEMENT ");
594 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
595 xmlDebugDumpString(output, node->ns->prefix);
596 fprintf(output, ":");
597 }
598 xmlDebugDumpString(output, node->name);
599 fprintf(output, "\n");
600 break;
601 case XML_ATTRIBUTE_NODE:
602 fprintf(output, shift);
603 fprintf(output, "Error, ATTRIBUTE found here\n");
604 break;
605 case XML_TEXT_NODE:
606 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000607 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000608 fprintf(output, "TEXT no enc\n");
609 else
610 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000611 break;
612 case XML_CDATA_SECTION_NODE:
613 fprintf(output, shift);
614 fprintf(output, "CDATA_SECTION\n");
615 break;
616 case XML_ENTITY_REF_NODE:
617 fprintf(output, shift);
618 fprintf(output, "ENTITY_REF(%s)\n", node->name);
619 break;
620 case XML_ENTITY_NODE:
621 fprintf(output, shift);
622 fprintf(output, "ENTITY\n");
623 break;
624 case XML_PI_NODE:
625 fprintf(output, shift);
626 fprintf(output, "PI %s\n", node->name);
627 break;
628 case XML_COMMENT_NODE:
629 fprintf(output, shift);
630 fprintf(output, "COMMENT\n");
631 break;
632 case XML_DOCUMENT_NODE:
633 case XML_HTML_DOCUMENT_NODE:
634 fprintf(output, shift);
635 fprintf(output, "Error, DOCUMENT found here\n");
636 break;
637 case XML_DOCUMENT_TYPE_NODE:
638 fprintf(output, shift);
639 fprintf(output, "DOCUMENT_TYPE\n");
640 break;
641 case XML_DOCUMENT_FRAG_NODE:
642 fprintf(output, shift);
643 fprintf(output, "DOCUMENT_FRAG\n");
644 break;
645 case XML_NOTATION_NODE:
646 fprintf(output, shift);
647 fprintf(output, "NOTATION\n");
648 break;
649 case XML_DTD_NODE:
650 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
651 return;
652 case XML_ELEMENT_DECL:
653 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
654 return;
655 case XML_ATTRIBUTE_DECL:
656 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
657 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000658 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000659 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
660 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000661 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000662 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
663 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000664 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000665 fprintf(output, shift);
666 fprintf(output, "INCLUDE START\n");
667 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000668 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000669 fprintf(output, shift);
670 fprintf(output, "INCLUDE END\n");
671 return;
672 default:
673 fprintf(output, shift);
674 fprintf(output, "NODE_%d !!!\n", node->type);
675 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000676 }
677 if (node->doc == NULL) {
678 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000679 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000680 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000681 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000682 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
683 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000684 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000685 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000686 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
687 shift[2 * i] = shift[2 * i + 1] = ' ';
688 shift[2 * i + 2] = shift[2 * i + 3] = 0;
689 fprintf(output, shift);
690 fprintf(output, "content=");
691#ifndef XML_USE_BUFFER_CONTENT
692 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +0000693#else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000694 xmlDebugDumpString(output, xmlBufferContent(node->content));
Owen Taylor3473f882001-02-23 17:55:21 +0000695#endif
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000696 fprintf(output, "\n");
697 }
Owen Taylor3473f882001-02-23 17:55:21 +0000698 } else {
699 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000700
701 ent = xmlGetDocEntity(node->doc, node->name);
702 if (ent != NULL)
703 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000704 }
705 /*
706 * Do a bit of checking
707 */
708 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000709 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000710 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000711 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000712 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000713 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000714 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000715 if ((node->parent != NULL) && (node->parent->children != node))
716 fprintf(output,
717 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000718 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000719 if (node->prev->next != node)
720 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000721 }
722 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000723 if ((node->parent != NULL) && (node->parent->last != node))
724 fprintf(output,
725 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000726 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000727 if (node->next->prev != node)
728 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000729 }
730}
731
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000732/**
733 * xmlDebugDumpNode:
734 * @output: the FILE * for the output
735 * @node: the node
736 * @depth: the indentation level.
737 *
738 * Dumps debug information for the element node, it is recursive
739 */
740void
741xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
742{
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000743 if (node == NULL) {
744 int i;
745 char shift[100];
746
747 for (i = 0; ((i < depth) && (i < 25)); i++)
748 shift[2 * i] = shift[2 * i + 1] = ' ';
749 shift[2 * i] = shift[2 * i + 1] = 0;
750
751 fprintf(output, shift);
752 fprintf(output, "node is NULL\n");
753 return;
754 }
Owen Taylor3473f882001-02-23 17:55:21 +0000755 xmlDebugDumpOneNode(output, node, depth);
756 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000757 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000758}
759
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000760/**
761 * xmlDebugDumpNodeList:
762 * @output: the FILE * for the output
763 * @node: the node list
764 * @depth: the indentation level.
765 *
766 * Dumps debug information for the list of element node, it is recursive
767 */
768void
769xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
770{
Owen Taylor3473f882001-02-23 17:55:21 +0000771 while (node != NULL) {
772 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000773 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000774 }
775}
776
777
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000778/**
779 * xmlDebugDumpDocumentHead:
780 * @output: the FILE * for the output
781 * @doc: the document
782 *
783 * Dumps debug information cncerning the document, not recursive
784 */
785void
786xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
787{
788 if (output == NULL)
789 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000790 if (doc == NULL) {
791 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000792 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000793 }
794
795 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000796 case XML_ELEMENT_NODE:
797 fprintf(output, "Error, ELEMENT found here ");
798 break;
799 case XML_ATTRIBUTE_NODE:
800 fprintf(output, "Error, ATTRIBUTE found here\n");
801 break;
802 case XML_TEXT_NODE:
803 fprintf(output, "Error, TEXT\n");
804 break;
805 case XML_CDATA_SECTION_NODE:
806 fprintf(output, "Error, CDATA_SECTION\n");
807 break;
808 case XML_ENTITY_REF_NODE:
809 fprintf(output, "Error, ENTITY_REF\n");
810 break;
811 case XML_ENTITY_NODE:
812 fprintf(output, "Error, ENTITY\n");
813 break;
814 case XML_PI_NODE:
815 fprintf(output, "Error, PI\n");
816 break;
817 case XML_COMMENT_NODE:
818 fprintf(output, "Error, COMMENT\n");
819 break;
820 case XML_DOCUMENT_NODE:
821 fprintf(output, "DOCUMENT\n");
822 break;
823 case XML_HTML_DOCUMENT_NODE:
824 fprintf(output, "HTML DOCUMENT\n");
825 break;
826 case XML_DOCUMENT_TYPE_NODE:
827 fprintf(output, "Error, DOCUMENT_TYPE\n");
828 break;
829 case XML_DOCUMENT_FRAG_NODE:
830 fprintf(output, "Error, DOCUMENT_FRAG\n");
831 break;
832 case XML_NOTATION_NODE:
833 fprintf(output, "Error, NOTATION\n");
834 break;
835 default:
836 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000837 }
838 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000839 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000840 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000841 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000842 }
843 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000844 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000845 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000846 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000847 }
848 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000849 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000850 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000851 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000852 }
853 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000854 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000855 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000856 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000857 }
858 if (doc->standalone)
859 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000860 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000861 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
862}
863
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000864/**
865 * xmlDebugDumpDocument:
866 * @output: the FILE * for the output
867 * @doc: the document
868 *
869 * Dumps debug information for the document, it's recursive
870 */
871void
872xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
873{
874 if (output == NULL)
875 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000876 if (doc == NULL) {
877 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000878 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000879 }
880 xmlDebugDumpDocumentHead(output, doc);
881 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000882 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000883 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000884}
Owen Taylor3473f882001-02-23 17:55:21 +0000885
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000886/**
887 * xmlDebugDumpDTD:
888 * @output: the FILE * for the output
889 * @dtd: the DTD
890 *
891 * Dumps debug information for the DTD
892 */
893void
894xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
895{
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000896 if (dtd == NULL) {
897 fprintf(output, "DTD is NULL\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000898 return;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000899 }
Owen Taylor3473f882001-02-23 17:55:21 +0000900 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000901 fprintf(output, "PBM: not a DTD\n");
902 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000903 }
904 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000905 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000906 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000907 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000908 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000909 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000910 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000911 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000912 fprintf(output, "\n");
913 /*
914 * Do a bit of checking
915 */
916 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000917 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000918 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000919 if ((dtd->parent != NULL)
920 && (dtd->parent->children != (xmlNodePtr) dtd))
921 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000922 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000923 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000924 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000925 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000926 }
927 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000928 if ((dtd->parent != NULL)
929 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000930 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000931 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000932 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000933 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000934 }
935 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000936 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000937 else
938 xmlDebugDumpNodeList(output, dtd->children, 1);
939}
940
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000941static void
942xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000943 if (cur == NULL) {
944 fprintf(output, "Entity is NULL");
945 return;
946 }
Owen Taylor3473f882001-02-23 17:55:21 +0000947 fprintf(output, "%s : ", cur->name);
948 switch (cur->etype) {
949 case XML_INTERNAL_GENERAL_ENTITY:
950 fprintf(output, "INTERNAL GENERAL, ");
951 break;
952 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
953 fprintf(output, "EXTERNAL PARSED, ");
954 break;
955 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
956 fprintf(output, "EXTERNAL UNPARSED, ");
957 break;
958 case XML_INTERNAL_PARAMETER_ENTITY:
959 fprintf(output, "INTERNAL PARAMETER, ");
960 break;
961 case XML_EXTERNAL_PARAMETER_ENTITY:
962 fprintf(output, "EXTERNAL PARAMETER, ");
963 break;
964 default:
965 fprintf(output, "UNKNOWN TYPE %d",
966 cur->etype);
967 }
968 if (cur->ExternalID != NULL)
969 fprintf(output, "ID \"%s\"", cur->ExternalID);
970 if (cur->SystemID != NULL)
971 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
972 if (cur->orig != NULL)
973 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000974 if ((cur->type != XML_ELEMENT_NODE) &&
975 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000976 fprintf(output, "\n content \"%s\"", cur->content);
977 fprintf(output, "\n");
978}
979
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000980/**
981 * xmlDebugDumpEntities:
982 * @output: the FILE * for the output
983 * @doc: the document
984 *
985 * Dumps debug information for all the entities in use by the document
986 */
987void
988xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
989{
990 if (output == NULL)
991 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000992 if (doc == NULL) {
993 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000994 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000995 }
996
997 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000998 case XML_ELEMENT_NODE:
999 fprintf(output, "Error, ELEMENT found here ");
1000 break;
1001 case XML_ATTRIBUTE_NODE:
1002 fprintf(output, "Error, ATTRIBUTE found here\n");
1003 break;
1004 case XML_TEXT_NODE:
1005 fprintf(output, "Error, TEXT\n");
1006 break;
1007 case XML_CDATA_SECTION_NODE:
1008 fprintf(output, "Error, CDATA_SECTION\n");
1009 break;
1010 case XML_ENTITY_REF_NODE:
1011 fprintf(output, "Error, ENTITY_REF\n");
1012 break;
1013 case XML_ENTITY_NODE:
1014 fprintf(output, "Error, ENTITY\n");
1015 break;
1016 case XML_PI_NODE:
1017 fprintf(output, "Error, PI\n");
1018 break;
1019 case XML_COMMENT_NODE:
1020 fprintf(output, "Error, COMMENT\n");
1021 break;
1022 case XML_DOCUMENT_NODE:
1023 fprintf(output, "DOCUMENT\n");
1024 break;
1025 case XML_HTML_DOCUMENT_NODE:
1026 fprintf(output, "HTML DOCUMENT\n");
1027 break;
1028 case XML_DOCUMENT_TYPE_NODE:
1029 fprintf(output, "Error, DOCUMENT_TYPE\n");
1030 break;
1031 case XML_DOCUMENT_FRAG_NODE:
1032 fprintf(output, "Error, DOCUMENT_FRAG\n");
1033 break;
1034 case XML_NOTATION_NODE:
1035 fprintf(output, "Error, NOTATION\n");
1036 break;
1037 default:
1038 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +00001039 }
1040 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001041 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1042 doc->intSubset->entities;
1043
1044 fprintf(output, "Entities in internal subset\n");
1045 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1046 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001047 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001048 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001049 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001050 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1051 doc->extSubset->entities;
1052
1053 fprintf(output, "Entities in external subset\n");
1054 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1055 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001056 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001057 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001058}
1059
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001060/**
1061 * xmlLsCountNode:
1062 * @node: the node to count
1063 *
1064 * Count the children of @node.
1065 *
1066 * Returns the number of children of @node.
1067 */
1068int
1069xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001070 int ret = 0;
1071 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001072
1073 if (node == NULL)
1074 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001075
1076 switch (node->type) {
1077 case XML_ELEMENT_NODE:
1078 list = node->children;
1079 break;
1080 case XML_DOCUMENT_NODE:
1081 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001082#ifdef LIBXML_DOCB_ENABLED
1083 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001084#endif
1085 list = ((xmlDocPtr) node)->children;
1086 break;
1087 case XML_ATTRIBUTE_NODE:
1088 list = ((xmlAttrPtr) node)->children;
1089 break;
1090 case XML_TEXT_NODE:
1091 case XML_CDATA_SECTION_NODE:
1092 case XML_PI_NODE:
1093 case XML_COMMENT_NODE:
1094 if (node->content != NULL) {
1095#ifndef XML_USE_BUFFER_CONTENT
1096 ret = xmlStrlen(node->content);
1097#else
1098 ret = xmlBufferLength(node->content);
1099#endif
1100 }
1101 break;
1102 case XML_ENTITY_REF_NODE:
1103 case XML_DOCUMENT_TYPE_NODE:
1104 case XML_ENTITY_NODE:
1105 case XML_DOCUMENT_FRAG_NODE:
1106 case XML_NOTATION_NODE:
1107 case XML_DTD_NODE:
1108 case XML_ELEMENT_DECL:
1109 case XML_ATTRIBUTE_DECL:
1110 case XML_ENTITY_DECL:
1111 case XML_NAMESPACE_DECL:
1112 case XML_XINCLUDE_START:
1113 case XML_XINCLUDE_END:
1114 ret = 1;
1115 break;
1116 }
1117 for (;list != NULL;ret++)
1118 list = list->next;
1119 return(ret);
1120}
1121
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001122/**
1123 * xmlLsOneNode:
1124 * @output: the FILE * for the output
1125 * @node: the node to dump
1126 *
1127 * Dump to @output the type and name of @node.
1128 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001129void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001130xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001131 if (node == NULL) {
1132 fprintf(output, "NULL\n");
1133 return;
1134 }
Owen Taylor3473f882001-02-23 17:55:21 +00001135 switch (node->type) {
1136 case XML_ELEMENT_NODE:
1137 fprintf(output, "-");
1138 break;
1139 case XML_ATTRIBUTE_NODE:
1140 fprintf(output, "a");
1141 break;
1142 case XML_TEXT_NODE:
1143 fprintf(output, "t");
1144 break;
1145 case XML_CDATA_SECTION_NODE:
1146 fprintf(output, "c");
1147 break;
1148 case XML_ENTITY_REF_NODE:
1149 fprintf(output, "e");
1150 break;
1151 case XML_ENTITY_NODE:
1152 fprintf(output, "E");
1153 break;
1154 case XML_PI_NODE:
1155 fprintf(output, "p");
1156 break;
1157 case XML_COMMENT_NODE:
1158 fprintf(output, "c");
1159 break;
1160 case XML_DOCUMENT_NODE:
1161 fprintf(output, "d");
1162 break;
1163 case XML_HTML_DOCUMENT_NODE:
1164 fprintf(output, "h");
1165 break;
1166 case XML_DOCUMENT_TYPE_NODE:
1167 fprintf(output, "T");
1168 break;
1169 case XML_DOCUMENT_FRAG_NODE:
1170 fprintf(output, "F");
1171 break;
1172 case XML_NOTATION_NODE:
1173 fprintf(output, "N");
1174 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001175 case XML_NAMESPACE_DECL:
1176 fprintf(output, "n");
1177 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001178 default:
1179 fprintf(output, "?");
1180 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001181 if (node->type != XML_NAMESPACE_DECL) {
1182 if (node->properties != NULL)
1183 fprintf(output, "a");
1184 else
1185 fprintf(output, "-");
1186 if (node->nsDef != NULL)
1187 fprintf(output, "n");
1188 else
1189 fprintf(output, "-");
1190 }
Owen Taylor3473f882001-02-23 17:55:21 +00001191
1192 fprintf(output, " %8d ", xmlLsCountNode(node));
1193
1194 switch (node->type) {
1195 case XML_ELEMENT_NODE:
1196 if (node->name != NULL)
1197 fprintf(output, "%s", node->name);
1198 break;
1199 case XML_ATTRIBUTE_NODE:
1200 if (node->name != NULL)
1201 fprintf(output, "%s", node->name);
1202 break;
1203 case XML_TEXT_NODE:
1204 if (node->content != NULL) {
1205#ifndef XML_USE_BUFFER_CONTENT
1206 xmlDebugDumpString(output, node->content);
1207#else
1208 xmlDebugDumpString(output, xmlBufferContent(node->content));
1209#endif
1210 }
1211 break;
1212 case XML_CDATA_SECTION_NODE:
1213 break;
1214 case XML_ENTITY_REF_NODE:
1215 if (node->name != NULL)
1216 fprintf(output, "%s", node->name);
1217 break;
1218 case XML_ENTITY_NODE:
1219 if (node->name != NULL)
1220 fprintf(output, "%s", node->name);
1221 break;
1222 case XML_PI_NODE:
1223 if (node->name != NULL)
1224 fprintf(output, "%s", node->name);
1225 break;
1226 case XML_COMMENT_NODE:
1227 break;
1228 case XML_DOCUMENT_NODE:
1229 break;
1230 case XML_HTML_DOCUMENT_NODE:
1231 break;
1232 case XML_DOCUMENT_TYPE_NODE:
1233 break;
1234 case XML_DOCUMENT_FRAG_NODE:
1235 break;
1236 case XML_NOTATION_NODE:
1237 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001238 case XML_NAMESPACE_DECL: {
1239 xmlNsPtr ns = (xmlNsPtr) node;
1240
1241 if (ns->prefix == NULL)
1242 fprintf(output, "default -> %s", ns->href);
1243 else
1244 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1245 break;
1246 }
Owen Taylor3473f882001-02-23 17:55:21 +00001247 default:
1248 if (node->name != NULL)
1249 fprintf(output, "%s", node->name);
1250 }
1251 fprintf(output, "\n");
1252}
1253
Daniel Veillard78d12092001-10-11 09:12:24 +00001254/**
1255 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001256 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001257 *
1258 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001259 *
1260 * Returns a pointer to either "True" or "False"
1261 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001262const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001263xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001264{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001265 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001266 return("True");
1267 else
1268 return("False");
1269}
1270
Owen Taylor3473f882001-02-23 17:55:21 +00001271/****************************************************************
1272 * *
1273 * The XML shell related functions *
1274 * *
1275 ****************************************************************/
1276
Daniel Veillard78d12092001-10-11 09:12:24 +00001277
1278
Owen Taylor3473f882001-02-23 17:55:21 +00001279/*
1280 * TODO: Improvement/cleanups for the XML shell
1281 * - allow to shell out an editor on a subpart
1282 * - cleanup function registrations (with help) and calling
1283 * - provide registration routines
1284 */
1285
1286/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001287 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001288 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001289 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001290 *
1291 * Print the xpath error to libxml default error channel
1292 */
1293void
1294xmlShellPrintXPathError(int errorType, const char *arg)
1295{
1296 const char *default_arg = "Result";
1297
1298 if (!arg)
1299 arg = default_arg;
1300
1301 switch (errorType) {
1302 case XPATH_UNDEFINED:
1303 xmlGenericError(xmlGenericErrorContext,
1304 "%s: no such node\n", arg);
1305 break;
1306
1307 case XPATH_BOOLEAN:
1308 xmlGenericError(xmlGenericErrorContext,
1309 "%s is a Boolean\n", arg);
1310 break;
1311 case XPATH_NUMBER:
1312 xmlGenericError(xmlGenericErrorContext,
1313 "%s is a number\n", arg);
1314 break;
1315 case XPATH_STRING:
1316 xmlGenericError(xmlGenericErrorContext,
1317 "%s is a string\n", arg);
1318 break;
1319 case XPATH_POINT:
1320 xmlGenericError(xmlGenericErrorContext,
1321 "%s is a point\n", arg);
1322 break;
1323 case XPATH_RANGE:
1324 xmlGenericError(xmlGenericErrorContext,
1325 "%s is a range\n", arg);
1326 break;
1327 case XPATH_LOCATIONSET:
1328 xmlGenericError(xmlGenericErrorContext,
1329 "%s is a range\n", arg);
1330 break;
1331 case XPATH_USERS:
1332 xmlGenericError(xmlGenericErrorContext,
1333 "%s is user-defined\n", arg);
1334 break;
1335 case XPATH_XSLT_TREE:
1336 xmlGenericError(xmlGenericErrorContext,
1337 "%s is an XSLT value tree\n", arg);
1338 break;
1339 }
1340 xmlGenericError(xmlGenericErrorContext,
1341 "Try casting the result string function (xpath builtin)\n",
1342 arg);
1343}
1344
1345
1346/**
1347 * xmlShellPrintNode:
1348 * @node : a non-null node to print to stdout
1349 *
1350 * Print node to stdout
1351 */
1352void
1353xmlShellPrintNode(xmlNodePtr node)
1354{
1355 if (!node)
1356 return;
1357
1358 if (node->type == XML_DOCUMENT_NODE)
1359 xmlDocDump(stdout, (xmlDocPtr) node);
1360 else if (node->type == XML_ATTRIBUTE_NODE)
1361 xmlDebugDumpAttrList(stdout, (xmlAttrPtr) node, 0);
1362 else
1363 xmlElemDump(stdout, node->doc, node);
1364
1365 fprintf(stdout, "\n");
1366}
1367
1368
1369/**
1370 * xmlShellPrintXPathResult:
Daniel Veillard9d06d302002-01-22 18:15:52 +00001371 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001372 *
1373 * Prints result to stdout
1374 */
1375void
1376xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1377{
1378 int i = 0;
1379
1380 if (list != NULL) {
1381 switch (list->type) {
1382 case XPATH_NODESET:{
1383 int indx;
1384
1385 if (list->nodesetval) {
1386 for (indx = 0; indx < list->nodesetval->nodeNr;
1387 indx++) {
1388 if (i > 0)
1389 fprintf(stderr, " -------\n");
1390 xmlShellPrintNode(list->nodesetval->
1391 nodeTab[indx]);
1392 }
1393 } else {
1394 xmlGenericError(xmlGenericErrorContext,
1395 "Empty node set\n");
1396 }
1397 break;
1398 }
1399 case XPATH_BOOLEAN:
1400 xmlGenericError(xmlGenericErrorContext,
1401 "Is a Boolean:%s\n",
1402 xmlBoolToText(list->boolval));
1403 break;
1404 case XPATH_NUMBER:
1405 xmlGenericError(xmlGenericErrorContext,
1406 "Is a number:%0g\n", list->floatval);
1407 break;
1408 case XPATH_STRING:
1409 xmlGenericError(xmlGenericErrorContext,
1410 "Is a string:%s\n", list->stringval);
1411 break;
1412
1413 default:
1414 xmlShellPrintXPathError(list->type, NULL);
1415 }
1416 }
1417}
1418
1419/**
Owen Taylor3473f882001-02-23 17:55:21 +00001420 * xmlShellList:
1421 * @ctxt: the shell context
1422 * @arg: unused
1423 * @node: a node
1424 * @node2: unused
1425 *
1426 * Implements the XML shell function "ls"
1427 * Does an Unix like listing of the given node (like a directory)
1428 *
1429 * Returns 0
1430 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001431int
1432xmlShellList(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1433 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1434 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1435{
Owen Taylor3473f882001-02-23 17:55:21 +00001436 xmlNodePtr cur;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001437 if (node == NULL) {
1438 fprintf(stdout, "NULL\n");
1439 return (0);
1440 }
Owen Taylor3473f882001-02-23 17:55:21 +00001441 if ((node->type == XML_DOCUMENT_NODE) ||
1442 (node->type == XML_HTML_DOCUMENT_NODE)) {
1443 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001444 } else if (node->type == XML_NAMESPACE_DECL) {
1445 xmlLsOneNode(stdout, node);
1446 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001447 } else if (node->children != NULL) {
1448 cur = node->children;
1449 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001450 xmlLsOneNode(stdout, node);
1451 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001452 }
1453 while (cur != NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001454 xmlLsOneNode(stdout, cur);
1455 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001456 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001457 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001458}
1459
1460/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001461 * xmlShellBase:
1462 * @ctxt: the shell context
1463 * @arg: unused
1464 * @node: a node
1465 * @node2: unused
1466 *
1467 * Implements the XML shell function "base"
1468 * dumps the current XML base of the node
1469 *
1470 * Returns 0
1471 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001472int
1473xmlShellBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1474 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1475 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1476{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001477 xmlChar *base;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001478 if (node == NULL) {
1479 fprintf(stdout, "NULL\n");
1480 return (0);
1481 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001482
1483 base = xmlNodeGetBase(node->doc, node);
1484
1485 if (base == NULL) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001486 fprintf(stdout, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001487 } else {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001488 fprintf(stdout, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001489 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001490 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001491 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001492}
1493
1494/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001495 * xmlShellSetBase:
1496 * @ctxt: the shell context
1497 * @arg: the new base
1498 * @node: a node
1499 * @node2: unused
1500 *
1501 * Implements the XML shell function "setbase"
1502 * change the current XML base of the node
1503 *
1504 * Returns 0
1505 */
1506static int
1507xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1508 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1509 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1510{
1511 xmlNodeSetBase(node, (xmlChar*) arg);
1512 return (0);
1513}
1514
1515/**
Owen Taylor3473f882001-02-23 17:55:21 +00001516 * xmlShellDir:
1517 * @ctxt: the shell context
1518 * @arg: unused
1519 * @node: a node
1520 * @node2: unused
1521 *
1522 * Implements the XML shell function "dir"
1523 * dumps informations about the node (namespace, attributes, content).
1524 *
1525 * Returns 0
1526 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001527int
1528xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1529 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1530 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1531{
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001532 if (node == NULL) {
1533 fprintf(stdout, "NULL\n");
1534 return (0);
1535 }
Owen Taylor3473f882001-02-23 17:55:21 +00001536 if ((node->type == XML_DOCUMENT_NODE) ||
1537 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001538 xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001539 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001540 xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001541 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001542 xmlDebugDumpOneNode(stdout, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001543 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001544 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001545}
1546
1547/**
1548 * xmlShellCat:
1549 * @ctxt: the shell context
1550 * @arg: unused
1551 * @node: a node
1552 * @node2: unused
1553 *
1554 * Implements the XML shell function "cat"
1555 * dumps the serialization node content (XML or HTML).
1556 *
1557 * Returns 0
1558 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001559int
1560xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1561 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1562{
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001563 if (node == NULL) {
1564 fprintf(stdout, "NULL\n");
1565 return (0);
1566 }
Owen Taylor3473f882001-02-23 17:55:21 +00001567 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1568#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001569 if (node->type == XML_HTML_DOCUMENT_NODE)
1570 htmlDocDump(stdout, (htmlDocPtr) node);
1571 else
1572 htmlNodeDumpFile(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001573#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001574 if (node->type == XML_DOCUMENT_NODE)
1575 xmlDocDump(stdout, (xmlDocPtr) node);
1576 else
1577 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001578#endif /* LIBXML_HTML_ENABLED */
1579 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001580 if (node->type == XML_DOCUMENT_NODE)
1581 xmlDocDump(stdout, (xmlDocPtr) node);
1582 else
1583 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001584 }
Daniel Veillardcd337f02001-11-22 18:20:37 +00001585 fprintf(stdout, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001586 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001587}
1588
1589/**
1590 * xmlShellLoad:
1591 * @ctxt: the shell context
1592 * @filename: the file name
1593 * @node: unused
1594 * @node2: unused
1595 *
1596 * Implements the XML shell function "load"
1597 * loads a new document specified by the filename
1598 *
1599 * Returns 0 or -1 if loading failed
1600 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001601int
1602xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1603 xmlNodePtr node ATTRIBUTE_UNUSED,
1604 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1605{
Owen Taylor3473f882001-02-23 17:55:21 +00001606 xmlDocPtr doc;
1607 int html = 0;
1608
1609 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001610 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001611
1612 if (html) {
1613#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001614 doc = htmlParseFile(filename, NULL);
1615#else
Daniel Veillardcd337f02001-11-22 18:20:37 +00001616 fprintf(stdout, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001617 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001618#endif /* LIBXML_HTML_ENABLED */
1619 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001620 doc = xmlParseFile(filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001621 }
1622 if (doc != NULL) {
1623 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001624 xmlFreeDoc(ctxt->doc);
1625 }
1626 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001627#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001628 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001629#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001630 xmlFree(ctxt->filename);
1631 ctxt->doc = doc;
1632 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001633#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001634 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001635#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001636 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001637 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001638 return (-1);
1639 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001640}
1641
1642/**
1643 * xmlShellWrite:
1644 * @ctxt: the shell context
1645 * @filename: the file name
1646 * @node: a node in the tree
1647 * @node2: unused
1648 *
1649 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001650 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001651 * of the subtree under the @node specified
1652 *
1653 * Returns 0 or -1 in case of error
1654 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001655int
Owen Taylor3473f882001-02-23 17:55:21 +00001656xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001657 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1658{
Owen Taylor3473f882001-02-23 17:55:21 +00001659 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001660 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001661 if ((filename == NULL) || (filename[0] == 0)) {
1662 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001663 "Write command requires a filename argument\n");
1664 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001665 }
1666#ifdef W_OK
1667 if (access((char *) filename, W_OK)) {
1668 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001669 "Cannot write to %s\n", filename);
1670 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001671 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001672#endif
1673 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001674 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001675 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1676 xmlGenericError(xmlGenericErrorContext,
1677 "Failed to write to %s\n", filename);
1678 return (-1);
1679 }
1680 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001681 case XML_HTML_DOCUMENT_NODE:
1682#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001683 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1684 xmlGenericError(xmlGenericErrorContext,
1685 "Failed to write to %s\n", filename);
1686 return (-1);
1687 }
Owen Taylor3473f882001-02-23 17:55:21 +00001688#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001689 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1690 xmlGenericError(xmlGenericErrorContext,
1691 "Failed to write to %s\n", filename);
1692 return (-1);
1693 }
Owen Taylor3473f882001-02-23 17:55:21 +00001694#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001695 break;
1696 default:{
1697 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001698
Daniel Veillard78d12092001-10-11 09:12:24 +00001699 f = fopen((char *) filename, "w");
1700 if (f == NULL) {
1701 xmlGenericError(xmlGenericErrorContext,
1702 "Failed to write to %s\n", filename);
1703 return (-1);
1704 }
1705 xmlElemDump(f, ctxt->doc, node);
1706 fclose(f);
1707 }
Owen Taylor3473f882001-02-23 17:55:21 +00001708 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001709 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001710}
1711
1712/**
1713 * xmlShellSave:
1714 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001715 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001716 * @node: unused
1717 * @node2: unused
1718 *
1719 * Implements the XML shell function "save"
1720 * Write the current document to the filename, or it's original name
1721 *
1722 * Returns 0 or -1 in case of error
1723 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001724int
1725xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1726 xmlNodePtr node ATTRIBUTE_UNUSED,
1727 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1728{
Owen Taylor3473f882001-02-23 17:55:21 +00001729 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001730 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001731 if ((filename == NULL) || (filename[0] == 0))
1732 filename = ctxt->filename;
1733#ifdef W_OK
1734 if (access((char *) filename, W_OK)) {
1735 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001736 "Cannot save to %s\n", filename);
1737 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001738 }
1739#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001740 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001741 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001742 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1743 xmlGenericError(xmlGenericErrorContext,
1744 "Failed to save to %s\n", filename);
1745 }
1746 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001747 case XML_HTML_DOCUMENT_NODE:
1748#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001749 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1750 xmlGenericError(xmlGenericErrorContext,
1751 "Failed to save to %s\n", filename);
1752 }
Owen Taylor3473f882001-02-23 17:55:21 +00001753#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001754 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1755 xmlGenericError(xmlGenericErrorContext,
1756 "Failed to save to %s\n", filename);
1757 }
Owen Taylor3473f882001-02-23 17:55:21 +00001758#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001759 break;
1760 default:
1761 xmlGenericError(xmlGenericErrorContext,
1762 "To save to subparts of a document use the 'write' command\n");
1763 return (-1);
1764
Owen Taylor3473f882001-02-23 17:55:21 +00001765 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001766 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001767}
1768
1769/**
1770 * xmlShellValidate:
1771 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001772 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001773 * @node: unused
1774 * @node2: unused
1775 *
1776 * Implements the XML shell function "validate"
1777 * Validate the document, if a DTD path is provided, then the validation
1778 * is done against the given DTD.
1779 *
1780 * Returns 0 or -1 in case of error
1781 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001782int
1783xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1784 xmlNodePtr node ATTRIBUTE_UNUSED,
1785 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1786{
Owen Taylor3473f882001-02-23 17:55:21 +00001787 xmlValidCtxt vctxt;
1788 int res = -1;
1789
1790 vctxt.userData = stderr;
1791 vctxt.error = (xmlValidityErrorFunc) fprintf;
1792 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1793
1794 if ((dtd == NULL) || (dtd[0] == 0)) {
1795 res = xmlValidateDocument(&vctxt, ctxt->doc);
1796 } else {
1797 xmlDtdPtr subset;
1798
Daniel Veillard78d12092001-10-11 09:12:24 +00001799 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1800 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001801 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1802
Daniel Veillard78d12092001-10-11 09:12:24 +00001803 xmlFreeDtd(subset);
1804 }
Owen Taylor3473f882001-02-23 17:55:21 +00001805 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001806 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00001807}
1808
1809/**
1810 * xmlShellDu:
1811 * @ctxt: the shell context
1812 * @arg: unused
1813 * @tree: a node defining a subtree
1814 * @node2: unused
1815 *
1816 * Implements the XML shell function "du"
1817 * show the structure of the subtree under node @tree
1818 * If @tree is null, the command works on the current node.
1819 *
1820 * Returns 0 or -1 in case of error
1821 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001822int
1823xmlShellDu(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1824 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1825 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1826{
Owen Taylor3473f882001-02-23 17:55:21 +00001827 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00001828 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00001829
Daniel Veillard78d12092001-10-11 09:12:24 +00001830 if (tree == NULL)
1831 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001832 node = tree;
1833 while (node != NULL) {
1834 if ((node->type == XML_DOCUMENT_NODE) ||
1835 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001836 fprintf(stdout, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001837 } else if (node->type == XML_ELEMENT_NODE) {
1838 for (i = 0; i < indent; i++)
Daniel Veillardcd337f02001-11-22 18:20:37 +00001839 fprintf(stdout, " ");
1840 fprintf(stdout, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00001841 } else {
1842 }
Owen Taylor3473f882001-02-23 17:55:21 +00001843
Daniel Veillard78d12092001-10-11 09:12:24 +00001844 /*
1845 * Browse the full subtree, deep first
1846 */
Owen Taylor3473f882001-02-23 17:55:21 +00001847
1848 if ((node->type == XML_DOCUMENT_NODE) ||
1849 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001850 node = ((xmlDocPtr) node)->children;
1851 } else if ((node->children != NULL)
1852 && (node->type != XML_ENTITY_REF_NODE)) {
1853 /* deep first */
1854 node = node->children;
1855 indent++;
1856 } else if ((node != tree) && (node->next != NULL)) {
1857 /* then siblings */
1858 node = node->next;
1859 } else if (node != tree) {
1860 /* go up to parents->next if needed */
1861 while (node != tree) {
1862 if (node->parent != NULL) {
1863 node = node->parent;
1864 indent--;
1865 }
1866 if ((node != tree) && (node->next != NULL)) {
1867 node = node->next;
1868 break;
1869 }
1870 if (node->parent == NULL) {
1871 node = NULL;
1872 break;
1873 }
1874 if (node == tree) {
1875 node = NULL;
1876 break;
1877 }
1878 }
1879 /* exit condition */
1880 if (node == tree)
1881 node = NULL;
1882 } else
1883 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001884 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001885 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001886}
1887
1888/**
1889 * xmlShellPwd:
1890 * @ctxt: the shell context
1891 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00001892 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00001893 * @node2: unused
1894 *
1895 * Implements the XML shell function "pwd"
1896 * Show the full path from the root to the node, if needed building
1897 * thumblers when similar elements exists at a given ancestor level.
1898 * The output is compatible with XPath commands.
1899 *
1900 * Returns 0 or -1 in case of error
1901 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001902int
1903xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
1904 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1905{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001906 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00001907
Daniel Veillard78d12092001-10-11 09:12:24 +00001908 if (node == NULL)
1909 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001910
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001911 path = xmlGetNodePath(node);
1912 if (path == NULL)
1913 return (-1);
1914
1915 /*
1916 * This test prevents buffer overflow, because this routine
1917 * is only called by xmlShell, in which the second argument is
1918 * 500 chars long.
1919 * It is a dirty hack before a cleaner solution is found.
1920 * Documentation should mention that the second argument must
1921 * be at least 500 chars long, and could be stripped if too long.
1922 */
1923 snprintf(buffer, 499, "%s", path);
1924 buffer[499] = '0';
1925 xmlFree(path);
1926
Daniel Veillard78d12092001-10-11 09:12:24 +00001927 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001928}
1929
1930/**
1931 * xmlShell
1932 * @doc: the initial document
1933 * @filename: the output buffer
1934 * @input: the line reading function
1935 * @output: the output FILE*
1936 *
1937 * Implements the XML shell
1938 * This allow to load, validate, view, modify and save a document
1939 * using a environment similar to a UNIX commandline.
1940 */
1941void
1942xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00001943 FILE * output)
1944{
Owen Taylor3473f882001-02-23 17:55:21 +00001945 char prompt[500] = "/ > ";
1946 char *cmdline = NULL, *cur;
1947 int nbargs;
1948 char command[100];
1949 char arg[400];
1950 int i;
1951 xmlShellCtxtPtr ctxt;
1952 xmlXPathObjectPtr list;
1953
1954 if (doc == NULL)
1955 return;
1956 if (filename == NULL)
1957 return;
1958 if (input == NULL)
1959 return;
1960 if (output == NULL)
1961 return;
1962 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00001963 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00001964 return;
1965 ctxt->loaded = 0;
1966 ctxt->doc = doc;
1967 ctxt->input = input;
1968 ctxt->output = output;
1969 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00001970 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001971
1972#ifdef LIBXML_XPATH_ENABLED
1973 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1974 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001975 xmlFree(ctxt);
1976 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001977 }
1978#endif /* LIBXML_XPATH_ENABLED */
1979 while (1) {
1980 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Daniel Veillard78d12092001-10-11 09:12:24 +00001981 sprintf(prompt, "%s > ", "/");
1982 else if (ctxt->node->name)
1983 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001984 else
Daniel Veillard78d12092001-10-11 09:12:24 +00001985 sprintf(prompt, "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00001986 prompt[sizeof(prompt) - 1] = 0;
1987
Daniel Veillard78d12092001-10-11 09:12:24 +00001988 /*
1989 * Get a new command line
1990 */
Owen Taylor3473f882001-02-23 17:55:21 +00001991 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00001992 if (cmdline == NULL)
1993 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001994
Daniel Veillard78d12092001-10-11 09:12:24 +00001995 /*
1996 * Parse the command itself
1997 */
1998 cur = cmdline;
1999 nbargs = 0;
2000 while ((*cur == ' ') || (*cur == '\t'))
2001 cur++;
2002 i = 0;
2003 while ((*cur != ' ') && (*cur != '\t') &&
2004 (*cur != '\n') && (*cur != '\r')) {
2005 if (*cur == 0)
2006 break;
2007 command[i++] = *cur++;
2008 }
2009 command[i] = 0;
2010 if (i == 0)
2011 continue;
2012 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002013
Daniel Veillard78d12092001-10-11 09:12:24 +00002014 /*
2015 * Parse the argument
2016 */
2017 while ((*cur == ' ') || (*cur == '\t'))
2018 cur++;
2019 i = 0;
2020 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2021 if (*cur == 0)
2022 break;
2023 arg[i++] = *cur++;
2024 }
2025 arg[i] = 0;
2026 if (i != 0)
2027 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002028
Daniel Veillard78d12092001-10-11 09:12:24 +00002029 /*
2030 * start interpreting the command
2031 */
Owen Taylor3473f882001-02-23 17:55:21 +00002032 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002033 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002034 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002035 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002036 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002037 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002038 if (!strcmp(command, "help")) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00002039 fprintf(stdout, "\tbase display XML base of the node\n");
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002040 fprintf(stdout, "\tsetbase URI change the XML base of the node\n");
Daniel Veillardcd337f02001-11-22 18:20:37 +00002041 fprintf(stdout, "\tbye leave shell\n");
2042 fprintf(stdout, "\tcat [node] display node or current node\n");
2043 fprintf(stdout, "\tcd [path] change directory to path or to root\n");
2044 fprintf(stdout, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2045 fprintf(stdout, "\tdu [path] show the structure of the subtree under path or the current node\n");
2046 fprintf(stdout, "\texit leave shell\n");
2047 fprintf(stdout, "\thelp display this help\n");
2048 fprintf(stdout, "\tfree display memory usage\n");
2049 fprintf(stdout, "\tload [name] load a new document with name\n");
2050 fprintf(stdout, "\tls [path] list contents of path or the current directory\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002051#ifdef LIBXML_XPATH_ENABLED
2052 fprintf(stdout, "\txpath expr evaluate the XPath expression in that context and print the result\n");
2053#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcd337f02001-11-22 18:20:37 +00002054 fprintf(stdout, "\tpwd display current working directory\n");
2055 fprintf(stdout, "\tquit leave shell\n");
2056 fprintf(stdout, "\tsave [name] save this document to name or the original name\n");
2057 fprintf(stdout, "\tvalidate check the document for errors\n");
2058 fprintf(stdout, "\twrite [name] write the current node to the filename\n");
Daniel Veillard5004f422001-11-08 13:53:05 +00002059 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002060 xmlShellValidate(ctxt, arg, NULL, NULL);
2061 } else if (!strcmp(command, "load")) {
2062 xmlShellLoad(ctxt, arg, NULL, NULL);
2063 } else if (!strcmp(command, "save")) {
2064 xmlShellSave(ctxt, arg, NULL, NULL);
2065 } else if (!strcmp(command, "write")) {
2066 xmlShellWrite(ctxt, arg, NULL, NULL);
2067 } else if (!strcmp(command, "free")) {
2068 if (arg[0] == 0) {
2069 xmlMemShow(stdout, 0);
2070 } else {
2071 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002072
Daniel Veillard78d12092001-10-11 09:12:24 +00002073 sscanf(arg, "%d", &len);
2074 xmlMemShow(stdout, len);
2075 }
2076 } else if (!strcmp(command, "pwd")) {
2077 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002078
Daniel Veillard78d12092001-10-11 09:12:24 +00002079 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillardcd337f02001-11-22 18:20:37 +00002080 fprintf(stdout, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002081 } else if (!strcmp(command, "du")) {
2082 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2083 } else if (!strcmp(command, "base")) {
2084 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002085#ifdef LIBXML_XPATH_ENABLED
2086 } else if (!strcmp(command, "xpath")) {
2087 if (arg[0] == 0) {
2088 xmlGenericError(xmlGenericErrorContext,
2089 "xpath: expression required\n");
2090 } else {
2091 ctxt->pctxt->node = ctxt->node;
2092 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2093 xmlXPathDebugDumpObject(stdout, list, 0);
2094 xmlXPathFreeObject(list);
2095 }
2096#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002097 } else if (!strcmp(command, "setbase")) {
2098 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002099 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2100 int dir = (!strcmp(command, "dir"));
2101
2102 if (arg[0] == 0) {
2103 if (dir)
2104 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2105 else
2106 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2107 } else {
2108 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002109#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002110 ctxt->pctxt->node = ctxt->node;
2111 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2112#else
2113 list = NULL;
2114#endif /* LIBXML_XPATH_ENABLED */
2115 if (list != NULL) {
2116 switch (list->type) {
2117 case XPATH_UNDEFINED:
2118 xmlGenericError(xmlGenericErrorContext,
2119 "%s: no such node\n", arg);
2120 break;
2121 case XPATH_NODESET:{
2122 int indx;
2123
Daniel Veillarda6825e82001-11-07 13:33:59 +00002124 if (list->nodesetval == NULL)
2125 break;
2126
Daniel Veillard78d12092001-10-11 09:12:24 +00002127 for (indx = 0;
2128 indx < list->nodesetval->nodeNr;
2129 indx++) {
2130 if (dir)
2131 xmlShellDir(ctxt, NULL,
2132 list->nodesetval->
2133 nodeTab[indx], NULL);
2134 else
2135 xmlShellList(ctxt, NULL,
2136 list->nodesetval->
2137 nodeTab[indx], NULL);
2138 }
2139 break;
2140 }
2141 case XPATH_BOOLEAN:
2142 xmlGenericError(xmlGenericErrorContext,
2143 "%s is a Boolean\n", arg);
2144 break;
2145 case XPATH_NUMBER:
2146 xmlGenericError(xmlGenericErrorContext,
2147 "%s is a number\n", arg);
2148 break;
2149 case XPATH_STRING:
2150 xmlGenericError(xmlGenericErrorContext,
2151 "%s is a string\n", arg);
2152 break;
2153 case XPATH_POINT:
2154 xmlGenericError(xmlGenericErrorContext,
2155 "%s is a point\n", arg);
2156 break;
2157 case XPATH_RANGE:
2158 xmlGenericError(xmlGenericErrorContext,
2159 "%s is a range\n", arg);
2160 break;
2161 case XPATH_LOCATIONSET:
2162 xmlGenericError(xmlGenericErrorContext,
2163 "%s is a range\n", arg);
2164 break;
2165 case XPATH_USERS:
2166 xmlGenericError(xmlGenericErrorContext,
2167 "%s is user-defined\n", arg);
2168 break;
2169 case XPATH_XSLT_TREE:
2170 xmlGenericError(xmlGenericErrorContext,
2171 "%s is an XSLT value tree\n",
2172 arg);
2173 break;
2174 }
2175#ifdef LIBXML_XPATH_ENABLED
2176 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002177#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002178 } else {
2179 xmlGenericError(xmlGenericErrorContext,
2180 "%s: no such node\n", arg);
2181 }
2182 ctxt->pctxt->node = NULL;
2183 }
2184 } else if (!strcmp(command, "cd")) {
2185 if (arg[0] == 0) {
2186 ctxt->node = (xmlNodePtr) ctxt->doc;
2187 } else {
2188#ifdef LIBXML_XPATH_ENABLED
2189 ctxt->pctxt->node = ctxt->node;
2190 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2191#else
2192 list = NULL;
2193#endif /* LIBXML_XPATH_ENABLED */
2194 if (list != NULL) {
2195 switch (list->type) {
2196 case XPATH_UNDEFINED:
2197 xmlGenericError(xmlGenericErrorContext,
2198 "%s: no such node\n", arg);
2199 break;
2200 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002201 if (list->nodesetval != NULL) {
2202 if (list->nodesetval->nodeNr == 1) {
2203 ctxt->node = list->nodesetval->nodeTab[0];
2204 } else
2205 xmlGenericError(xmlGenericErrorContext,
2206 "%s is a %d Node Set\n",
2207 arg,
2208 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002209 } else
2210 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002211 "%s is an empty Node Set\n",
2212 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002213 break;
2214 case XPATH_BOOLEAN:
2215 xmlGenericError(xmlGenericErrorContext,
2216 "%s is a Boolean\n", arg);
2217 break;
2218 case XPATH_NUMBER:
2219 xmlGenericError(xmlGenericErrorContext,
2220 "%s is a number\n", arg);
2221 break;
2222 case XPATH_STRING:
2223 xmlGenericError(xmlGenericErrorContext,
2224 "%s is a string\n", arg);
2225 break;
2226 case XPATH_POINT:
2227 xmlGenericError(xmlGenericErrorContext,
2228 "%s is a point\n", arg);
2229 break;
2230 case XPATH_RANGE:
2231 xmlGenericError(xmlGenericErrorContext,
2232 "%s is a range\n", arg);
2233 break;
2234 case XPATH_LOCATIONSET:
2235 xmlGenericError(xmlGenericErrorContext,
2236 "%s is a range\n", arg);
2237 break;
2238 case XPATH_USERS:
2239 xmlGenericError(xmlGenericErrorContext,
2240 "%s is user-defined\n", arg);
2241 break;
2242 case XPATH_XSLT_TREE:
2243 xmlGenericError(xmlGenericErrorContext,
2244 "%s is an XSLT value tree\n",
2245 arg);
2246 break;
2247 }
2248#ifdef LIBXML_XPATH_ENABLED
2249 xmlXPathFreeObject(list);
2250#endif
2251 } else {
2252 xmlGenericError(xmlGenericErrorContext,
2253 "%s: no such node\n", arg);
2254 }
2255 ctxt->pctxt->node = NULL;
2256 }
2257 } else if (!strcmp(command, "cat")) {
2258 if (arg[0] == 0) {
2259 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2260 } else {
2261 ctxt->pctxt->node = ctxt->node;
2262#ifdef LIBXML_XPATH_ENABLED
2263 ctxt->pctxt->node = ctxt->node;
2264 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2265#else
2266 list = NULL;
2267#endif /* LIBXML_XPATH_ENABLED */
2268 if (list != NULL) {
2269 switch (list->type) {
2270 case XPATH_UNDEFINED:
2271 xmlGenericError(xmlGenericErrorContext,
2272 "%s: no such node\n", arg);
2273 break;
2274 case XPATH_NODESET:{
2275 int indx;
2276
Daniel Veillarda6825e82001-11-07 13:33:59 +00002277 if (list->nodesetval == NULL)
2278 break;
2279
Daniel Veillard78d12092001-10-11 09:12:24 +00002280 for (indx = 0;
2281 indx < list->nodesetval->nodeNr;
2282 indx++) {
2283 if (i > 0)
Daniel Veillardcd337f02001-11-22 18:20:37 +00002284 fprintf(stdout, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002285 xmlShellCat(ctxt, NULL,
2286 list->nodesetval->
2287 nodeTab[indx], NULL);
2288 }
2289 break;
2290 }
2291 case XPATH_BOOLEAN:
2292 xmlGenericError(xmlGenericErrorContext,
2293 "%s is a Boolean\n", arg);
2294 break;
2295 case XPATH_NUMBER:
2296 xmlGenericError(xmlGenericErrorContext,
2297 "%s is a number\n", arg);
2298 break;
2299 case XPATH_STRING:
2300 xmlGenericError(xmlGenericErrorContext,
2301 "%s is a string\n", arg);
2302 break;
2303 case XPATH_POINT:
2304 xmlGenericError(xmlGenericErrorContext,
2305 "%s is a point\n", arg);
2306 break;
2307 case XPATH_RANGE:
2308 xmlGenericError(xmlGenericErrorContext,
2309 "%s is a range\n", arg);
2310 break;
2311 case XPATH_LOCATIONSET:
2312 xmlGenericError(xmlGenericErrorContext,
2313 "%s is a range\n", arg);
2314 break;
2315 case XPATH_USERS:
2316 xmlGenericError(xmlGenericErrorContext,
2317 "%s is user-defined\n", arg);
2318 break;
2319 case XPATH_XSLT_TREE:
2320 xmlGenericError(xmlGenericErrorContext,
2321 "%s is an XSLT value tree\n",
2322 arg);
2323 break;
2324 }
2325#ifdef LIBXML_XPATH_ENABLED
2326 xmlXPathFreeObject(list);
2327#endif
2328 } else {
2329 xmlGenericError(xmlGenericErrorContext,
2330 "%s: no such node\n", arg);
2331 }
2332 ctxt->pctxt->node = NULL;
2333 }
2334 } else {
2335 xmlGenericError(xmlGenericErrorContext,
2336 "Unknown command %s\n", command);
2337 }
2338 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002339 }
2340#ifdef LIBXML_XPATH_ENABLED
2341 xmlXPathFreeContext(ctxt->pctxt);
2342#endif /* LIBXML_XPATH_ENABLED */
2343 if (ctxt->loaded) {
2344 xmlFreeDoc(ctxt->doc);
2345 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002346 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002347 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002348 xmlFree(ctxt);
2349 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002350 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002351}
2352
2353#endif /* LIBXML_DEBUG_ENABLED */