blob: df50f66ca7d12f7f8632317b1c49a3e5f6d48308 [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=");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000698 xmlDebugDumpString(output, node->content);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000699 fprintf(output, "\n");
700 }
Owen Taylor3473f882001-02-23 17:55:21 +0000701 } else {
702 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000703
704 ent = xmlGetDocEntity(node->doc, node->name);
705 if (ent != NULL)
706 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000707 }
708 /*
709 * Do a bit of checking
710 */
711 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000712 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000713 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000714 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000715 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000716 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000717 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000718 if ((node->parent != NULL) && (node->parent->children != node))
719 fprintf(output,
720 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000721 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000722 if (node->prev->next != node)
723 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000724 }
725 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000726 if ((node->parent != NULL) && (node->parent->last != node))
727 fprintf(output,
728 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000729 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000730 if (node->next->prev != node)
731 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000732 }
733}
734
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000735/**
736 * xmlDebugDumpNode:
737 * @output: the FILE * for the output
738 * @node: the node
739 * @depth: the indentation level.
740 *
741 * Dumps debug information for the element node, it is recursive
742 */
743void
744xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
745{
Daniel Veillard7db38712002-02-07 16:39:11 +0000746 if (output == NULL)
747 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000748 if (node == NULL) {
749 int i;
750 char shift[100];
751
752 for (i = 0; ((i < depth) && (i < 25)); i++)
753 shift[2 * i] = shift[2 * i + 1] = ' ';
754 shift[2 * i] = shift[2 * i + 1] = 0;
755
756 fprintf(output, shift);
757 fprintf(output, "node is NULL\n");
758 return;
759 }
Owen Taylor3473f882001-02-23 17:55:21 +0000760 xmlDebugDumpOneNode(output, node, depth);
761 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000762 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000763}
764
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000765/**
766 * xmlDebugDumpNodeList:
767 * @output: the FILE * for the output
768 * @node: the node list
769 * @depth: the indentation level.
770 *
771 * Dumps debug information for the list of element node, it is recursive
772 */
773void
774xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
775{
Daniel Veillard7db38712002-02-07 16:39:11 +0000776 if (output == NULL)
777 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000778 while (node != NULL) {
779 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000780 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000781 }
782}
783
784
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000785/**
786 * xmlDebugDumpDocumentHead:
787 * @output: the FILE * for the output
788 * @doc: the document
789 *
790 * Dumps debug information cncerning the document, not recursive
791 */
792void
793xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
794{
795 if (output == NULL)
796 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000797 if (doc == NULL) {
798 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000799 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000800 }
801
802 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000803 case XML_ELEMENT_NODE:
804 fprintf(output, "Error, ELEMENT found here ");
805 break;
806 case XML_ATTRIBUTE_NODE:
807 fprintf(output, "Error, ATTRIBUTE found here\n");
808 break;
809 case XML_TEXT_NODE:
810 fprintf(output, "Error, TEXT\n");
811 break;
812 case XML_CDATA_SECTION_NODE:
813 fprintf(output, "Error, CDATA_SECTION\n");
814 break;
815 case XML_ENTITY_REF_NODE:
816 fprintf(output, "Error, ENTITY_REF\n");
817 break;
818 case XML_ENTITY_NODE:
819 fprintf(output, "Error, ENTITY\n");
820 break;
821 case XML_PI_NODE:
822 fprintf(output, "Error, PI\n");
823 break;
824 case XML_COMMENT_NODE:
825 fprintf(output, "Error, COMMENT\n");
826 break;
827 case XML_DOCUMENT_NODE:
828 fprintf(output, "DOCUMENT\n");
829 break;
830 case XML_HTML_DOCUMENT_NODE:
831 fprintf(output, "HTML DOCUMENT\n");
832 break;
833 case XML_DOCUMENT_TYPE_NODE:
834 fprintf(output, "Error, DOCUMENT_TYPE\n");
835 break;
836 case XML_DOCUMENT_FRAG_NODE:
837 fprintf(output, "Error, DOCUMENT_FRAG\n");
838 break;
839 case XML_NOTATION_NODE:
840 fprintf(output, "Error, NOTATION\n");
841 break;
842 default:
843 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000844 }
845 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000846 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000847 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000848 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000849 }
850 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000851 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000852 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000853 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000854 }
855 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000856 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000857 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000858 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000859 }
860 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000861 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000862 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000863 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000864 }
865 if (doc->standalone)
866 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000867 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000868 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
869}
870
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000871/**
872 * xmlDebugDumpDocument:
873 * @output: the FILE * for the output
874 * @doc: the document
875 *
876 * Dumps debug information for the document, it's recursive
877 */
878void
879xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
880{
881 if (output == NULL)
882 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000883 if (doc == NULL) {
884 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000885 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000886 }
887 xmlDebugDumpDocumentHead(output, doc);
888 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000889 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000890 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000891}
Owen Taylor3473f882001-02-23 17:55:21 +0000892
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000893/**
894 * xmlDebugDumpDTD:
895 * @output: the FILE * for the output
896 * @dtd: the DTD
897 *
898 * Dumps debug information for the DTD
899 */
900void
901xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
902{
Daniel Veillard7db38712002-02-07 16:39:11 +0000903 if (output == NULL)
904 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000905 if (dtd == NULL) {
906 fprintf(output, "DTD is NULL\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000907 return;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000908 }
Owen Taylor3473f882001-02-23 17:55:21 +0000909 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000910 fprintf(output, "PBM: not a DTD\n");
911 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000912 }
913 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000914 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000915 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000916 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000917 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000918 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000919 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000920 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000921 fprintf(output, "\n");
922 /*
923 * Do a bit of checking
924 */
925 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000926 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000927 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000928 if ((dtd->parent != NULL)
929 && (dtd->parent->children != (xmlNodePtr) dtd))
930 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000931 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000932 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000933 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000934 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000935 }
936 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000937 if ((dtd->parent != NULL)
938 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000939 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000940 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000941 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000942 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000943 }
944 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000945 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000946 else
947 xmlDebugDumpNodeList(output, dtd->children, 1);
948}
949
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000950static void
951xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000952 if (cur == NULL) {
953 fprintf(output, "Entity is NULL");
954 return;
955 }
Owen Taylor3473f882001-02-23 17:55:21 +0000956 fprintf(output, "%s : ", cur->name);
957 switch (cur->etype) {
958 case XML_INTERNAL_GENERAL_ENTITY:
959 fprintf(output, "INTERNAL GENERAL, ");
960 break;
961 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
962 fprintf(output, "EXTERNAL PARSED, ");
963 break;
964 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
965 fprintf(output, "EXTERNAL UNPARSED, ");
966 break;
967 case XML_INTERNAL_PARAMETER_ENTITY:
968 fprintf(output, "INTERNAL PARAMETER, ");
969 break;
970 case XML_EXTERNAL_PARAMETER_ENTITY:
971 fprintf(output, "EXTERNAL PARAMETER, ");
972 break;
973 default:
974 fprintf(output, "UNKNOWN TYPE %d",
975 cur->etype);
976 }
977 if (cur->ExternalID != NULL)
978 fprintf(output, "ID \"%s\"", cur->ExternalID);
979 if (cur->SystemID != NULL)
980 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
981 if (cur->orig != NULL)
982 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000983 if ((cur->type != XML_ELEMENT_NODE) &&
984 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000985 fprintf(output, "\n content \"%s\"", cur->content);
986 fprintf(output, "\n");
987}
988
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000989/**
990 * xmlDebugDumpEntities:
991 * @output: the FILE * for the output
992 * @doc: the document
993 *
994 * Dumps debug information for all the entities in use by the document
995 */
996void
997xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
998{
999 if (output == NULL)
1000 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001001 if (doc == NULL) {
1002 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001003 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001004 }
1005
1006 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001007 case XML_ELEMENT_NODE:
1008 fprintf(output, "Error, ELEMENT found here ");
1009 break;
1010 case XML_ATTRIBUTE_NODE:
1011 fprintf(output, "Error, ATTRIBUTE found here\n");
1012 break;
1013 case XML_TEXT_NODE:
1014 fprintf(output, "Error, TEXT\n");
1015 break;
1016 case XML_CDATA_SECTION_NODE:
1017 fprintf(output, "Error, CDATA_SECTION\n");
1018 break;
1019 case XML_ENTITY_REF_NODE:
1020 fprintf(output, "Error, ENTITY_REF\n");
1021 break;
1022 case XML_ENTITY_NODE:
1023 fprintf(output, "Error, ENTITY\n");
1024 break;
1025 case XML_PI_NODE:
1026 fprintf(output, "Error, PI\n");
1027 break;
1028 case XML_COMMENT_NODE:
1029 fprintf(output, "Error, COMMENT\n");
1030 break;
1031 case XML_DOCUMENT_NODE:
1032 fprintf(output, "DOCUMENT\n");
1033 break;
1034 case XML_HTML_DOCUMENT_NODE:
1035 fprintf(output, "HTML DOCUMENT\n");
1036 break;
1037 case XML_DOCUMENT_TYPE_NODE:
1038 fprintf(output, "Error, DOCUMENT_TYPE\n");
1039 break;
1040 case XML_DOCUMENT_FRAG_NODE:
1041 fprintf(output, "Error, DOCUMENT_FRAG\n");
1042 break;
1043 case XML_NOTATION_NODE:
1044 fprintf(output, "Error, NOTATION\n");
1045 break;
1046 default:
1047 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +00001048 }
1049 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001050 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1051 doc->intSubset->entities;
1052
1053 fprintf(output, "Entities in internal 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 internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001058 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001059 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1060 doc->extSubset->entities;
1061
1062 fprintf(output, "Entities in external subset\n");
1063 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1064 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001065 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001066 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001067}
1068
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001069/**
1070 * xmlLsCountNode:
1071 * @node: the node to count
1072 *
1073 * Count the children of @node.
1074 *
1075 * Returns the number of children of @node.
1076 */
1077int
1078xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001079 int ret = 0;
1080 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001081
1082 if (node == NULL)
1083 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001084
1085 switch (node->type) {
1086 case XML_ELEMENT_NODE:
1087 list = node->children;
1088 break;
1089 case XML_DOCUMENT_NODE:
1090 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001091#ifdef LIBXML_DOCB_ENABLED
1092 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001093#endif
1094 list = ((xmlDocPtr) node)->children;
1095 break;
1096 case XML_ATTRIBUTE_NODE:
1097 list = ((xmlAttrPtr) node)->children;
1098 break;
1099 case XML_TEXT_NODE:
1100 case XML_CDATA_SECTION_NODE:
1101 case XML_PI_NODE:
1102 case XML_COMMENT_NODE:
1103 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001104 ret = xmlStrlen(node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001105 }
1106 break;
1107 case XML_ENTITY_REF_NODE:
1108 case XML_DOCUMENT_TYPE_NODE:
1109 case XML_ENTITY_NODE:
1110 case XML_DOCUMENT_FRAG_NODE:
1111 case XML_NOTATION_NODE:
1112 case XML_DTD_NODE:
1113 case XML_ELEMENT_DECL:
1114 case XML_ATTRIBUTE_DECL:
1115 case XML_ENTITY_DECL:
1116 case XML_NAMESPACE_DECL:
1117 case XML_XINCLUDE_START:
1118 case XML_XINCLUDE_END:
1119 ret = 1;
1120 break;
1121 }
1122 for (;list != NULL;ret++)
1123 list = list->next;
1124 return(ret);
1125}
1126
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001127/**
1128 * xmlLsOneNode:
1129 * @output: the FILE * for the output
1130 * @node: the node to dump
1131 *
1132 * Dump to @output the type and name of @node.
1133 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001134void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001135xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001136 if (node == NULL) {
1137 fprintf(output, "NULL\n");
1138 return;
1139 }
Owen Taylor3473f882001-02-23 17:55:21 +00001140 switch (node->type) {
1141 case XML_ELEMENT_NODE:
1142 fprintf(output, "-");
1143 break;
1144 case XML_ATTRIBUTE_NODE:
1145 fprintf(output, "a");
1146 break;
1147 case XML_TEXT_NODE:
1148 fprintf(output, "t");
1149 break;
1150 case XML_CDATA_SECTION_NODE:
Daniel Veillard75be0132002-03-13 10:03:35 +00001151 fprintf(output, "C");
Owen Taylor3473f882001-02-23 17:55:21 +00001152 break;
1153 case XML_ENTITY_REF_NODE:
1154 fprintf(output, "e");
1155 break;
1156 case XML_ENTITY_NODE:
1157 fprintf(output, "E");
1158 break;
1159 case XML_PI_NODE:
1160 fprintf(output, "p");
1161 break;
1162 case XML_COMMENT_NODE:
1163 fprintf(output, "c");
1164 break;
1165 case XML_DOCUMENT_NODE:
1166 fprintf(output, "d");
1167 break;
1168 case XML_HTML_DOCUMENT_NODE:
1169 fprintf(output, "h");
1170 break;
1171 case XML_DOCUMENT_TYPE_NODE:
1172 fprintf(output, "T");
1173 break;
1174 case XML_DOCUMENT_FRAG_NODE:
1175 fprintf(output, "F");
1176 break;
1177 case XML_NOTATION_NODE:
1178 fprintf(output, "N");
1179 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001180 case XML_NAMESPACE_DECL:
1181 fprintf(output, "n");
1182 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001183 default:
1184 fprintf(output, "?");
1185 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001186 if (node->type != XML_NAMESPACE_DECL) {
1187 if (node->properties != NULL)
1188 fprintf(output, "a");
1189 else
1190 fprintf(output, "-");
1191 if (node->nsDef != NULL)
1192 fprintf(output, "n");
1193 else
1194 fprintf(output, "-");
1195 }
Owen Taylor3473f882001-02-23 17:55:21 +00001196
1197 fprintf(output, " %8d ", xmlLsCountNode(node));
1198
1199 switch (node->type) {
1200 case XML_ELEMENT_NODE:
1201 if (node->name != NULL)
1202 fprintf(output, "%s", node->name);
1203 break;
1204 case XML_ATTRIBUTE_NODE:
1205 if (node->name != NULL)
1206 fprintf(output, "%s", node->name);
1207 break;
1208 case XML_TEXT_NODE:
1209 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001210 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001211 }
1212 break;
1213 case XML_CDATA_SECTION_NODE:
1214 break;
1215 case XML_ENTITY_REF_NODE:
1216 if (node->name != NULL)
1217 fprintf(output, "%s", node->name);
1218 break;
1219 case XML_ENTITY_NODE:
1220 if (node->name != NULL)
1221 fprintf(output, "%s", node->name);
1222 break;
1223 case XML_PI_NODE:
1224 if (node->name != NULL)
1225 fprintf(output, "%s", node->name);
1226 break;
1227 case XML_COMMENT_NODE:
1228 break;
1229 case XML_DOCUMENT_NODE:
1230 break;
1231 case XML_HTML_DOCUMENT_NODE:
1232 break;
1233 case XML_DOCUMENT_TYPE_NODE:
1234 break;
1235 case XML_DOCUMENT_FRAG_NODE:
1236 break;
1237 case XML_NOTATION_NODE:
1238 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001239 case XML_NAMESPACE_DECL: {
1240 xmlNsPtr ns = (xmlNsPtr) node;
1241
1242 if (ns->prefix == NULL)
1243 fprintf(output, "default -> %s", ns->href);
1244 else
1245 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1246 break;
1247 }
Owen Taylor3473f882001-02-23 17:55:21 +00001248 default:
1249 if (node->name != NULL)
1250 fprintf(output, "%s", node->name);
1251 }
1252 fprintf(output, "\n");
1253}
1254
Daniel Veillard78d12092001-10-11 09:12:24 +00001255/**
1256 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001257 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001258 *
1259 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001260 *
1261 * Returns a pointer to either "True" or "False"
1262 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001263const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001264xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001265{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001266 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001267 return("True");
1268 else
1269 return("False");
1270}
1271
Owen Taylor3473f882001-02-23 17:55:21 +00001272/****************************************************************
1273 * *
1274 * The XML shell related functions *
1275 * *
1276 ****************************************************************/
1277
Daniel Veillard78d12092001-10-11 09:12:24 +00001278
1279
Owen Taylor3473f882001-02-23 17:55:21 +00001280/*
1281 * TODO: Improvement/cleanups for the XML shell
1282 * - allow to shell out an editor on a subpart
1283 * - cleanup function registrations (with help) and calling
1284 * - provide registration routines
1285 */
1286
1287/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001288 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001289 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001290 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001291 *
1292 * Print the xpath error to libxml default error channel
1293 */
1294void
1295xmlShellPrintXPathError(int errorType, const char *arg)
1296{
1297 const char *default_arg = "Result";
1298
1299 if (!arg)
1300 arg = default_arg;
1301
1302 switch (errorType) {
1303 case XPATH_UNDEFINED:
1304 xmlGenericError(xmlGenericErrorContext,
1305 "%s: no such node\n", arg);
1306 break;
1307
1308 case XPATH_BOOLEAN:
1309 xmlGenericError(xmlGenericErrorContext,
1310 "%s is a Boolean\n", arg);
1311 break;
1312 case XPATH_NUMBER:
1313 xmlGenericError(xmlGenericErrorContext,
1314 "%s is a number\n", arg);
1315 break;
1316 case XPATH_STRING:
1317 xmlGenericError(xmlGenericErrorContext,
1318 "%s is a string\n", arg);
1319 break;
1320 case XPATH_POINT:
1321 xmlGenericError(xmlGenericErrorContext,
1322 "%s is a point\n", arg);
1323 break;
1324 case XPATH_RANGE:
1325 xmlGenericError(xmlGenericErrorContext,
1326 "%s is a range\n", arg);
1327 break;
1328 case XPATH_LOCATIONSET:
1329 xmlGenericError(xmlGenericErrorContext,
1330 "%s is a range\n", arg);
1331 break;
1332 case XPATH_USERS:
1333 xmlGenericError(xmlGenericErrorContext,
1334 "%s is user-defined\n", arg);
1335 break;
1336 case XPATH_XSLT_TREE:
1337 xmlGenericError(xmlGenericErrorContext,
1338 "%s is an XSLT value tree\n", arg);
1339 break;
1340 }
1341 xmlGenericError(xmlGenericErrorContext,
1342 "Try casting the result string function (xpath builtin)\n",
1343 arg);
1344}
1345
1346
1347/**
1348 * xmlShellPrintNode:
1349 * @node : a non-null node to print to stdout
1350 *
1351 * Print node to stdout
1352 */
1353void
1354xmlShellPrintNode(xmlNodePtr node)
1355{
1356 if (!node)
1357 return;
1358
1359 if (node->type == XML_DOCUMENT_NODE)
1360 xmlDocDump(stdout, (xmlDocPtr) node);
1361 else if (node->type == XML_ATTRIBUTE_NODE)
1362 xmlDebugDumpAttrList(stdout, (xmlAttrPtr) node, 0);
1363 else
1364 xmlElemDump(stdout, node->doc, node);
1365
1366 fprintf(stdout, "\n");
1367}
1368
1369
1370/**
1371 * xmlShellPrintXPathResult:
Daniel Veillard9d06d302002-01-22 18:15:52 +00001372 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001373 *
1374 * Prints result to stdout
1375 */
1376void
1377xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1378{
1379 int i = 0;
1380
1381 if (list != NULL) {
1382 switch (list->type) {
1383 case XPATH_NODESET:{
1384 int indx;
1385
1386 if (list->nodesetval) {
1387 for (indx = 0; indx < list->nodesetval->nodeNr;
1388 indx++) {
1389 if (i > 0)
1390 fprintf(stderr, " -------\n");
1391 xmlShellPrintNode(list->nodesetval->
1392 nodeTab[indx]);
1393 }
1394 } else {
1395 xmlGenericError(xmlGenericErrorContext,
1396 "Empty node set\n");
1397 }
1398 break;
1399 }
1400 case XPATH_BOOLEAN:
1401 xmlGenericError(xmlGenericErrorContext,
1402 "Is a Boolean:%s\n",
1403 xmlBoolToText(list->boolval));
1404 break;
1405 case XPATH_NUMBER:
1406 xmlGenericError(xmlGenericErrorContext,
1407 "Is a number:%0g\n", list->floatval);
1408 break;
1409 case XPATH_STRING:
1410 xmlGenericError(xmlGenericErrorContext,
1411 "Is a string:%s\n", list->stringval);
1412 break;
1413
1414 default:
1415 xmlShellPrintXPathError(list->type, NULL);
1416 }
1417 }
1418}
1419
1420/**
Owen Taylor3473f882001-02-23 17:55:21 +00001421 * xmlShellList:
1422 * @ctxt: the shell context
1423 * @arg: unused
1424 * @node: a node
1425 * @node2: unused
1426 *
1427 * Implements the XML shell function "ls"
1428 * Does an Unix like listing of the given node (like a directory)
1429 *
1430 * Returns 0
1431 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001432int
1433xmlShellList(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1434 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1435 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1436{
Owen Taylor3473f882001-02-23 17:55:21 +00001437 xmlNodePtr cur;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001438 if (node == NULL) {
1439 fprintf(stdout, "NULL\n");
1440 return (0);
1441 }
Owen Taylor3473f882001-02-23 17:55:21 +00001442 if ((node->type == XML_DOCUMENT_NODE) ||
1443 (node->type == XML_HTML_DOCUMENT_NODE)) {
1444 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001445 } else if (node->type == XML_NAMESPACE_DECL) {
1446 xmlLsOneNode(stdout, node);
1447 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001448 } else if (node->children != NULL) {
1449 cur = node->children;
1450 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001451 xmlLsOneNode(stdout, node);
1452 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001453 }
1454 while (cur != NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001455 xmlLsOneNode(stdout, cur);
1456 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001457 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001458 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001459}
1460
1461/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001462 * xmlShellBase:
1463 * @ctxt: the shell context
1464 * @arg: unused
1465 * @node: a node
1466 * @node2: unused
1467 *
1468 * Implements the XML shell function "base"
1469 * dumps the current XML base of the node
1470 *
1471 * Returns 0
1472 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001473int
1474xmlShellBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1475 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1476 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1477{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001478 xmlChar *base;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001479 if (node == NULL) {
1480 fprintf(stdout, "NULL\n");
1481 return (0);
1482 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001483
1484 base = xmlNodeGetBase(node->doc, node);
1485
1486 if (base == NULL) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001487 fprintf(stdout, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001488 } else {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001489 fprintf(stdout, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001490 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001491 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001492 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001493}
1494
1495/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001496 * xmlShellSetBase:
1497 * @ctxt: the shell context
1498 * @arg: the new base
1499 * @node: a node
1500 * @node2: unused
1501 *
1502 * Implements the XML shell function "setbase"
1503 * change the current XML base of the node
1504 *
1505 * Returns 0
1506 */
1507static int
1508xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1509 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1510 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1511{
1512 xmlNodeSetBase(node, (xmlChar*) arg);
1513 return (0);
1514}
1515
1516/**
Owen Taylor3473f882001-02-23 17:55:21 +00001517 * xmlShellDir:
1518 * @ctxt: the shell context
1519 * @arg: unused
1520 * @node: a node
1521 * @node2: unused
1522 *
1523 * Implements the XML shell function "dir"
1524 * dumps informations about the node (namespace, attributes, content).
1525 *
1526 * Returns 0
1527 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001528int
1529xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1530 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1531 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1532{
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001533 if (node == NULL) {
1534 fprintf(stdout, "NULL\n");
1535 return (0);
1536 }
Owen Taylor3473f882001-02-23 17:55:21 +00001537 if ((node->type == XML_DOCUMENT_NODE) ||
1538 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001539 xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001540 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001541 xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001542 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001543 xmlDebugDumpOneNode(stdout, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001544 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001545 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001546}
1547
1548/**
1549 * xmlShellCat:
1550 * @ctxt: the shell context
1551 * @arg: unused
1552 * @node: a node
1553 * @node2: unused
1554 *
1555 * Implements the XML shell function "cat"
1556 * dumps the serialization node content (XML or HTML).
1557 *
1558 * Returns 0
1559 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001560int
1561xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1562 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1563{
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001564 if (node == NULL) {
1565 fprintf(stdout, "NULL\n");
1566 return (0);
1567 }
Owen Taylor3473f882001-02-23 17:55:21 +00001568 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1569#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001570 if (node->type == XML_HTML_DOCUMENT_NODE)
1571 htmlDocDump(stdout, (htmlDocPtr) node);
1572 else
1573 htmlNodeDumpFile(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001574#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001575 if (node->type == XML_DOCUMENT_NODE)
1576 xmlDocDump(stdout, (xmlDocPtr) node);
1577 else
1578 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001579#endif /* LIBXML_HTML_ENABLED */
1580 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001581 if (node->type == XML_DOCUMENT_NODE)
1582 xmlDocDump(stdout, (xmlDocPtr) node);
1583 else
1584 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001585 }
Daniel Veillardcd337f02001-11-22 18:20:37 +00001586 fprintf(stdout, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001587 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001588}
1589
1590/**
1591 * xmlShellLoad:
1592 * @ctxt: the shell context
1593 * @filename: the file name
1594 * @node: unused
1595 * @node2: unused
1596 *
1597 * Implements the XML shell function "load"
1598 * loads a new document specified by the filename
1599 *
1600 * Returns 0 or -1 if loading failed
1601 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001602int
1603xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1604 xmlNodePtr node ATTRIBUTE_UNUSED,
1605 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1606{
Owen Taylor3473f882001-02-23 17:55:21 +00001607 xmlDocPtr doc;
1608 int html = 0;
1609
1610 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001611 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001612
1613 if (html) {
1614#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001615 doc = htmlParseFile(filename, NULL);
1616#else
Daniel Veillardcd337f02001-11-22 18:20:37 +00001617 fprintf(stdout, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001618 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001619#endif /* LIBXML_HTML_ENABLED */
1620 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001621 doc = xmlParseFile(filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001622 }
1623 if (doc != NULL) {
1624 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001625 xmlFreeDoc(ctxt->doc);
1626 }
1627 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001628#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001629 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001630#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001631 xmlFree(ctxt->filename);
1632 ctxt->doc = doc;
1633 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001634#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001635 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001636#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001637 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001638 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001639 return (-1);
1640 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001641}
1642
1643/**
1644 * xmlShellWrite:
1645 * @ctxt: the shell context
1646 * @filename: the file name
1647 * @node: a node in the tree
1648 * @node2: unused
1649 *
1650 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001651 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001652 * of the subtree under the @node specified
1653 *
1654 * Returns 0 or -1 in case of error
1655 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001656int
Owen Taylor3473f882001-02-23 17:55:21 +00001657xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001658 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1659{
Owen Taylor3473f882001-02-23 17:55:21 +00001660 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001661 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001662 if ((filename == NULL) || (filename[0] == 0)) {
1663 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001664 "Write command requires a filename argument\n");
1665 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001666 }
1667#ifdef W_OK
1668 if (access((char *) filename, W_OK)) {
1669 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001670 "Cannot write to %s\n", filename);
1671 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001672 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001673#endif
1674 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001675 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001676 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1677 xmlGenericError(xmlGenericErrorContext,
1678 "Failed to write to %s\n", filename);
1679 return (-1);
1680 }
1681 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001682 case XML_HTML_DOCUMENT_NODE:
1683#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001684 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1685 xmlGenericError(xmlGenericErrorContext,
1686 "Failed to write to %s\n", filename);
1687 return (-1);
1688 }
Owen Taylor3473f882001-02-23 17:55:21 +00001689#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001690 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1691 xmlGenericError(xmlGenericErrorContext,
1692 "Failed to write to %s\n", filename);
1693 return (-1);
1694 }
Owen Taylor3473f882001-02-23 17:55:21 +00001695#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001696 break;
1697 default:{
1698 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001699
Daniel Veillard78d12092001-10-11 09:12:24 +00001700 f = fopen((char *) filename, "w");
1701 if (f == NULL) {
1702 xmlGenericError(xmlGenericErrorContext,
1703 "Failed to write to %s\n", filename);
1704 return (-1);
1705 }
1706 xmlElemDump(f, ctxt->doc, node);
1707 fclose(f);
1708 }
Owen Taylor3473f882001-02-23 17:55:21 +00001709 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001710 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001711}
1712
1713/**
1714 * xmlShellSave:
1715 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001716 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001717 * @node: unused
1718 * @node2: unused
1719 *
1720 * Implements the XML shell function "save"
1721 * Write the current document to the filename, or it's original name
1722 *
1723 * Returns 0 or -1 in case of error
1724 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001725int
1726xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1727 xmlNodePtr node ATTRIBUTE_UNUSED,
1728 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1729{
Owen Taylor3473f882001-02-23 17:55:21 +00001730 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001731 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001732 if ((filename == NULL) || (filename[0] == 0))
1733 filename = ctxt->filename;
1734#ifdef W_OK
1735 if (access((char *) filename, W_OK)) {
1736 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001737 "Cannot save to %s\n", filename);
1738 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001739 }
1740#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001741 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001742 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001743 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1744 xmlGenericError(xmlGenericErrorContext,
1745 "Failed to save to %s\n", filename);
1746 }
1747 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001748 case XML_HTML_DOCUMENT_NODE:
1749#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001750 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1751 xmlGenericError(xmlGenericErrorContext,
1752 "Failed to save to %s\n", filename);
1753 }
Owen Taylor3473f882001-02-23 17:55:21 +00001754#else
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 }
Owen Taylor3473f882001-02-23 17:55:21 +00001759#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001760 break;
1761 default:
1762 xmlGenericError(xmlGenericErrorContext,
1763 "To save to subparts of a document use the 'write' command\n");
1764 return (-1);
1765
Owen Taylor3473f882001-02-23 17:55:21 +00001766 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001767 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001768}
1769
1770/**
1771 * xmlShellValidate:
1772 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001773 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001774 * @node: unused
1775 * @node2: unused
1776 *
1777 * Implements the XML shell function "validate"
1778 * Validate the document, if a DTD path is provided, then the validation
1779 * is done against the given DTD.
1780 *
1781 * Returns 0 or -1 in case of error
1782 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001783int
1784xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1785 xmlNodePtr node ATTRIBUTE_UNUSED,
1786 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1787{
Owen Taylor3473f882001-02-23 17:55:21 +00001788 xmlValidCtxt vctxt;
1789 int res = -1;
1790
1791 vctxt.userData = stderr;
1792 vctxt.error = (xmlValidityErrorFunc) fprintf;
1793 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1794
1795 if ((dtd == NULL) || (dtd[0] == 0)) {
1796 res = xmlValidateDocument(&vctxt, ctxt->doc);
1797 } else {
1798 xmlDtdPtr subset;
1799
Daniel Veillard78d12092001-10-11 09:12:24 +00001800 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1801 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001802 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1803
Daniel Veillard78d12092001-10-11 09:12:24 +00001804 xmlFreeDtd(subset);
1805 }
Owen Taylor3473f882001-02-23 17:55:21 +00001806 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001807 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00001808}
1809
1810/**
1811 * xmlShellDu:
1812 * @ctxt: the shell context
1813 * @arg: unused
1814 * @tree: a node defining a subtree
1815 * @node2: unused
1816 *
1817 * Implements the XML shell function "du"
1818 * show the structure of the subtree under node @tree
1819 * If @tree is null, the command works on the current node.
1820 *
1821 * Returns 0 or -1 in case of error
1822 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001823int
1824xmlShellDu(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1825 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1826 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1827{
Owen Taylor3473f882001-02-23 17:55:21 +00001828 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00001829 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00001830
Daniel Veillard78d12092001-10-11 09:12:24 +00001831 if (tree == NULL)
1832 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001833 node = tree;
1834 while (node != NULL) {
1835 if ((node->type == XML_DOCUMENT_NODE) ||
1836 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001837 fprintf(stdout, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001838 } else if (node->type == XML_ELEMENT_NODE) {
1839 for (i = 0; i < indent; i++)
Daniel Veillardcd337f02001-11-22 18:20:37 +00001840 fprintf(stdout, " ");
1841 fprintf(stdout, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00001842 } else {
1843 }
Owen Taylor3473f882001-02-23 17:55:21 +00001844
Daniel Veillard78d12092001-10-11 09:12:24 +00001845 /*
1846 * Browse the full subtree, deep first
1847 */
Owen Taylor3473f882001-02-23 17:55:21 +00001848
1849 if ((node->type == XML_DOCUMENT_NODE) ||
1850 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001851 node = ((xmlDocPtr) node)->children;
1852 } else if ((node->children != NULL)
1853 && (node->type != XML_ENTITY_REF_NODE)) {
1854 /* deep first */
1855 node = node->children;
1856 indent++;
1857 } else if ((node != tree) && (node->next != NULL)) {
1858 /* then siblings */
1859 node = node->next;
1860 } else if (node != tree) {
1861 /* go up to parents->next if needed */
1862 while (node != tree) {
1863 if (node->parent != NULL) {
1864 node = node->parent;
1865 indent--;
1866 }
1867 if ((node != tree) && (node->next != NULL)) {
1868 node = node->next;
1869 break;
1870 }
1871 if (node->parent == NULL) {
1872 node = NULL;
1873 break;
1874 }
1875 if (node == tree) {
1876 node = NULL;
1877 break;
1878 }
1879 }
1880 /* exit condition */
1881 if (node == tree)
1882 node = NULL;
1883 } else
1884 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001885 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001886 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001887}
1888
1889/**
1890 * xmlShellPwd:
1891 * @ctxt: the shell context
1892 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00001893 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00001894 * @node2: unused
1895 *
1896 * Implements the XML shell function "pwd"
1897 * Show the full path from the root to the node, if needed building
1898 * thumblers when similar elements exists at a given ancestor level.
1899 * The output is compatible with XPath commands.
1900 *
1901 * Returns 0 or -1 in case of error
1902 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001903int
1904xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
1905 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1906{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001907 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00001908
Daniel Veillard78d12092001-10-11 09:12:24 +00001909 if (node == NULL)
1910 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001911
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001912 path = xmlGetNodePath(node);
1913 if (path == NULL)
1914 return (-1);
1915
1916 /*
1917 * This test prevents buffer overflow, because this routine
1918 * is only called by xmlShell, in which the second argument is
1919 * 500 chars long.
1920 * It is a dirty hack before a cleaner solution is found.
1921 * Documentation should mention that the second argument must
1922 * be at least 500 chars long, and could be stripped if too long.
1923 */
1924 snprintf(buffer, 499, "%s", path);
1925 buffer[499] = '0';
1926 xmlFree(path);
1927
Daniel Veillard78d12092001-10-11 09:12:24 +00001928 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001929}
1930
1931/**
1932 * xmlShell
1933 * @doc: the initial document
1934 * @filename: the output buffer
1935 * @input: the line reading function
1936 * @output: the output FILE*
1937 *
1938 * Implements the XML shell
1939 * This allow to load, validate, view, modify and save a document
1940 * using a environment similar to a UNIX commandline.
1941 */
1942void
1943xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00001944 FILE * output)
1945{
Owen Taylor3473f882001-02-23 17:55:21 +00001946 char prompt[500] = "/ > ";
1947 char *cmdline = NULL, *cur;
1948 int nbargs;
1949 char command[100];
1950 char arg[400];
1951 int i;
1952 xmlShellCtxtPtr ctxt;
1953 xmlXPathObjectPtr list;
1954
1955 if (doc == NULL)
1956 return;
1957 if (filename == NULL)
1958 return;
1959 if (input == NULL)
1960 return;
1961 if (output == NULL)
1962 return;
1963 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00001964 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00001965 return;
1966 ctxt->loaded = 0;
1967 ctxt->doc = doc;
1968 ctxt->input = input;
1969 ctxt->output = output;
1970 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00001971 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001972
1973#ifdef LIBXML_XPATH_ENABLED
1974 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1975 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001976 xmlFree(ctxt);
1977 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001978 }
1979#endif /* LIBXML_XPATH_ENABLED */
1980 while (1) {
1981 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Daniel Veillard78d12092001-10-11 09:12:24 +00001982 sprintf(prompt, "%s > ", "/");
1983 else if (ctxt->node->name)
1984 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001985 else
Daniel Veillard78d12092001-10-11 09:12:24 +00001986 sprintf(prompt, "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00001987 prompt[sizeof(prompt) - 1] = 0;
1988
Daniel Veillard78d12092001-10-11 09:12:24 +00001989 /*
1990 * Get a new command line
1991 */
Owen Taylor3473f882001-02-23 17:55:21 +00001992 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00001993 if (cmdline == NULL)
1994 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001995
Daniel Veillard78d12092001-10-11 09:12:24 +00001996 /*
1997 * Parse the command itself
1998 */
1999 cur = cmdline;
2000 nbargs = 0;
2001 while ((*cur == ' ') || (*cur == '\t'))
2002 cur++;
2003 i = 0;
2004 while ((*cur != ' ') && (*cur != '\t') &&
2005 (*cur != '\n') && (*cur != '\r')) {
2006 if (*cur == 0)
2007 break;
2008 command[i++] = *cur++;
2009 }
2010 command[i] = 0;
2011 if (i == 0)
2012 continue;
2013 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002014
Daniel Veillard78d12092001-10-11 09:12:24 +00002015 /*
2016 * Parse the argument
2017 */
2018 while ((*cur == ' ') || (*cur == '\t'))
2019 cur++;
2020 i = 0;
2021 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2022 if (*cur == 0)
2023 break;
2024 arg[i++] = *cur++;
2025 }
2026 arg[i] = 0;
2027 if (i != 0)
2028 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002029
Daniel Veillard78d12092001-10-11 09:12:24 +00002030 /*
2031 * start interpreting the command
2032 */
Owen Taylor3473f882001-02-23 17:55:21 +00002033 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002034 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002035 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002036 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002037 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002038 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002039 if (!strcmp(command, "help")) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00002040 fprintf(stdout, "\tbase display XML base of the node\n");
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002041 fprintf(stdout, "\tsetbase URI change the XML base of the node\n");
Daniel Veillardcd337f02001-11-22 18:20:37 +00002042 fprintf(stdout, "\tbye leave shell\n");
2043 fprintf(stdout, "\tcat [node] display node or current node\n");
2044 fprintf(stdout, "\tcd [path] change directory to path or to root\n");
2045 fprintf(stdout, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2046 fprintf(stdout, "\tdu [path] show the structure of the subtree under path or the current node\n");
2047 fprintf(stdout, "\texit leave shell\n");
2048 fprintf(stdout, "\thelp display this help\n");
2049 fprintf(stdout, "\tfree display memory usage\n");
2050 fprintf(stdout, "\tload [name] load a new document with name\n");
2051 fprintf(stdout, "\tls [path] list contents of path or the current directory\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002052#ifdef LIBXML_XPATH_ENABLED
2053 fprintf(stdout, "\txpath expr evaluate the XPath expression in that context and print the result\n");
2054#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcd337f02001-11-22 18:20:37 +00002055 fprintf(stdout, "\tpwd display current working directory\n");
2056 fprintf(stdout, "\tquit leave shell\n");
2057 fprintf(stdout, "\tsave [name] save this document to name or the original name\n");
2058 fprintf(stdout, "\tvalidate check the document for errors\n");
2059 fprintf(stdout, "\twrite [name] write the current node to the filename\n");
Daniel Veillard5004f422001-11-08 13:53:05 +00002060 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002061 xmlShellValidate(ctxt, arg, NULL, NULL);
2062 } else if (!strcmp(command, "load")) {
2063 xmlShellLoad(ctxt, arg, NULL, NULL);
2064 } else if (!strcmp(command, "save")) {
2065 xmlShellSave(ctxt, arg, NULL, NULL);
2066 } else if (!strcmp(command, "write")) {
2067 xmlShellWrite(ctxt, arg, NULL, NULL);
2068 } else if (!strcmp(command, "free")) {
2069 if (arg[0] == 0) {
2070 xmlMemShow(stdout, 0);
2071 } else {
2072 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002073
Daniel Veillard78d12092001-10-11 09:12:24 +00002074 sscanf(arg, "%d", &len);
2075 xmlMemShow(stdout, len);
2076 }
2077 } else if (!strcmp(command, "pwd")) {
2078 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002079
Daniel Veillard78d12092001-10-11 09:12:24 +00002080 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillardcd337f02001-11-22 18:20:37 +00002081 fprintf(stdout, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002082 } else if (!strcmp(command, "du")) {
2083 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2084 } else if (!strcmp(command, "base")) {
2085 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002086#ifdef LIBXML_XPATH_ENABLED
2087 } else if (!strcmp(command, "xpath")) {
2088 if (arg[0] == 0) {
2089 xmlGenericError(xmlGenericErrorContext,
2090 "xpath: expression required\n");
2091 } else {
2092 ctxt->pctxt->node = ctxt->node;
2093 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2094 xmlXPathDebugDumpObject(stdout, list, 0);
2095 xmlXPathFreeObject(list);
2096 }
2097#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002098 } else if (!strcmp(command, "setbase")) {
2099 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002100 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2101 int dir = (!strcmp(command, "dir"));
2102
2103 if (arg[0] == 0) {
2104 if (dir)
2105 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2106 else
2107 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2108 } else {
2109 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002110#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002111 ctxt->pctxt->node = ctxt->node;
2112 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2113#else
2114 list = NULL;
2115#endif /* LIBXML_XPATH_ENABLED */
2116 if (list != NULL) {
2117 switch (list->type) {
2118 case XPATH_UNDEFINED:
2119 xmlGenericError(xmlGenericErrorContext,
2120 "%s: no such node\n", arg);
2121 break;
2122 case XPATH_NODESET:{
2123 int indx;
2124
Daniel Veillarda6825e82001-11-07 13:33:59 +00002125 if (list->nodesetval == NULL)
2126 break;
2127
Daniel Veillard78d12092001-10-11 09:12:24 +00002128 for (indx = 0;
2129 indx < list->nodesetval->nodeNr;
2130 indx++) {
2131 if (dir)
2132 xmlShellDir(ctxt, NULL,
2133 list->nodesetval->
2134 nodeTab[indx], NULL);
2135 else
2136 xmlShellList(ctxt, NULL,
2137 list->nodesetval->
2138 nodeTab[indx], NULL);
2139 }
2140 break;
2141 }
2142 case XPATH_BOOLEAN:
2143 xmlGenericError(xmlGenericErrorContext,
2144 "%s is a Boolean\n", arg);
2145 break;
2146 case XPATH_NUMBER:
2147 xmlGenericError(xmlGenericErrorContext,
2148 "%s is a number\n", arg);
2149 break;
2150 case XPATH_STRING:
2151 xmlGenericError(xmlGenericErrorContext,
2152 "%s is a string\n", arg);
2153 break;
2154 case XPATH_POINT:
2155 xmlGenericError(xmlGenericErrorContext,
2156 "%s is a point\n", arg);
2157 break;
2158 case XPATH_RANGE:
2159 xmlGenericError(xmlGenericErrorContext,
2160 "%s is a range\n", arg);
2161 break;
2162 case XPATH_LOCATIONSET:
2163 xmlGenericError(xmlGenericErrorContext,
2164 "%s is a range\n", arg);
2165 break;
2166 case XPATH_USERS:
2167 xmlGenericError(xmlGenericErrorContext,
2168 "%s is user-defined\n", arg);
2169 break;
2170 case XPATH_XSLT_TREE:
2171 xmlGenericError(xmlGenericErrorContext,
2172 "%s is an XSLT value tree\n",
2173 arg);
2174 break;
2175 }
2176#ifdef LIBXML_XPATH_ENABLED
2177 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002178#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002179 } else {
2180 xmlGenericError(xmlGenericErrorContext,
2181 "%s: no such node\n", arg);
2182 }
2183 ctxt->pctxt->node = NULL;
2184 }
2185 } else if (!strcmp(command, "cd")) {
2186 if (arg[0] == 0) {
2187 ctxt->node = (xmlNodePtr) ctxt->doc;
2188 } else {
2189#ifdef LIBXML_XPATH_ENABLED
2190 ctxt->pctxt->node = ctxt->node;
2191 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2192#else
2193 list = NULL;
2194#endif /* LIBXML_XPATH_ENABLED */
2195 if (list != NULL) {
2196 switch (list->type) {
2197 case XPATH_UNDEFINED:
2198 xmlGenericError(xmlGenericErrorContext,
2199 "%s: no such node\n", arg);
2200 break;
2201 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002202 if (list->nodesetval != NULL) {
2203 if (list->nodesetval->nodeNr == 1) {
2204 ctxt->node = list->nodesetval->nodeTab[0];
2205 } else
2206 xmlGenericError(xmlGenericErrorContext,
2207 "%s is a %d Node Set\n",
2208 arg,
2209 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002210 } else
2211 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002212 "%s is an empty Node Set\n",
2213 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002214 break;
2215 case XPATH_BOOLEAN:
2216 xmlGenericError(xmlGenericErrorContext,
2217 "%s is a Boolean\n", arg);
2218 break;
2219 case XPATH_NUMBER:
2220 xmlGenericError(xmlGenericErrorContext,
2221 "%s is a number\n", arg);
2222 break;
2223 case XPATH_STRING:
2224 xmlGenericError(xmlGenericErrorContext,
2225 "%s is a string\n", arg);
2226 break;
2227 case XPATH_POINT:
2228 xmlGenericError(xmlGenericErrorContext,
2229 "%s is a point\n", arg);
2230 break;
2231 case XPATH_RANGE:
2232 xmlGenericError(xmlGenericErrorContext,
2233 "%s is a range\n", arg);
2234 break;
2235 case XPATH_LOCATIONSET:
2236 xmlGenericError(xmlGenericErrorContext,
2237 "%s is a range\n", arg);
2238 break;
2239 case XPATH_USERS:
2240 xmlGenericError(xmlGenericErrorContext,
2241 "%s is user-defined\n", arg);
2242 break;
2243 case XPATH_XSLT_TREE:
2244 xmlGenericError(xmlGenericErrorContext,
2245 "%s is an XSLT value tree\n",
2246 arg);
2247 break;
2248 }
2249#ifdef LIBXML_XPATH_ENABLED
2250 xmlXPathFreeObject(list);
2251#endif
2252 } else {
2253 xmlGenericError(xmlGenericErrorContext,
2254 "%s: no such node\n", arg);
2255 }
2256 ctxt->pctxt->node = NULL;
2257 }
2258 } else if (!strcmp(command, "cat")) {
2259 if (arg[0] == 0) {
2260 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2261 } else {
2262 ctxt->pctxt->node = ctxt->node;
2263#ifdef LIBXML_XPATH_ENABLED
2264 ctxt->pctxt->node = ctxt->node;
2265 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2266#else
2267 list = NULL;
2268#endif /* LIBXML_XPATH_ENABLED */
2269 if (list != NULL) {
2270 switch (list->type) {
2271 case XPATH_UNDEFINED:
2272 xmlGenericError(xmlGenericErrorContext,
2273 "%s: no such node\n", arg);
2274 break;
2275 case XPATH_NODESET:{
2276 int indx;
2277
Daniel Veillarda6825e82001-11-07 13:33:59 +00002278 if (list->nodesetval == NULL)
2279 break;
2280
Daniel Veillard78d12092001-10-11 09:12:24 +00002281 for (indx = 0;
2282 indx < list->nodesetval->nodeNr;
2283 indx++) {
2284 if (i > 0)
Daniel Veillardcd337f02001-11-22 18:20:37 +00002285 fprintf(stdout, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002286 xmlShellCat(ctxt, NULL,
2287 list->nodesetval->
2288 nodeTab[indx], NULL);
2289 }
2290 break;
2291 }
2292 case XPATH_BOOLEAN:
2293 xmlGenericError(xmlGenericErrorContext,
2294 "%s is a Boolean\n", arg);
2295 break;
2296 case XPATH_NUMBER:
2297 xmlGenericError(xmlGenericErrorContext,
2298 "%s is a number\n", arg);
2299 break;
2300 case XPATH_STRING:
2301 xmlGenericError(xmlGenericErrorContext,
2302 "%s is a string\n", arg);
2303 break;
2304 case XPATH_POINT:
2305 xmlGenericError(xmlGenericErrorContext,
2306 "%s is a point\n", arg);
2307 break;
2308 case XPATH_RANGE:
2309 xmlGenericError(xmlGenericErrorContext,
2310 "%s is a range\n", arg);
2311 break;
2312 case XPATH_LOCATIONSET:
2313 xmlGenericError(xmlGenericErrorContext,
2314 "%s is a range\n", arg);
2315 break;
2316 case XPATH_USERS:
2317 xmlGenericError(xmlGenericErrorContext,
2318 "%s is user-defined\n", arg);
2319 break;
2320 case XPATH_XSLT_TREE:
2321 xmlGenericError(xmlGenericErrorContext,
2322 "%s is an XSLT value tree\n",
2323 arg);
2324 break;
2325 }
2326#ifdef LIBXML_XPATH_ENABLED
2327 xmlXPathFreeObject(list);
2328#endif
2329 } else {
2330 xmlGenericError(xmlGenericErrorContext,
2331 "%s: no such node\n", arg);
2332 }
2333 ctxt->pctxt->node = NULL;
2334 }
2335 } else {
2336 xmlGenericError(xmlGenericErrorContext,
2337 "Unknown command %s\n", command);
2338 }
2339 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002340 }
2341#ifdef LIBXML_XPATH_ENABLED
2342 xmlXPathFreeContext(ctxt->pctxt);
2343#endif /* LIBXML_XPATH_ENABLED */
2344 if (ctxt->loaded) {
2345 xmlFreeDoc(ctxt->doc);
2346 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002347 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002348 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002349 xmlFree(ctxt);
2350 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002351 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002352}
2353
2354#endif /* LIBXML_DEBUG_ENABLED */