blob: c485038a9aac4710a34fc2f3b3c82a9a35d54d3c [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>
Daniel Veillard0ba59232002-02-10 13:20:39 +000030#include <libxml/xpathInternals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000031
Daniel Veillard5e2dace2001-07-18 19:30:27 +000032/**
33 * xmlDebugDumpString:
34 * @output: the FILE * for the output
35 * @str: the string
36 *
37 * Dumps informations about the string, shorten it if necessary
38 */
39void
40xmlDebugDumpString(FILE * output, const xmlChar * str)
41{
Owen Taylor3473f882001-02-23 17:55:21 +000042 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000043
Daniel Veillard7db38712002-02-07 16:39:11 +000044 if (output == NULL)
45 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +000046 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000047 fprintf(output, "(NULL)");
48 return;
Owen Taylor3473f882001-02-23 17:55:21 +000049 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000050 for (i = 0; i < 40; i++)
51 if (str[i] == 0)
52 return;
53 else if (IS_BLANK(str[i]))
54 fputc(' ', output);
55 else if (str[i] >= 0x80)
56 fprintf(output, "#%X", str[i]);
57 else
58 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000059 fprintf(output, "...");
60}
61
Daniel Veillard56a4cb82001-03-24 17:00:36 +000062static void
63xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000064 int i;
65 char shift[100];
66
67 for (i = 0;((i < depth) && (i < 25));i++)
68 shift[2 * i] = shift[2 * i + 1] = ' ';
69 shift[2 * i] = shift[2 * i + 1] = 0;
70
71 fprintf(output, shift);
72
Daniel Veillard5e926fa2002-01-22 21:44:25 +000073 if (dtd == NULL) {
74 fprintf(output, "DTD node is NULL\n");
75 return;
76 }
77
Owen Taylor3473f882001-02-23 17:55:21 +000078 if (dtd->type != XML_DTD_NODE) {
79 fprintf(output, "PBM: not a DTD\n");
80 return;
81 }
82 if (dtd->name != NULL)
83 fprintf(output, "DTD(%s)", dtd->name);
84 else
85 fprintf(output, "DTD");
86 if (dtd->ExternalID != NULL)
87 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
88 if (dtd->SystemID != NULL)
89 fprintf(output, ", SYSTEM %s", dtd->SystemID);
90 fprintf(output, "\n");
91 /*
92 * Do a bit of checking
93 */
94 if (dtd->parent == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000095 fprintf(output, "PBM: DTD has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +000096 if (dtd->doc == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000097 fprintf(output, "PBM: DTD has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +000098 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +000099 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000100 if (dtd->prev == NULL) {
101 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000102 fprintf(output, "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000103 } else {
104 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000105 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000106 }
107 if (dtd->next == NULL) {
108 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000109 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000110 } else {
111 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000112 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000113 }
114}
115
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000116static void
117xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000118 int i;
119 char shift[100];
120
121 for (i = 0;((i < depth) && (i < 25));i++)
122 shift[2 * i] = shift[2 * i + 1] = ' ';
123 shift[2 * i] = shift[2 * i + 1] = 0;
124
125 fprintf(output, shift);
126
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000127 if (attr == NULL) {
128 fprintf(output, "Attribute declaration is NULL\n");
129 return;
130 }
Owen Taylor3473f882001-02-23 17:55:21 +0000131 if (attr->type != XML_ATTRIBUTE_DECL) {
132 fprintf(output, "PBM: not a Attr\n");
133 return;
134 }
135 if (attr->name != NULL)
136 fprintf(output, "ATTRDECL(%s)", attr->name);
137 else
138 fprintf(output, "PBM ATTRDECL noname!!!");
139 if (attr->elem != NULL)
140 fprintf(output, " for %s", attr->elem);
141 else
142 fprintf(output, " PBM noelem!!!");
143 switch (attr->atype) {
144 case XML_ATTRIBUTE_CDATA:
145 fprintf(output, " CDATA");
146 break;
147 case XML_ATTRIBUTE_ID:
148 fprintf(output, " ID");
149 break;
150 case XML_ATTRIBUTE_IDREF:
151 fprintf(output, " IDREF");
152 break;
153 case XML_ATTRIBUTE_IDREFS:
154 fprintf(output, " IDREFS");
155 break;
156 case XML_ATTRIBUTE_ENTITY:
157 fprintf(output, " ENTITY");
158 break;
159 case XML_ATTRIBUTE_ENTITIES:
160 fprintf(output, " ENTITIES");
161 break;
162 case XML_ATTRIBUTE_NMTOKEN:
163 fprintf(output, " NMTOKEN");
164 break;
165 case XML_ATTRIBUTE_NMTOKENS:
166 fprintf(output, " NMTOKENS");
167 break;
168 case XML_ATTRIBUTE_ENUMERATION:
169 fprintf(output, " ENUMERATION");
170 break;
171 case XML_ATTRIBUTE_NOTATION:
172 fprintf(output, " NOTATION ");
173 break;
174 }
175 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000176 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000177 xmlEnumerationPtr cur = attr->tree;
178
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000179 for (indx = 0;indx < 5; indx++) {
180 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000181 fprintf(output, "|%s", cur->name);
182 else
183 fprintf(output, " (%s", cur->name);
184 cur = cur->next;
185 if (cur == NULL) break;
186 }
187 if (cur == NULL)
188 fprintf(output, ")");
189 else
190 fprintf(output, "...)");
191 }
192 switch (attr->def) {
193 case XML_ATTRIBUTE_NONE:
194 break;
195 case XML_ATTRIBUTE_REQUIRED:
196 fprintf(output, " REQUIRED");
197 break;
198 case XML_ATTRIBUTE_IMPLIED:
199 fprintf(output, " IMPLIED");
200 break;
201 case XML_ATTRIBUTE_FIXED:
202 fprintf(output, " FIXED");
203 break;
204 }
205 if (attr->defaultValue != NULL) {
206 fprintf(output, "\"");
207 xmlDebugDumpString(output, attr->defaultValue);
208 fprintf(output, "\"");
209 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000210 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000211
212 /*
213 * Do a bit of checking
214 */
215 if (attr->parent == NULL)
216 fprintf(output, "PBM: Attr has no parent\n");
217 if (attr->doc == NULL)
218 fprintf(output, "PBM: Attr has no doc\n");
219 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
220 fprintf(output, "PBM: Attr doc differs from parent's one\n");
221 if (attr->prev == NULL) {
222 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
223 fprintf(output, "PBM: Attr has no prev and not first of list\n");
224 } else {
225 if (attr->prev->next != (xmlNodePtr) attr)
226 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
227 }
228 if (attr->next == NULL) {
229 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
230 fprintf(output, "PBM: Attr has no next and not last of list\n");
231 } else {
232 if (attr->next->prev != (xmlNodePtr) attr)
233 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
234 }
235}
236
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000237static void
238xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000239 int i;
240 char shift[100];
241
242 for (i = 0;((i < depth) && (i < 25));i++)
243 shift[2 * i] = shift[2 * i + 1] = ' ';
244 shift[2 * i] = shift[2 * i + 1] = 0;
245
246 fprintf(output, shift);
247
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000248 if (elem == NULL) {
249 fprintf(output, "Element declaration is NULL\n");
250 return;
251 }
Owen Taylor3473f882001-02-23 17:55:21 +0000252 if (elem->type != XML_ELEMENT_DECL) {
253 fprintf(output, "PBM: not a Elem\n");
254 return;
255 }
256 if (elem->name != NULL) {
257 fprintf(output, "ELEMDECL(");
258 xmlDebugDumpString(output, elem->name);
259 fprintf(output, ")");
260 } else
261 fprintf(output, "PBM ELEMDECL noname!!!");
262 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000263 case XML_ELEMENT_TYPE_UNDEFINED:
264 fprintf(output, ", UNDEFINED");
265 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000266 case XML_ELEMENT_TYPE_EMPTY:
267 fprintf(output, ", EMPTY");
268 break;
269 case XML_ELEMENT_TYPE_ANY:
270 fprintf(output, ", ANY");
271 break;
272 case XML_ELEMENT_TYPE_MIXED:
273 fprintf(output, ", MIXED ");
274 break;
275 case XML_ELEMENT_TYPE_ELEMENT:
276 fprintf(output, ", MIXED ");
277 break;
278 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000279 if ((elem->type != XML_ELEMENT_NODE) &&
280 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000281 char buf[5001];
282
283 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000284 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000285 buf[5000] = 0;
286 fprintf(output, "%s", buf);
287 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000288 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000289
290 /*
291 * Do a bit of checking
292 */
293 if (elem->parent == NULL)
294 fprintf(output, "PBM: Elem has no parent\n");
295 if (elem->doc == NULL)
296 fprintf(output, "PBM: Elem has no doc\n");
297 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
298 fprintf(output, "PBM: Elem doc differs from parent's one\n");
299 if (elem->prev == NULL) {
300 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
301 fprintf(output, "PBM: Elem has no prev and not first of list\n");
302 } else {
303 if (elem->prev->next != (xmlNodePtr) elem)
304 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
305 }
306 if (elem->next == NULL) {
307 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
308 fprintf(output, "PBM: Elem has no next and not last of list\n");
309 } else {
310 if (elem->next->prev != (xmlNodePtr) elem)
311 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
312 }
313}
314
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000315static void
316xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000317 int i;
318 char shift[100];
319
320 for (i = 0;((i < depth) && (i < 25));i++)
321 shift[2 * i] = shift[2 * i + 1] = ' ';
322 shift[2 * i] = shift[2 * i + 1] = 0;
323
324 fprintf(output, shift);
325
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000326 if (ent == NULL) {
327 fprintf(output, "Entity declaration is NULL\n");
328 return;
329 }
Owen Taylor3473f882001-02-23 17:55:21 +0000330 if (ent->type != XML_ENTITY_DECL) {
331 fprintf(output, "PBM: not a Entity decl\n");
332 return;
333 }
334 if (ent->name != NULL) {
335 fprintf(output, "ENTITYDECL(");
336 xmlDebugDumpString(output, ent->name);
337 fprintf(output, ")");
338 } else
339 fprintf(output, "PBM ENTITYDECL noname!!!");
340 switch (ent->etype) {
341 case XML_INTERNAL_GENERAL_ENTITY:
342 fprintf(output, ", internal\n");
343 break;
344 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
345 fprintf(output, ", external parsed\n");
346 break;
347 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
348 fprintf(output, ", unparsed\n");
349 break;
350 case XML_INTERNAL_PARAMETER_ENTITY:
351 fprintf(output, ", parameter\n");
352 break;
353 case XML_EXTERNAL_PARAMETER_ENTITY:
354 fprintf(output, ", external parameter\n");
355 break;
356 case XML_INTERNAL_PREDEFINED_ENTITY:
357 fprintf(output, ", predefined\n");
358 break;
359 }
360 if (ent->ExternalID) {
361 fprintf(output, shift);
362 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
363 }
364 if (ent->SystemID) {
365 fprintf(output, shift);
366 fprintf(output, " SystemID=%s\n", ent->SystemID);
367 }
368 if (ent->URI != NULL) {
369 fprintf(output, shift);
370 fprintf(output, " URI=%s\n", ent->URI);
371 }
372 if (ent->content) {
373 fprintf(output, shift);
374 fprintf(output, " content=");
375 xmlDebugDumpString(output, ent->content);
376 fprintf(output, "\n");
377 }
378
379 /*
380 * Do a bit of checking
381 */
382 if (ent->parent == NULL)
383 fprintf(output, "PBM: Ent has no parent\n");
384 if (ent->doc == NULL)
385 fprintf(output, "PBM: Ent has no doc\n");
386 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
387 fprintf(output, "PBM: Ent doc differs from parent's one\n");
388 if (ent->prev == NULL) {
389 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
390 fprintf(output, "PBM: Ent has no prev and not first of list\n");
391 } else {
392 if (ent->prev->next != (xmlNodePtr) ent)
393 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
394 }
395 if (ent->next == NULL) {
396 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
397 fprintf(output, "PBM: Ent has no next and not last of list\n");
398 } else {
399 if (ent->next->prev != (xmlNodePtr) ent)
400 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
401 }
402}
403
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000404static void
405xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000406 int i;
407 char shift[100];
408
409 for (i = 0;((i < depth) && (i < 25));i++)
410 shift[2 * i] = shift[2 * i + 1] = ' ';
411 shift[2 * i] = shift[2 * i + 1] = 0;
412
413 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000414
415 if (ns == NULL) {
416 fprintf(output, "namespace node is NULL\n");
417 return;
418 }
Owen Taylor3473f882001-02-23 17:55:21 +0000419 if (ns->type != XML_NAMESPACE_DECL) {
420 fprintf(output, "invalid namespace node %d\n", ns->type);
421 return;
422 }
423 if (ns->href == NULL) {
424 if (ns->prefix != NULL)
425 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
426 else
427 fprintf(output, "incomplete default namespace href=NULL\n");
428 } else {
429 if (ns->prefix != NULL)
430 fprintf(output, "namespace %s href=", ns->prefix);
431 else
432 fprintf(output, "default namespace href=");
433
434 xmlDebugDumpString(output, ns->href);
435 fprintf(output, "\n");
436 }
437}
438
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000439static void
440xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000441 while (ns != NULL) {
442 xmlDebugDumpNamespace(output, ns, depth);
443 ns = ns->next;
444 }
445}
446
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000447static void
448xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000449 int i;
450 char shift[100];
451
452 for (i = 0;((i < depth) && (i < 25));i++)
453 shift[2 * i] = shift[2 * i + 1] = ' ';
454 shift[2 * i] = shift[2 * i + 1] = 0;
455
456 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000457
458 if (ent == NULL) {
459 fprintf(output, "Entity is NULL\n");
460 return;
461 }
Owen Taylor3473f882001-02-23 17:55:21 +0000462 switch (ent->etype) {
463 case XML_INTERNAL_GENERAL_ENTITY:
464 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
465 break;
466 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
467 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
468 break;
469 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
470 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
471 break;
472 case XML_INTERNAL_PARAMETER_ENTITY:
473 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
474 break;
475 case XML_EXTERNAL_PARAMETER_ENTITY:
476 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
477 break;
478 default:
479 fprintf(output, "ENTITY_%d ! ", ent->etype);
480 }
481 fprintf(output, "%s\n", ent->name);
482 if (ent->ExternalID) {
483 fprintf(output, shift);
484 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
485 }
486 if (ent->SystemID) {
487 fprintf(output, shift);
488 fprintf(output, "SystemID=%s\n", ent->SystemID);
489 }
490 if (ent->URI) {
491 fprintf(output, shift);
492 fprintf(output, "URI=%s\n", ent->URI);
493 }
494 if (ent->content) {
495 fprintf(output, shift);
496 fprintf(output, "content=");
497 xmlDebugDumpString(output, ent->content);
498 fprintf(output, "\n");
499 }
500}
501
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000502/**
503 * xmlDebugDumpAttr:
504 * @output: the FILE * for the output
505 * @attr: the attribute
506 * @depth: the indentation level.
507 *
508 * Dumps debug information for the attribute
509 */
510void
511xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000512 int i;
513 char shift[100];
514
515 for (i = 0;((i < depth) && (i < 25));i++)
516 shift[2 * i] = shift[2 * i + 1] = ' ';
517 shift[2 * i] = shift[2 * i + 1] = 0;
518
519 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000520
521 if (attr == NULL) {
522 fprintf(output, "Attr is NULL");
523 return;
524 }
Owen Taylor3473f882001-02-23 17:55:21 +0000525 fprintf(output, "ATTRIBUTE ");
526 xmlDebugDumpString(output, attr->name);
527 fprintf(output, "\n");
528 if (attr->children != NULL)
529 xmlDebugDumpNodeList(output, attr->children, depth + 1);
530
531 /*
532 * Do a bit of checking
533 */
534 if (attr->parent == NULL)
535 fprintf(output, "PBM: Attr has no parent\n");
536 if (attr->doc == NULL)
537 fprintf(output, "PBM: Attr has no doc\n");
538 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
539 fprintf(output, "PBM: Attr doc differs from parent's one\n");
540 if (attr->prev == NULL) {
541 if ((attr->parent != NULL) && (attr->parent->properties != attr))
542 fprintf(output, "PBM: Attr has no prev and not first of list\n");
543 } else {
544 if (attr->prev->next != attr)
545 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
546 }
547 if (attr->next != NULL) {
548 if (attr->next->prev != attr)
549 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
550 }
551}
552
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000553/**
554 * xmlDebugDumpAttrList:
555 * @output: the FILE * for the output
556 * @attr: the attribute list
557 * @depth: the indentation level.
558 *
559 * Dumps debug information for the attribute list
560 */
561void
562xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
563{
Daniel Veillard7db38712002-02-07 16:39:11 +0000564 if (output == NULL)
565 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000566 while (attr != NULL) {
567 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000568 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000569 }
570}
571
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000572/**
573 * xmlDebugDumpOneNode:
574 * @output: the FILE * for the output
575 * @node: the node
576 * @depth: the indentation level.
577 *
578 * Dumps debug information for the element node, it is not recursive
579 */
580void
581xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
582{
Owen Taylor3473f882001-02-23 17:55:21 +0000583 int i;
584 char shift[100];
585
Daniel Veillard7db38712002-02-07 16:39:11 +0000586 if (output == NULL)
587 output = stdout;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000588 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000589 shift[2 * i] = shift[2 * i + 1] = ' ';
590 shift[2 * i] = shift[2 * i + 1] = 0;
591
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000592 if (node == NULL) {
593 fprintf(output, shift);
594 fprintf(output, "node is NULL\n");
595 return;
596 }
Owen Taylor3473f882001-02-23 17:55:21 +0000597 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000598 case XML_ELEMENT_NODE:
599 fprintf(output, shift);
600 fprintf(output, "ELEMENT ");
601 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
602 xmlDebugDumpString(output, node->ns->prefix);
603 fprintf(output, ":");
604 }
605 xmlDebugDumpString(output, node->name);
606 fprintf(output, "\n");
607 break;
608 case XML_ATTRIBUTE_NODE:
609 fprintf(output, shift);
610 fprintf(output, "Error, ATTRIBUTE found here\n");
611 break;
612 case XML_TEXT_NODE:
613 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000614 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000615 fprintf(output, "TEXT no enc\n");
616 else
617 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000618 break;
619 case XML_CDATA_SECTION_NODE:
620 fprintf(output, shift);
621 fprintf(output, "CDATA_SECTION\n");
622 break;
623 case XML_ENTITY_REF_NODE:
624 fprintf(output, shift);
625 fprintf(output, "ENTITY_REF(%s)\n", node->name);
626 break;
627 case XML_ENTITY_NODE:
628 fprintf(output, shift);
629 fprintf(output, "ENTITY\n");
630 break;
631 case XML_PI_NODE:
632 fprintf(output, shift);
633 fprintf(output, "PI %s\n", node->name);
634 break;
635 case XML_COMMENT_NODE:
636 fprintf(output, shift);
637 fprintf(output, "COMMENT\n");
638 break;
639 case XML_DOCUMENT_NODE:
640 case XML_HTML_DOCUMENT_NODE:
641 fprintf(output, shift);
642 fprintf(output, "Error, DOCUMENT found here\n");
643 break;
644 case XML_DOCUMENT_TYPE_NODE:
645 fprintf(output, shift);
646 fprintf(output, "DOCUMENT_TYPE\n");
647 break;
648 case XML_DOCUMENT_FRAG_NODE:
649 fprintf(output, shift);
650 fprintf(output, "DOCUMENT_FRAG\n");
651 break;
652 case XML_NOTATION_NODE:
653 fprintf(output, shift);
654 fprintf(output, "NOTATION\n");
655 break;
656 case XML_DTD_NODE:
657 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
658 return;
659 case XML_ELEMENT_DECL:
660 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
661 return;
662 case XML_ATTRIBUTE_DECL:
663 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
664 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000665 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000666 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
667 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000668 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000669 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
670 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000671 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000672 fprintf(output, shift);
673 fprintf(output, "INCLUDE START\n");
674 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000675 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000676 fprintf(output, shift);
677 fprintf(output, "INCLUDE END\n");
678 return;
679 default:
680 fprintf(output, shift);
681 fprintf(output, "NODE_%d !!!\n", node->type);
682 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000683 }
684 if (node->doc == NULL) {
685 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000686 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000687 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000688 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000689 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
690 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000691 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000692 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000693 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
694 shift[2 * i] = shift[2 * i + 1] = ' ';
695 shift[2 * i + 2] = shift[2 * i + 3] = 0;
696 fprintf(output, shift);
697 fprintf(output, "content=");
698#ifndef XML_USE_BUFFER_CONTENT
699 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +0000700#else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000701 xmlDebugDumpString(output, xmlBufferContent(node->content));
Owen Taylor3473f882001-02-23 17:55:21 +0000702#endif
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000703 fprintf(output, "\n");
704 }
Owen Taylor3473f882001-02-23 17:55:21 +0000705 } else {
706 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000707
708 ent = xmlGetDocEntity(node->doc, node->name);
709 if (ent != NULL)
710 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000711 }
712 /*
713 * Do a bit of checking
714 */
715 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000716 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000717 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000718 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000719 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000720 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000721 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000722 if ((node->parent != NULL) && (node->parent->children != node))
723 fprintf(output,
724 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000725 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000726 if (node->prev->next != node)
727 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000728 }
729 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000730 if ((node->parent != NULL) && (node->parent->last != node))
731 fprintf(output,
732 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000733 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000734 if (node->next->prev != node)
735 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000736 }
737}
738
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000739/**
740 * xmlDebugDumpNode:
741 * @output: the FILE * for the output
742 * @node: the node
743 * @depth: the indentation level.
744 *
745 * Dumps debug information for the element node, it is recursive
746 */
747void
748xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
749{
Daniel Veillard7db38712002-02-07 16:39:11 +0000750 if (output == NULL)
751 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000752 if (node == NULL) {
753 int i;
754 char shift[100];
755
756 for (i = 0; ((i < depth) && (i < 25)); i++)
757 shift[2 * i] = shift[2 * i + 1] = ' ';
758 shift[2 * i] = shift[2 * i + 1] = 0;
759
760 fprintf(output, shift);
761 fprintf(output, "node is NULL\n");
762 return;
763 }
Owen Taylor3473f882001-02-23 17:55:21 +0000764 xmlDebugDumpOneNode(output, node, depth);
765 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000766 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000767}
768
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000769/**
770 * xmlDebugDumpNodeList:
771 * @output: the FILE * for the output
772 * @node: the node list
773 * @depth: the indentation level.
774 *
775 * Dumps debug information for the list of element node, it is recursive
776 */
777void
778xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
779{
Daniel Veillard7db38712002-02-07 16:39:11 +0000780 if (output == NULL)
781 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000782 while (node != NULL) {
783 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000784 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000785 }
786}
787
788
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000789/**
790 * xmlDebugDumpDocumentHead:
791 * @output: the FILE * for the output
792 * @doc: the document
793 *
794 * Dumps debug information cncerning the document, not recursive
795 */
796void
797xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
798{
799 if (output == NULL)
800 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000801 if (doc == NULL) {
802 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000803 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000804 }
805
806 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000807 case XML_ELEMENT_NODE:
808 fprintf(output, "Error, ELEMENT found here ");
809 break;
810 case XML_ATTRIBUTE_NODE:
811 fprintf(output, "Error, ATTRIBUTE found here\n");
812 break;
813 case XML_TEXT_NODE:
814 fprintf(output, "Error, TEXT\n");
815 break;
816 case XML_CDATA_SECTION_NODE:
817 fprintf(output, "Error, CDATA_SECTION\n");
818 break;
819 case XML_ENTITY_REF_NODE:
820 fprintf(output, "Error, ENTITY_REF\n");
821 break;
822 case XML_ENTITY_NODE:
823 fprintf(output, "Error, ENTITY\n");
824 break;
825 case XML_PI_NODE:
826 fprintf(output, "Error, PI\n");
827 break;
828 case XML_COMMENT_NODE:
829 fprintf(output, "Error, COMMENT\n");
830 break;
831 case XML_DOCUMENT_NODE:
832 fprintf(output, "DOCUMENT\n");
833 break;
834 case XML_HTML_DOCUMENT_NODE:
835 fprintf(output, "HTML DOCUMENT\n");
836 break;
837 case XML_DOCUMENT_TYPE_NODE:
838 fprintf(output, "Error, DOCUMENT_TYPE\n");
839 break;
840 case XML_DOCUMENT_FRAG_NODE:
841 fprintf(output, "Error, DOCUMENT_FRAG\n");
842 break;
843 case XML_NOTATION_NODE:
844 fprintf(output, "Error, NOTATION\n");
845 break;
846 default:
847 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000848 }
849 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000850 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000851 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000852 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000853 }
854 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000855 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000856 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000857 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000858 }
859 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000860 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000861 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000862 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000863 }
864 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000865 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000866 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000867 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000868 }
869 if (doc->standalone)
870 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000871 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000872 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
873}
874
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000875/**
876 * xmlDebugDumpDocument:
877 * @output: the FILE * for the output
878 * @doc: the document
879 *
880 * Dumps debug information for the document, it's recursive
881 */
882void
883xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
884{
885 if (output == NULL)
886 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000887 if (doc == NULL) {
888 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000889 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000890 }
891 xmlDebugDumpDocumentHead(output, doc);
892 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000893 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000894 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000895}
Owen Taylor3473f882001-02-23 17:55:21 +0000896
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000897/**
898 * xmlDebugDumpDTD:
899 * @output: the FILE * for the output
900 * @dtd: the DTD
901 *
902 * Dumps debug information for the DTD
903 */
904void
905xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
906{
Daniel Veillard7db38712002-02-07 16:39:11 +0000907 if (output == NULL)
908 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000909 if (dtd == NULL) {
910 fprintf(output, "DTD is NULL\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000911 return;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000912 }
Owen Taylor3473f882001-02-23 17:55:21 +0000913 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000914 fprintf(output, "PBM: not a DTD\n");
915 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000916 }
917 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000918 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000919 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000920 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000921 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000922 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000923 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000924 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000925 fprintf(output, "\n");
926 /*
927 * Do a bit of checking
928 */
929 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000930 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000931 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000932 if ((dtd->parent != NULL)
933 && (dtd->parent->children != (xmlNodePtr) dtd))
934 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000935 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000936 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000937 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000938 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000939 }
940 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000941 if ((dtd->parent != NULL)
942 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000943 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000944 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000945 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000946 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000947 }
948 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000949 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000950 else
951 xmlDebugDumpNodeList(output, dtd->children, 1);
952}
953
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000954static void
955xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000956 if (cur == NULL) {
957 fprintf(output, "Entity is NULL");
958 return;
959 }
Owen Taylor3473f882001-02-23 17:55:21 +0000960 fprintf(output, "%s : ", cur->name);
961 switch (cur->etype) {
962 case XML_INTERNAL_GENERAL_ENTITY:
963 fprintf(output, "INTERNAL GENERAL, ");
964 break;
965 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
966 fprintf(output, "EXTERNAL PARSED, ");
967 break;
968 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
969 fprintf(output, "EXTERNAL UNPARSED, ");
970 break;
971 case XML_INTERNAL_PARAMETER_ENTITY:
972 fprintf(output, "INTERNAL PARAMETER, ");
973 break;
974 case XML_EXTERNAL_PARAMETER_ENTITY:
975 fprintf(output, "EXTERNAL PARAMETER, ");
976 break;
977 default:
978 fprintf(output, "UNKNOWN TYPE %d",
979 cur->etype);
980 }
981 if (cur->ExternalID != NULL)
982 fprintf(output, "ID \"%s\"", cur->ExternalID);
983 if (cur->SystemID != NULL)
984 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
985 if (cur->orig != NULL)
986 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000987 if ((cur->type != XML_ELEMENT_NODE) &&
988 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000989 fprintf(output, "\n content \"%s\"", cur->content);
990 fprintf(output, "\n");
991}
992
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000993/**
994 * xmlDebugDumpEntities:
995 * @output: the FILE * for the output
996 * @doc: the document
997 *
998 * Dumps debug information for all the entities in use by the document
999 */
1000void
1001xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1002{
1003 if (output == NULL)
1004 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001005 if (doc == NULL) {
1006 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001007 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001008 }
1009
1010 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001011 case XML_ELEMENT_NODE:
1012 fprintf(output, "Error, ELEMENT found here ");
1013 break;
1014 case XML_ATTRIBUTE_NODE:
1015 fprintf(output, "Error, ATTRIBUTE found here\n");
1016 break;
1017 case XML_TEXT_NODE:
1018 fprintf(output, "Error, TEXT\n");
1019 break;
1020 case XML_CDATA_SECTION_NODE:
1021 fprintf(output, "Error, CDATA_SECTION\n");
1022 break;
1023 case XML_ENTITY_REF_NODE:
1024 fprintf(output, "Error, ENTITY_REF\n");
1025 break;
1026 case XML_ENTITY_NODE:
1027 fprintf(output, "Error, ENTITY\n");
1028 break;
1029 case XML_PI_NODE:
1030 fprintf(output, "Error, PI\n");
1031 break;
1032 case XML_COMMENT_NODE:
1033 fprintf(output, "Error, COMMENT\n");
1034 break;
1035 case XML_DOCUMENT_NODE:
1036 fprintf(output, "DOCUMENT\n");
1037 break;
1038 case XML_HTML_DOCUMENT_NODE:
1039 fprintf(output, "HTML DOCUMENT\n");
1040 break;
1041 case XML_DOCUMENT_TYPE_NODE:
1042 fprintf(output, "Error, DOCUMENT_TYPE\n");
1043 break;
1044 case XML_DOCUMENT_FRAG_NODE:
1045 fprintf(output, "Error, DOCUMENT_FRAG\n");
1046 break;
1047 case XML_NOTATION_NODE:
1048 fprintf(output, "Error, NOTATION\n");
1049 break;
1050 default:
1051 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +00001052 }
1053 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001054 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1055 doc->intSubset->entities;
1056
1057 fprintf(output, "Entities in internal subset\n");
1058 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1059 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001060 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001061 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001062 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001063 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1064 doc->extSubset->entities;
1065
1066 fprintf(output, "Entities in external subset\n");
1067 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1068 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001069 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001070 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001071}
1072
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001073/**
1074 * xmlLsCountNode:
1075 * @node: the node to count
1076 *
1077 * Count the children of @node.
1078 *
1079 * Returns the number of children of @node.
1080 */
1081int
1082xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001083 int ret = 0;
1084 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001085
1086 if (node == NULL)
1087 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001088
1089 switch (node->type) {
1090 case XML_ELEMENT_NODE:
1091 list = node->children;
1092 break;
1093 case XML_DOCUMENT_NODE:
1094 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001095#ifdef LIBXML_DOCB_ENABLED
1096 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001097#endif
1098 list = ((xmlDocPtr) node)->children;
1099 break;
1100 case XML_ATTRIBUTE_NODE:
1101 list = ((xmlAttrPtr) node)->children;
1102 break;
1103 case XML_TEXT_NODE:
1104 case XML_CDATA_SECTION_NODE:
1105 case XML_PI_NODE:
1106 case XML_COMMENT_NODE:
1107 if (node->content != NULL) {
1108#ifndef XML_USE_BUFFER_CONTENT
1109 ret = xmlStrlen(node->content);
1110#else
1111 ret = xmlBufferLength(node->content);
1112#endif
1113 }
1114 break;
1115 case XML_ENTITY_REF_NODE:
1116 case XML_DOCUMENT_TYPE_NODE:
1117 case XML_ENTITY_NODE:
1118 case XML_DOCUMENT_FRAG_NODE:
1119 case XML_NOTATION_NODE:
1120 case XML_DTD_NODE:
1121 case XML_ELEMENT_DECL:
1122 case XML_ATTRIBUTE_DECL:
1123 case XML_ENTITY_DECL:
1124 case XML_NAMESPACE_DECL:
1125 case XML_XINCLUDE_START:
1126 case XML_XINCLUDE_END:
1127 ret = 1;
1128 break;
1129 }
1130 for (;list != NULL;ret++)
1131 list = list->next;
1132 return(ret);
1133}
1134
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001135/**
1136 * xmlLsOneNode:
1137 * @output: the FILE * for the output
1138 * @node: the node to dump
1139 *
1140 * Dump to @output the type and name of @node.
1141 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001142void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001143xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001144 if (node == NULL) {
1145 fprintf(output, "NULL\n");
1146 return;
1147 }
Owen Taylor3473f882001-02-23 17:55:21 +00001148 switch (node->type) {
1149 case XML_ELEMENT_NODE:
1150 fprintf(output, "-");
1151 break;
1152 case XML_ATTRIBUTE_NODE:
1153 fprintf(output, "a");
1154 break;
1155 case XML_TEXT_NODE:
1156 fprintf(output, "t");
1157 break;
1158 case XML_CDATA_SECTION_NODE:
1159 fprintf(output, "c");
1160 break;
1161 case XML_ENTITY_REF_NODE:
1162 fprintf(output, "e");
1163 break;
1164 case XML_ENTITY_NODE:
1165 fprintf(output, "E");
1166 break;
1167 case XML_PI_NODE:
1168 fprintf(output, "p");
1169 break;
1170 case XML_COMMENT_NODE:
1171 fprintf(output, "c");
1172 break;
1173 case XML_DOCUMENT_NODE:
1174 fprintf(output, "d");
1175 break;
1176 case XML_HTML_DOCUMENT_NODE:
1177 fprintf(output, "h");
1178 break;
1179 case XML_DOCUMENT_TYPE_NODE:
1180 fprintf(output, "T");
1181 break;
1182 case XML_DOCUMENT_FRAG_NODE:
1183 fprintf(output, "F");
1184 break;
1185 case XML_NOTATION_NODE:
1186 fprintf(output, "N");
1187 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001188 case XML_NAMESPACE_DECL:
1189 fprintf(output, "n");
1190 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001191 default:
1192 fprintf(output, "?");
1193 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001194 if (node->type != XML_NAMESPACE_DECL) {
1195 if (node->properties != NULL)
1196 fprintf(output, "a");
1197 else
1198 fprintf(output, "-");
1199 if (node->nsDef != NULL)
1200 fprintf(output, "n");
1201 else
1202 fprintf(output, "-");
1203 }
Owen Taylor3473f882001-02-23 17:55:21 +00001204
1205 fprintf(output, " %8d ", xmlLsCountNode(node));
1206
1207 switch (node->type) {
1208 case XML_ELEMENT_NODE:
1209 if (node->name != NULL)
1210 fprintf(output, "%s", node->name);
1211 break;
1212 case XML_ATTRIBUTE_NODE:
1213 if (node->name != NULL)
1214 fprintf(output, "%s", node->name);
1215 break;
1216 case XML_TEXT_NODE:
1217 if (node->content != NULL) {
1218#ifndef XML_USE_BUFFER_CONTENT
1219 xmlDebugDumpString(output, node->content);
1220#else
1221 xmlDebugDumpString(output, xmlBufferContent(node->content));
1222#endif
1223 }
1224 break;
1225 case XML_CDATA_SECTION_NODE:
1226 break;
1227 case XML_ENTITY_REF_NODE:
1228 if (node->name != NULL)
1229 fprintf(output, "%s", node->name);
1230 break;
1231 case XML_ENTITY_NODE:
1232 if (node->name != NULL)
1233 fprintf(output, "%s", node->name);
1234 break;
1235 case XML_PI_NODE:
1236 if (node->name != NULL)
1237 fprintf(output, "%s", node->name);
1238 break;
1239 case XML_COMMENT_NODE:
1240 break;
1241 case XML_DOCUMENT_NODE:
1242 break;
1243 case XML_HTML_DOCUMENT_NODE:
1244 break;
1245 case XML_DOCUMENT_TYPE_NODE:
1246 break;
1247 case XML_DOCUMENT_FRAG_NODE:
1248 break;
1249 case XML_NOTATION_NODE:
1250 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001251 case XML_NAMESPACE_DECL: {
1252 xmlNsPtr ns = (xmlNsPtr) node;
1253
1254 if (ns->prefix == NULL)
1255 fprintf(output, "default -> %s", ns->href);
1256 else
1257 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1258 break;
1259 }
Owen Taylor3473f882001-02-23 17:55:21 +00001260 default:
1261 if (node->name != NULL)
1262 fprintf(output, "%s", node->name);
1263 }
1264 fprintf(output, "\n");
1265}
1266
Daniel Veillard78d12092001-10-11 09:12:24 +00001267/**
1268 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001269 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001270 *
1271 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001272 *
1273 * Returns a pointer to either "True" or "False"
1274 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001275const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001276xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001277{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001278 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001279 return("True");
1280 else
1281 return("False");
1282}
1283
Owen Taylor3473f882001-02-23 17:55:21 +00001284/****************************************************************
1285 * *
1286 * The XML shell related functions *
1287 * *
1288 ****************************************************************/
1289
Daniel Veillard78d12092001-10-11 09:12:24 +00001290
1291
Owen Taylor3473f882001-02-23 17:55:21 +00001292/*
1293 * TODO: Improvement/cleanups for the XML shell
1294 * - allow to shell out an editor on a subpart
1295 * - cleanup function registrations (with help) and calling
1296 * - provide registration routines
1297 */
1298
1299/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001300 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001301 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001302 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001303 *
1304 * Print the xpath error to libxml default error channel
1305 */
1306void
1307xmlShellPrintXPathError(int errorType, const char *arg)
1308{
1309 const char *default_arg = "Result";
1310
1311 if (!arg)
1312 arg = default_arg;
1313
1314 switch (errorType) {
1315 case XPATH_UNDEFINED:
1316 xmlGenericError(xmlGenericErrorContext,
1317 "%s: no such node\n", arg);
1318 break;
1319
1320 case XPATH_BOOLEAN:
1321 xmlGenericError(xmlGenericErrorContext,
1322 "%s is a Boolean\n", arg);
1323 break;
1324 case XPATH_NUMBER:
1325 xmlGenericError(xmlGenericErrorContext,
1326 "%s is a number\n", arg);
1327 break;
1328 case XPATH_STRING:
1329 xmlGenericError(xmlGenericErrorContext,
1330 "%s is a string\n", arg);
1331 break;
1332 case XPATH_POINT:
1333 xmlGenericError(xmlGenericErrorContext,
1334 "%s is a point\n", arg);
1335 break;
1336 case XPATH_RANGE:
1337 xmlGenericError(xmlGenericErrorContext,
1338 "%s is a range\n", arg);
1339 break;
1340 case XPATH_LOCATIONSET:
1341 xmlGenericError(xmlGenericErrorContext,
1342 "%s is a range\n", arg);
1343 break;
1344 case XPATH_USERS:
1345 xmlGenericError(xmlGenericErrorContext,
1346 "%s is user-defined\n", arg);
1347 break;
1348 case XPATH_XSLT_TREE:
1349 xmlGenericError(xmlGenericErrorContext,
1350 "%s is an XSLT value tree\n", arg);
1351 break;
1352 }
1353 xmlGenericError(xmlGenericErrorContext,
1354 "Try casting the result string function (xpath builtin)\n",
1355 arg);
1356}
1357
1358
1359/**
1360 * xmlShellPrintNode:
1361 * @node : a non-null node to print to stdout
1362 *
1363 * Print node to stdout
1364 */
1365void
1366xmlShellPrintNode(xmlNodePtr node)
1367{
1368 if (!node)
1369 return;
1370
1371 if (node->type == XML_DOCUMENT_NODE)
1372 xmlDocDump(stdout, (xmlDocPtr) node);
1373 else if (node->type == XML_ATTRIBUTE_NODE)
1374 xmlDebugDumpAttrList(stdout, (xmlAttrPtr) node, 0);
1375 else
1376 xmlElemDump(stdout, node->doc, node);
1377
1378 fprintf(stdout, "\n");
1379}
1380
1381
1382/**
1383 * xmlShellPrintXPathResult:
Daniel Veillard9d06d302002-01-22 18:15:52 +00001384 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001385 *
1386 * Prints result to stdout
1387 */
1388void
1389xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1390{
1391 int i = 0;
1392
1393 if (list != NULL) {
1394 switch (list->type) {
1395 case XPATH_NODESET:{
1396 int indx;
1397
1398 if (list->nodesetval) {
1399 for (indx = 0; indx < list->nodesetval->nodeNr;
1400 indx++) {
1401 if (i > 0)
1402 fprintf(stderr, " -------\n");
1403 xmlShellPrintNode(list->nodesetval->
1404 nodeTab[indx]);
1405 }
1406 } else {
1407 xmlGenericError(xmlGenericErrorContext,
1408 "Empty node set\n");
1409 }
1410 break;
1411 }
1412 case XPATH_BOOLEAN:
1413 xmlGenericError(xmlGenericErrorContext,
1414 "Is a Boolean:%s\n",
1415 xmlBoolToText(list->boolval));
1416 break;
1417 case XPATH_NUMBER:
1418 xmlGenericError(xmlGenericErrorContext,
1419 "Is a number:%0g\n", list->floatval);
1420 break;
1421 case XPATH_STRING:
1422 xmlGenericError(xmlGenericErrorContext,
1423 "Is a string:%s\n", list->stringval);
1424 break;
1425
1426 default:
1427 xmlShellPrintXPathError(list->type, NULL);
1428 }
1429 }
1430}
1431
1432/**
Owen Taylor3473f882001-02-23 17:55:21 +00001433 * xmlShellList:
1434 * @ctxt: the shell context
1435 * @arg: unused
1436 * @node: a node
1437 * @node2: unused
1438 *
1439 * Implements the XML shell function "ls"
1440 * Does an Unix like listing of the given node (like a directory)
1441 *
1442 * Returns 0
1443 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001444int
1445xmlShellList(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1446 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1447 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1448{
Owen Taylor3473f882001-02-23 17:55:21 +00001449 xmlNodePtr cur;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001450 if (node == NULL) {
1451 fprintf(stdout, "NULL\n");
1452 return (0);
1453 }
Owen Taylor3473f882001-02-23 17:55:21 +00001454 if ((node->type == XML_DOCUMENT_NODE) ||
1455 (node->type == XML_HTML_DOCUMENT_NODE)) {
1456 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001457 } else if (node->type == XML_NAMESPACE_DECL) {
1458 xmlLsOneNode(stdout, node);
1459 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001460 } else if (node->children != NULL) {
1461 cur = node->children;
1462 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001463 xmlLsOneNode(stdout, node);
1464 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001465 }
1466 while (cur != NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001467 xmlLsOneNode(stdout, cur);
1468 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001469 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001470 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001471}
1472
1473/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001474 * xmlShellBase:
1475 * @ctxt: the shell context
1476 * @arg: unused
1477 * @node: a node
1478 * @node2: unused
1479 *
1480 * Implements the XML shell function "base"
1481 * dumps the current XML base of the node
1482 *
1483 * Returns 0
1484 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001485int
1486xmlShellBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1487 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1488 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1489{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001490 xmlChar *base;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001491 if (node == NULL) {
1492 fprintf(stdout, "NULL\n");
1493 return (0);
1494 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001495
1496 base = xmlNodeGetBase(node->doc, node);
1497
1498 if (base == NULL) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001499 fprintf(stdout, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001500 } else {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001501 fprintf(stdout, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001502 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001503 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001504 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001505}
1506
1507/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001508 * xmlShellSetBase:
1509 * @ctxt: the shell context
1510 * @arg: the new base
1511 * @node: a node
1512 * @node2: unused
1513 *
1514 * Implements the XML shell function "setbase"
1515 * change the current XML base of the node
1516 *
1517 * Returns 0
1518 */
1519static int
1520xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1521 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1522 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1523{
1524 xmlNodeSetBase(node, (xmlChar*) arg);
1525 return (0);
1526}
1527
1528/**
Owen Taylor3473f882001-02-23 17:55:21 +00001529 * xmlShellDir:
1530 * @ctxt: the shell context
1531 * @arg: unused
1532 * @node: a node
1533 * @node2: unused
1534 *
1535 * Implements the XML shell function "dir"
1536 * dumps informations about the node (namespace, attributes, content).
1537 *
1538 * Returns 0
1539 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001540int
1541xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1542 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1543 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1544{
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001545 if (node == NULL) {
1546 fprintf(stdout, "NULL\n");
1547 return (0);
1548 }
Owen Taylor3473f882001-02-23 17:55:21 +00001549 if ((node->type == XML_DOCUMENT_NODE) ||
1550 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001551 xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001552 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001553 xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001554 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001555 xmlDebugDumpOneNode(stdout, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001556 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001557 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001558}
1559
1560/**
1561 * xmlShellCat:
1562 * @ctxt: the shell context
1563 * @arg: unused
1564 * @node: a node
1565 * @node2: unused
1566 *
1567 * Implements the XML shell function "cat"
1568 * dumps the serialization node content (XML or HTML).
1569 *
1570 * Returns 0
1571 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001572int
1573xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1574 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1575{
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001576 if (node == NULL) {
1577 fprintf(stdout, "NULL\n");
1578 return (0);
1579 }
Owen Taylor3473f882001-02-23 17:55:21 +00001580 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1581#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001582 if (node->type == XML_HTML_DOCUMENT_NODE)
1583 htmlDocDump(stdout, (htmlDocPtr) node);
1584 else
1585 htmlNodeDumpFile(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001586#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001587 if (node->type == XML_DOCUMENT_NODE)
1588 xmlDocDump(stdout, (xmlDocPtr) node);
1589 else
1590 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001591#endif /* LIBXML_HTML_ENABLED */
1592 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001593 if (node->type == XML_DOCUMENT_NODE)
1594 xmlDocDump(stdout, (xmlDocPtr) node);
1595 else
1596 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001597 }
Daniel Veillardcd337f02001-11-22 18:20:37 +00001598 fprintf(stdout, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001599 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001600}
1601
1602/**
1603 * xmlShellLoad:
1604 * @ctxt: the shell context
1605 * @filename: the file name
1606 * @node: unused
1607 * @node2: unused
1608 *
1609 * Implements the XML shell function "load"
1610 * loads a new document specified by the filename
1611 *
1612 * Returns 0 or -1 if loading failed
1613 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001614int
1615xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1616 xmlNodePtr node ATTRIBUTE_UNUSED,
1617 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1618{
Owen Taylor3473f882001-02-23 17:55:21 +00001619 xmlDocPtr doc;
1620 int html = 0;
1621
1622 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001623 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001624
1625 if (html) {
1626#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001627 doc = htmlParseFile(filename, NULL);
1628#else
Daniel Veillardcd337f02001-11-22 18:20:37 +00001629 fprintf(stdout, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001630 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001631#endif /* LIBXML_HTML_ENABLED */
1632 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001633 doc = xmlParseFile(filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001634 }
1635 if (doc != NULL) {
1636 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001637 xmlFreeDoc(ctxt->doc);
1638 }
1639 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001640#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001641 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001642#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001643 xmlFree(ctxt->filename);
1644 ctxt->doc = doc;
1645 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001646#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001647 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001648#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001649 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001650 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001651 return (-1);
1652 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001653}
1654
1655/**
1656 * xmlShellWrite:
1657 * @ctxt: the shell context
1658 * @filename: the file name
1659 * @node: a node in the tree
1660 * @node2: unused
1661 *
1662 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001663 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001664 * of the subtree under the @node specified
1665 *
1666 * Returns 0 or -1 in case of error
1667 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001668int
Owen Taylor3473f882001-02-23 17:55:21 +00001669xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001670 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1671{
Owen Taylor3473f882001-02-23 17:55:21 +00001672 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001673 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001674 if ((filename == NULL) || (filename[0] == 0)) {
1675 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001676 "Write command requires a filename argument\n");
1677 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001678 }
1679#ifdef W_OK
1680 if (access((char *) filename, W_OK)) {
1681 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001682 "Cannot write to %s\n", filename);
1683 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001684 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001685#endif
1686 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001687 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001688 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1689 xmlGenericError(xmlGenericErrorContext,
1690 "Failed to write to %s\n", filename);
1691 return (-1);
1692 }
1693 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001694 case XML_HTML_DOCUMENT_NODE:
1695#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001696 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1697 xmlGenericError(xmlGenericErrorContext,
1698 "Failed to write to %s\n", filename);
1699 return (-1);
1700 }
Owen Taylor3473f882001-02-23 17:55:21 +00001701#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001702 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1703 xmlGenericError(xmlGenericErrorContext,
1704 "Failed to write to %s\n", filename);
1705 return (-1);
1706 }
Owen Taylor3473f882001-02-23 17:55:21 +00001707#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001708 break;
1709 default:{
1710 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001711
Daniel Veillard78d12092001-10-11 09:12:24 +00001712 f = fopen((char *) filename, "w");
1713 if (f == NULL) {
1714 xmlGenericError(xmlGenericErrorContext,
1715 "Failed to write to %s\n", filename);
1716 return (-1);
1717 }
1718 xmlElemDump(f, ctxt->doc, node);
1719 fclose(f);
1720 }
Owen Taylor3473f882001-02-23 17:55:21 +00001721 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001722 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001723}
1724
1725/**
1726 * xmlShellSave:
1727 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001728 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001729 * @node: unused
1730 * @node2: unused
1731 *
1732 * Implements the XML shell function "save"
1733 * Write the current document to the filename, or it's original name
1734 *
1735 * Returns 0 or -1 in case of error
1736 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001737int
1738xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1739 xmlNodePtr node ATTRIBUTE_UNUSED,
1740 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1741{
Owen Taylor3473f882001-02-23 17:55:21 +00001742 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001743 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001744 if ((filename == NULL) || (filename[0] == 0))
1745 filename = ctxt->filename;
1746#ifdef W_OK
1747 if (access((char *) filename, W_OK)) {
1748 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001749 "Cannot save to %s\n", filename);
1750 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001751 }
1752#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001753 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001754 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001755 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1756 xmlGenericError(xmlGenericErrorContext,
1757 "Failed to save to %s\n", filename);
1758 }
1759 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001760 case XML_HTML_DOCUMENT_NODE:
1761#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001762 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1763 xmlGenericError(xmlGenericErrorContext,
1764 "Failed to save to %s\n", filename);
1765 }
Owen Taylor3473f882001-02-23 17:55:21 +00001766#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001767 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1768 xmlGenericError(xmlGenericErrorContext,
1769 "Failed to save to %s\n", filename);
1770 }
Owen Taylor3473f882001-02-23 17:55:21 +00001771#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001772 break;
1773 default:
1774 xmlGenericError(xmlGenericErrorContext,
1775 "To save to subparts of a document use the 'write' command\n");
1776 return (-1);
1777
Owen Taylor3473f882001-02-23 17:55:21 +00001778 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001779 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001780}
1781
1782/**
1783 * xmlShellValidate:
1784 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001785 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001786 * @node: unused
1787 * @node2: unused
1788 *
1789 * Implements the XML shell function "validate"
1790 * Validate the document, if a DTD path is provided, then the validation
1791 * is done against the given DTD.
1792 *
1793 * Returns 0 or -1 in case of error
1794 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001795int
1796xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1797 xmlNodePtr node ATTRIBUTE_UNUSED,
1798 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1799{
Owen Taylor3473f882001-02-23 17:55:21 +00001800 xmlValidCtxt vctxt;
1801 int res = -1;
1802
1803 vctxt.userData = stderr;
1804 vctxt.error = (xmlValidityErrorFunc) fprintf;
1805 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1806
1807 if ((dtd == NULL) || (dtd[0] == 0)) {
1808 res = xmlValidateDocument(&vctxt, ctxt->doc);
1809 } else {
1810 xmlDtdPtr subset;
1811
Daniel Veillard78d12092001-10-11 09:12:24 +00001812 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1813 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001814 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1815
Daniel Veillard78d12092001-10-11 09:12:24 +00001816 xmlFreeDtd(subset);
1817 }
Owen Taylor3473f882001-02-23 17:55:21 +00001818 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001819 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00001820}
1821
1822/**
1823 * xmlShellDu:
1824 * @ctxt: the shell context
1825 * @arg: unused
1826 * @tree: a node defining a subtree
1827 * @node2: unused
1828 *
1829 * Implements the XML shell function "du"
1830 * show the structure of the subtree under node @tree
1831 * If @tree is null, the command works on the current node.
1832 *
1833 * Returns 0 or -1 in case of error
1834 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001835int
1836xmlShellDu(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1837 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1838 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1839{
Owen Taylor3473f882001-02-23 17:55:21 +00001840 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00001841 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00001842
Daniel Veillard78d12092001-10-11 09:12:24 +00001843 if (tree == NULL)
1844 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001845 node = tree;
1846 while (node != NULL) {
1847 if ((node->type == XML_DOCUMENT_NODE) ||
1848 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001849 fprintf(stdout, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001850 } else if (node->type == XML_ELEMENT_NODE) {
1851 for (i = 0; i < indent; i++)
Daniel Veillardcd337f02001-11-22 18:20:37 +00001852 fprintf(stdout, " ");
1853 fprintf(stdout, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00001854 } else {
1855 }
Owen Taylor3473f882001-02-23 17:55:21 +00001856
Daniel Veillard78d12092001-10-11 09:12:24 +00001857 /*
1858 * Browse the full subtree, deep first
1859 */
Owen Taylor3473f882001-02-23 17:55:21 +00001860
1861 if ((node->type == XML_DOCUMENT_NODE) ||
1862 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001863 node = ((xmlDocPtr) node)->children;
1864 } else if ((node->children != NULL)
1865 && (node->type != XML_ENTITY_REF_NODE)) {
1866 /* deep first */
1867 node = node->children;
1868 indent++;
1869 } else if ((node != tree) && (node->next != NULL)) {
1870 /* then siblings */
1871 node = node->next;
1872 } else if (node != tree) {
1873 /* go up to parents->next if needed */
1874 while (node != tree) {
1875 if (node->parent != NULL) {
1876 node = node->parent;
1877 indent--;
1878 }
1879 if ((node != tree) && (node->next != NULL)) {
1880 node = node->next;
1881 break;
1882 }
1883 if (node->parent == NULL) {
1884 node = NULL;
1885 break;
1886 }
1887 if (node == tree) {
1888 node = NULL;
1889 break;
1890 }
1891 }
1892 /* exit condition */
1893 if (node == tree)
1894 node = NULL;
1895 } else
1896 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001897 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001898 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001899}
1900
1901/**
1902 * xmlShellPwd:
1903 * @ctxt: the shell context
1904 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00001905 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00001906 * @node2: unused
1907 *
1908 * Implements the XML shell function "pwd"
1909 * Show the full path from the root to the node, if needed building
1910 * thumblers when similar elements exists at a given ancestor level.
1911 * The output is compatible with XPath commands.
1912 *
1913 * Returns 0 or -1 in case of error
1914 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001915int
1916xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
1917 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1918{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001919 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00001920
Daniel Veillard78d12092001-10-11 09:12:24 +00001921 if (node == NULL)
1922 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001923
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001924 path = xmlGetNodePath(node);
1925 if (path == NULL)
1926 return (-1);
1927
1928 /*
1929 * This test prevents buffer overflow, because this routine
1930 * is only called by xmlShell, in which the second argument is
1931 * 500 chars long.
1932 * It is a dirty hack before a cleaner solution is found.
1933 * Documentation should mention that the second argument must
1934 * be at least 500 chars long, and could be stripped if too long.
1935 */
1936 snprintf(buffer, 499, "%s", path);
1937 buffer[499] = '0';
1938 xmlFree(path);
1939
Daniel Veillard78d12092001-10-11 09:12:24 +00001940 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001941}
1942
1943/**
1944 * xmlShell
1945 * @doc: the initial document
1946 * @filename: the output buffer
1947 * @input: the line reading function
1948 * @output: the output FILE*
1949 *
1950 * Implements the XML shell
1951 * This allow to load, validate, view, modify and save a document
1952 * using a environment similar to a UNIX commandline.
1953 */
1954void
1955xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00001956 FILE * output)
1957{
Owen Taylor3473f882001-02-23 17:55:21 +00001958 char prompt[500] = "/ > ";
1959 char *cmdline = NULL, *cur;
1960 int nbargs;
1961 char command[100];
1962 char arg[400];
1963 int i;
1964 xmlShellCtxtPtr ctxt;
1965 xmlXPathObjectPtr list;
1966
1967 if (doc == NULL)
1968 return;
1969 if (filename == NULL)
1970 return;
1971 if (input == NULL)
1972 return;
1973 if (output == NULL)
1974 return;
1975 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00001976 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00001977 return;
1978 ctxt->loaded = 0;
1979 ctxt->doc = doc;
1980 ctxt->input = input;
1981 ctxt->output = output;
1982 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00001983 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001984
1985#ifdef LIBXML_XPATH_ENABLED
1986 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1987 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001988 xmlFree(ctxt);
1989 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001990 }
1991#endif /* LIBXML_XPATH_ENABLED */
1992 while (1) {
1993 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Daniel Veillard78d12092001-10-11 09:12:24 +00001994 sprintf(prompt, "%s > ", "/");
1995 else if (ctxt->node->name)
1996 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001997 else
Daniel Veillard78d12092001-10-11 09:12:24 +00001998 sprintf(prompt, "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00001999 prompt[sizeof(prompt) - 1] = 0;
2000
Daniel Veillard78d12092001-10-11 09:12:24 +00002001 /*
2002 * Get a new command line
2003 */
Owen Taylor3473f882001-02-23 17:55:21 +00002004 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00002005 if (cmdline == NULL)
2006 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002007
Daniel Veillard78d12092001-10-11 09:12:24 +00002008 /*
2009 * Parse the command itself
2010 */
2011 cur = cmdline;
2012 nbargs = 0;
2013 while ((*cur == ' ') || (*cur == '\t'))
2014 cur++;
2015 i = 0;
2016 while ((*cur != ' ') && (*cur != '\t') &&
2017 (*cur != '\n') && (*cur != '\r')) {
2018 if (*cur == 0)
2019 break;
2020 command[i++] = *cur++;
2021 }
2022 command[i] = 0;
2023 if (i == 0)
2024 continue;
2025 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002026
Daniel Veillard78d12092001-10-11 09:12:24 +00002027 /*
2028 * Parse the argument
2029 */
2030 while ((*cur == ' ') || (*cur == '\t'))
2031 cur++;
2032 i = 0;
2033 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2034 if (*cur == 0)
2035 break;
2036 arg[i++] = *cur++;
2037 }
2038 arg[i] = 0;
2039 if (i != 0)
2040 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002041
Daniel Veillard78d12092001-10-11 09:12:24 +00002042 /*
2043 * start interpreting the command
2044 */
Owen Taylor3473f882001-02-23 17:55:21 +00002045 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002046 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002047 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002048 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002049 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002050 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002051 if (!strcmp(command, "help")) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00002052 fprintf(stdout, "\tbase display XML base of the node\n");
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002053 fprintf(stdout, "\tsetbase URI change the XML base of the node\n");
Daniel Veillardcd337f02001-11-22 18:20:37 +00002054 fprintf(stdout, "\tbye leave shell\n");
2055 fprintf(stdout, "\tcat [node] display node or current node\n");
2056 fprintf(stdout, "\tcd [path] change directory to path or to root\n");
2057 fprintf(stdout, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2058 fprintf(stdout, "\tdu [path] show the structure of the subtree under path or the current node\n");
2059 fprintf(stdout, "\texit leave shell\n");
2060 fprintf(stdout, "\thelp display this help\n");
2061 fprintf(stdout, "\tfree display memory usage\n");
2062 fprintf(stdout, "\tload [name] load a new document with name\n");
2063 fprintf(stdout, "\tls [path] list contents of path or the current directory\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002064#ifdef LIBXML_XPATH_ENABLED
2065 fprintf(stdout, "\txpath expr evaluate the XPath expression in that context and print the result\n");
2066#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcd337f02001-11-22 18:20:37 +00002067 fprintf(stdout, "\tpwd display current working directory\n");
2068 fprintf(stdout, "\tquit leave shell\n");
2069 fprintf(stdout, "\tsave [name] save this document to name or the original name\n");
2070 fprintf(stdout, "\tvalidate check the document for errors\n");
2071 fprintf(stdout, "\twrite [name] write the current node to the filename\n");
Daniel Veillard5004f422001-11-08 13:53:05 +00002072 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002073 xmlShellValidate(ctxt, arg, NULL, NULL);
2074 } else if (!strcmp(command, "load")) {
2075 xmlShellLoad(ctxt, arg, NULL, NULL);
2076 } else if (!strcmp(command, "save")) {
2077 xmlShellSave(ctxt, arg, NULL, NULL);
2078 } else if (!strcmp(command, "write")) {
2079 xmlShellWrite(ctxt, arg, NULL, NULL);
2080 } else if (!strcmp(command, "free")) {
2081 if (arg[0] == 0) {
2082 xmlMemShow(stdout, 0);
2083 } else {
2084 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002085
Daniel Veillard78d12092001-10-11 09:12:24 +00002086 sscanf(arg, "%d", &len);
2087 xmlMemShow(stdout, len);
2088 }
2089 } else if (!strcmp(command, "pwd")) {
2090 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002091
Daniel Veillard78d12092001-10-11 09:12:24 +00002092 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillardcd337f02001-11-22 18:20:37 +00002093 fprintf(stdout, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002094 } else if (!strcmp(command, "du")) {
2095 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2096 } else if (!strcmp(command, "base")) {
2097 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002098#ifdef LIBXML_XPATH_ENABLED
2099 } else if (!strcmp(command, "xpath")) {
2100 if (arg[0] == 0) {
2101 xmlGenericError(xmlGenericErrorContext,
2102 "xpath: expression required\n");
2103 } else {
2104 ctxt->pctxt->node = ctxt->node;
2105 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2106 xmlXPathDebugDumpObject(stdout, list, 0);
2107 xmlXPathFreeObject(list);
2108 }
2109#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002110 } else if (!strcmp(command, "setbase")) {
2111 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002112 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2113 int dir = (!strcmp(command, "dir"));
2114
2115 if (arg[0] == 0) {
2116 if (dir)
2117 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2118 else
2119 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2120 } else {
2121 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002122#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002123 ctxt->pctxt->node = ctxt->node;
2124 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2125#else
2126 list = NULL;
2127#endif /* LIBXML_XPATH_ENABLED */
2128 if (list != NULL) {
2129 switch (list->type) {
2130 case XPATH_UNDEFINED:
2131 xmlGenericError(xmlGenericErrorContext,
2132 "%s: no such node\n", arg);
2133 break;
2134 case XPATH_NODESET:{
2135 int indx;
2136
Daniel Veillarda6825e82001-11-07 13:33:59 +00002137 if (list->nodesetval == NULL)
2138 break;
2139
Daniel Veillard78d12092001-10-11 09:12:24 +00002140 for (indx = 0;
2141 indx < list->nodesetval->nodeNr;
2142 indx++) {
2143 if (dir)
2144 xmlShellDir(ctxt, NULL,
2145 list->nodesetval->
2146 nodeTab[indx], NULL);
2147 else
2148 xmlShellList(ctxt, NULL,
2149 list->nodesetval->
2150 nodeTab[indx], NULL);
2151 }
2152 break;
2153 }
2154 case XPATH_BOOLEAN:
2155 xmlGenericError(xmlGenericErrorContext,
2156 "%s is a Boolean\n", arg);
2157 break;
2158 case XPATH_NUMBER:
2159 xmlGenericError(xmlGenericErrorContext,
2160 "%s is a number\n", arg);
2161 break;
2162 case XPATH_STRING:
2163 xmlGenericError(xmlGenericErrorContext,
2164 "%s is a string\n", arg);
2165 break;
2166 case XPATH_POINT:
2167 xmlGenericError(xmlGenericErrorContext,
2168 "%s is a point\n", arg);
2169 break;
2170 case XPATH_RANGE:
2171 xmlGenericError(xmlGenericErrorContext,
2172 "%s is a range\n", arg);
2173 break;
2174 case XPATH_LOCATIONSET:
2175 xmlGenericError(xmlGenericErrorContext,
2176 "%s is a range\n", arg);
2177 break;
2178 case XPATH_USERS:
2179 xmlGenericError(xmlGenericErrorContext,
2180 "%s is user-defined\n", arg);
2181 break;
2182 case XPATH_XSLT_TREE:
2183 xmlGenericError(xmlGenericErrorContext,
2184 "%s is an XSLT value tree\n",
2185 arg);
2186 break;
2187 }
2188#ifdef LIBXML_XPATH_ENABLED
2189 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002190#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002191 } else {
2192 xmlGenericError(xmlGenericErrorContext,
2193 "%s: no such node\n", arg);
2194 }
2195 ctxt->pctxt->node = NULL;
2196 }
2197 } else if (!strcmp(command, "cd")) {
2198 if (arg[0] == 0) {
2199 ctxt->node = (xmlNodePtr) ctxt->doc;
2200 } else {
2201#ifdef LIBXML_XPATH_ENABLED
2202 ctxt->pctxt->node = ctxt->node;
2203 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2204#else
2205 list = NULL;
2206#endif /* LIBXML_XPATH_ENABLED */
2207 if (list != NULL) {
2208 switch (list->type) {
2209 case XPATH_UNDEFINED:
2210 xmlGenericError(xmlGenericErrorContext,
2211 "%s: no such node\n", arg);
2212 break;
2213 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002214 if (list->nodesetval != NULL) {
2215 if (list->nodesetval->nodeNr == 1) {
2216 ctxt->node = list->nodesetval->nodeTab[0];
2217 } else
2218 xmlGenericError(xmlGenericErrorContext,
2219 "%s is a %d Node Set\n",
2220 arg,
2221 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002222 } else
2223 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002224 "%s is an empty Node Set\n",
2225 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002226 break;
2227 case XPATH_BOOLEAN:
2228 xmlGenericError(xmlGenericErrorContext,
2229 "%s is a Boolean\n", arg);
2230 break;
2231 case XPATH_NUMBER:
2232 xmlGenericError(xmlGenericErrorContext,
2233 "%s is a number\n", arg);
2234 break;
2235 case XPATH_STRING:
2236 xmlGenericError(xmlGenericErrorContext,
2237 "%s is a string\n", arg);
2238 break;
2239 case XPATH_POINT:
2240 xmlGenericError(xmlGenericErrorContext,
2241 "%s is a point\n", arg);
2242 break;
2243 case XPATH_RANGE:
2244 xmlGenericError(xmlGenericErrorContext,
2245 "%s is a range\n", arg);
2246 break;
2247 case XPATH_LOCATIONSET:
2248 xmlGenericError(xmlGenericErrorContext,
2249 "%s is a range\n", arg);
2250 break;
2251 case XPATH_USERS:
2252 xmlGenericError(xmlGenericErrorContext,
2253 "%s is user-defined\n", arg);
2254 break;
2255 case XPATH_XSLT_TREE:
2256 xmlGenericError(xmlGenericErrorContext,
2257 "%s is an XSLT value tree\n",
2258 arg);
2259 break;
2260 }
2261#ifdef LIBXML_XPATH_ENABLED
2262 xmlXPathFreeObject(list);
2263#endif
2264 } else {
2265 xmlGenericError(xmlGenericErrorContext,
2266 "%s: no such node\n", arg);
2267 }
2268 ctxt->pctxt->node = NULL;
2269 }
2270 } else if (!strcmp(command, "cat")) {
2271 if (arg[0] == 0) {
2272 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2273 } else {
2274 ctxt->pctxt->node = ctxt->node;
2275#ifdef LIBXML_XPATH_ENABLED
2276 ctxt->pctxt->node = ctxt->node;
2277 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2278#else
2279 list = NULL;
2280#endif /* LIBXML_XPATH_ENABLED */
2281 if (list != NULL) {
2282 switch (list->type) {
2283 case XPATH_UNDEFINED:
2284 xmlGenericError(xmlGenericErrorContext,
2285 "%s: no such node\n", arg);
2286 break;
2287 case XPATH_NODESET:{
2288 int indx;
2289
Daniel Veillarda6825e82001-11-07 13:33:59 +00002290 if (list->nodesetval == NULL)
2291 break;
2292
Daniel Veillard78d12092001-10-11 09:12:24 +00002293 for (indx = 0;
2294 indx < list->nodesetval->nodeNr;
2295 indx++) {
2296 if (i > 0)
Daniel Veillardcd337f02001-11-22 18:20:37 +00002297 fprintf(stdout, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002298 xmlShellCat(ctxt, NULL,
2299 list->nodesetval->
2300 nodeTab[indx], NULL);
2301 }
2302 break;
2303 }
2304 case XPATH_BOOLEAN:
2305 xmlGenericError(xmlGenericErrorContext,
2306 "%s is a Boolean\n", arg);
2307 break;
2308 case XPATH_NUMBER:
2309 xmlGenericError(xmlGenericErrorContext,
2310 "%s is a number\n", arg);
2311 break;
2312 case XPATH_STRING:
2313 xmlGenericError(xmlGenericErrorContext,
2314 "%s is a string\n", arg);
2315 break;
2316 case XPATH_POINT:
2317 xmlGenericError(xmlGenericErrorContext,
2318 "%s is a point\n", arg);
2319 break;
2320 case XPATH_RANGE:
2321 xmlGenericError(xmlGenericErrorContext,
2322 "%s is a range\n", arg);
2323 break;
2324 case XPATH_LOCATIONSET:
2325 xmlGenericError(xmlGenericErrorContext,
2326 "%s is a range\n", arg);
2327 break;
2328 case XPATH_USERS:
2329 xmlGenericError(xmlGenericErrorContext,
2330 "%s is user-defined\n", arg);
2331 break;
2332 case XPATH_XSLT_TREE:
2333 xmlGenericError(xmlGenericErrorContext,
2334 "%s is an XSLT value tree\n",
2335 arg);
2336 break;
2337 }
2338#ifdef LIBXML_XPATH_ENABLED
2339 xmlXPathFreeObject(list);
2340#endif
2341 } else {
2342 xmlGenericError(xmlGenericErrorContext,
2343 "%s: no such node\n", arg);
2344 }
2345 ctxt->pctxt->node = NULL;
2346 }
2347 } else {
2348 xmlGenericError(xmlGenericErrorContext,
2349 "Unknown command %s\n", command);
2350 }
2351 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002352 }
2353#ifdef LIBXML_XPATH_ENABLED
2354 xmlXPathFreeContext(ctxt->pctxt);
2355#endif /* LIBXML_XPATH_ENABLED */
2356 if (ctxt->loaded) {
2357 xmlFreeDoc(ctxt->doc);
2358 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002359 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002360 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002361 xmlFree(ctxt);
2362 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002363 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002364}
2365
2366#endif /* LIBXML_DEBUG_ENABLED */