blob: 6300455cc999e74226d375b57ae94ddadcba91ed [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * debugXML.c : This is a set of routines used for debugging the tree
3 * produced by the XML parser.
4 *
5 * See Copyright for the status of this software.
6 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00007 * Daniel Veillard <daniel@veillard.com>
Owen Taylor3473f882001-02-23 17:55:21 +00008 */
9
Bjorn Reese70a9da52001-04-21 16:57:29 +000010#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000011#ifdef LIBXML_DEBUG_ENABLED
12
Owen Taylor3473f882001-02-23 17:55:21 +000013#include <string.h>
14#ifdef HAVE_STDLIB_H
15#include <stdlib.h>
16#endif
17#ifdef HAVE_STRING_H
18#include <string.h>
19#endif
20#include <libxml/xmlmemory.h>
21#include <libxml/tree.h>
22#include <libxml/parser.h>
Daniel Veillard567e1b42001-08-01 15:53:47 +000023#include <libxml/parserInternals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000024#include <libxml/valid.h>
25#include <libxml/debugXML.h>
26#include <libxml/HTMLtree.h>
27#include <libxml/HTMLparser.h>
28#include <libxml/xmlerror.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000029#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000030
Daniel Veillard5e2dace2001-07-18 19:30:27 +000031/**
32 * xmlDebugDumpString:
33 * @output: the FILE * for the output
34 * @str: the string
35 *
36 * Dumps informations about the string, shorten it if necessary
37 */
38void
39xmlDebugDumpString(FILE * output, const xmlChar * str)
40{
Owen Taylor3473f882001-02-23 17:55:21 +000041 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000042
Daniel Veillard7db38712002-02-07 16:39:11 +000043 if (output == NULL)
44 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +000045 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000046 fprintf(output, "(NULL)");
47 return;
Owen Taylor3473f882001-02-23 17:55:21 +000048 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000049 for (i = 0; i < 40; i++)
50 if (str[i] == 0)
51 return;
52 else if (IS_BLANK(str[i]))
53 fputc(' ', output);
54 else if (str[i] >= 0x80)
55 fprintf(output, "#%X", str[i]);
56 else
57 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000058 fprintf(output, "...");
59}
60
Daniel Veillard56a4cb82001-03-24 17:00:36 +000061static void
62xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000063 int i;
64 char shift[100];
65
66 for (i = 0;((i < depth) && (i < 25));i++)
67 shift[2 * i] = shift[2 * i + 1] = ' ';
68 shift[2 * i] = shift[2 * i + 1] = 0;
69
70 fprintf(output, shift);
71
Daniel Veillard5e926fa2002-01-22 21:44:25 +000072 if (dtd == NULL) {
73 fprintf(output, "DTD node is NULL\n");
74 return;
75 }
76
Owen Taylor3473f882001-02-23 17:55:21 +000077 if (dtd->type != XML_DTD_NODE) {
78 fprintf(output, "PBM: not a DTD\n");
79 return;
80 }
81 if (dtd->name != NULL)
82 fprintf(output, "DTD(%s)", dtd->name);
83 else
84 fprintf(output, "DTD");
85 if (dtd->ExternalID != NULL)
86 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
87 if (dtd->SystemID != NULL)
88 fprintf(output, ", SYSTEM %s", dtd->SystemID);
89 fprintf(output, "\n");
90 /*
91 * Do a bit of checking
92 */
93 if (dtd->parent == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000094 fprintf(output, "PBM: DTD has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +000095 if (dtd->doc == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000096 fprintf(output, "PBM: DTD has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +000097 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +000098 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +000099 if (dtd->prev == NULL) {
100 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000101 fprintf(output, "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000102 } else {
103 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000104 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000105 }
106 if (dtd->next == NULL) {
107 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000108 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000109 } else {
110 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000111 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000112 }
113}
114
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000115static void
116xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000117 int i;
118 char shift[100];
119
120 for (i = 0;((i < depth) && (i < 25));i++)
121 shift[2 * i] = shift[2 * i + 1] = ' ';
122 shift[2 * i] = shift[2 * i + 1] = 0;
123
124 fprintf(output, shift);
125
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000126 if (attr == NULL) {
127 fprintf(output, "Attribute declaration is NULL\n");
128 return;
129 }
Owen Taylor3473f882001-02-23 17:55:21 +0000130 if (attr->type != XML_ATTRIBUTE_DECL) {
131 fprintf(output, "PBM: not a Attr\n");
132 return;
133 }
134 if (attr->name != NULL)
135 fprintf(output, "ATTRDECL(%s)", attr->name);
136 else
137 fprintf(output, "PBM ATTRDECL noname!!!");
138 if (attr->elem != NULL)
139 fprintf(output, " for %s", attr->elem);
140 else
141 fprintf(output, " PBM noelem!!!");
142 switch (attr->atype) {
143 case XML_ATTRIBUTE_CDATA:
144 fprintf(output, " CDATA");
145 break;
146 case XML_ATTRIBUTE_ID:
147 fprintf(output, " ID");
148 break;
149 case XML_ATTRIBUTE_IDREF:
150 fprintf(output, " IDREF");
151 break;
152 case XML_ATTRIBUTE_IDREFS:
153 fprintf(output, " IDREFS");
154 break;
155 case XML_ATTRIBUTE_ENTITY:
156 fprintf(output, " ENTITY");
157 break;
158 case XML_ATTRIBUTE_ENTITIES:
159 fprintf(output, " ENTITIES");
160 break;
161 case XML_ATTRIBUTE_NMTOKEN:
162 fprintf(output, " NMTOKEN");
163 break;
164 case XML_ATTRIBUTE_NMTOKENS:
165 fprintf(output, " NMTOKENS");
166 break;
167 case XML_ATTRIBUTE_ENUMERATION:
168 fprintf(output, " ENUMERATION");
169 break;
170 case XML_ATTRIBUTE_NOTATION:
171 fprintf(output, " NOTATION ");
172 break;
173 }
174 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000175 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000176 xmlEnumerationPtr cur = attr->tree;
177
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000178 for (indx = 0;indx < 5; indx++) {
179 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000180 fprintf(output, "|%s", cur->name);
181 else
182 fprintf(output, " (%s", cur->name);
183 cur = cur->next;
184 if (cur == NULL) break;
185 }
186 if (cur == NULL)
187 fprintf(output, ")");
188 else
189 fprintf(output, "...)");
190 }
191 switch (attr->def) {
192 case XML_ATTRIBUTE_NONE:
193 break;
194 case XML_ATTRIBUTE_REQUIRED:
195 fprintf(output, " REQUIRED");
196 break;
197 case XML_ATTRIBUTE_IMPLIED:
198 fprintf(output, " IMPLIED");
199 break;
200 case XML_ATTRIBUTE_FIXED:
201 fprintf(output, " FIXED");
202 break;
203 }
204 if (attr->defaultValue != NULL) {
205 fprintf(output, "\"");
206 xmlDebugDumpString(output, attr->defaultValue);
207 fprintf(output, "\"");
208 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000209 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000210
211 /*
212 * Do a bit of checking
213 */
214 if (attr->parent == NULL)
215 fprintf(output, "PBM: Attr has no parent\n");
216 if (attr->doc == NULL)
217 fprintf(output, "PBM: Attr has no doc\n");
218 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
219 fprintf(output, "PBM: Attr doc differs from parent's one\n");
220 if (attr->prev == NULL) {
221 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
222 fprintf(output, "PBM: Attr has no prev and not first of list\n");
223 } else {
224 if (attr->prev->next != (xmlNodePtr) attr)
225 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
226 }
227 if (attr->next == NULL) {
228 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
229 fprintf(output, "PBM: Attr has no next and not last of list\n");
230 } else {
231 if (attr->next->prev != (xmlNodePtr) attr)
232 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
233 }
234}
235
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000236static void
237xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000238 int i;
239 char shift[100];
240
241 for (i = 0;((i < depth) && (i < 25));i++)
242 shift[2 * i] = shift[2 * i + 1] = ' ';
243 shift[2 * i] = shift[2 * i + 1] = 0;
244
245 fprintf(output, shift);
246
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000247 if (elem == NULL) {
248 fprintf(output, "Element declaration is NULL\n");
249 return;
250 }
Owen Taylor3473f882001-02-23 17:55:21 +0000251 if (elem->type != XML_ELEMENT_DECL) {
252 fprintf(output, "PBM: not a Elem\n");
253 return;
254 }
255 if (elem->name != NULL) {
256 fprintf(output, "ELEMDECL(");
257 xmlDebugDumpString(output, elem->name);
258 fprintf(output, ")");
259 } else
260 fprintf(output, "PBM ELEMDECL noname!!!");
261 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000262 case XML_ELEMENT_TYPE_UNDEFINED:
263 fprintf(output, ", UNDEFINED");
264 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000265 case XML_ELEMENT_TYPE_EMPTY:
266 fprintf(output, ", EMPTY");
267 break;
268 case XML_ELEMENT_TYPE_ANY:
269 fprintf(output, ", ANY");
270 break;
271 case XML_ELEMENT_TYPE_MIXED:
272 fprintf(output, ", MIXED ");
273 break;
274 case XML_ELEMENT_TYPE_ELEMENT:
275 fprintf(output, ", MIXED ");
276 break;
277 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000278 if ((elem->type != XML_ELEMENT_NODE) &&
279 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000280 char buf[5001];
281
282 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000283 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000284 buf[5000] = 0;
285 fprintf(output, "%s", buf);
286 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000287 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000288
289 /*
290 * Do a bit of checking
291 */
292 if (elem->parent == NULL)
293 fprintf(output, "PBM: Elem has no parent\n");
294 if (elem->doc == NULL)
295 fprintf(output, "PBM: Elem has no doc\n");
296 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
297 fprintf(output, "PBM: Elem doc differs from parent's one\n");
298 if (elem->prev == NULL) {
299 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
300 fprintf(output, "PBM: Elem has no prev and not first of list\n");
301 } else {
302 if (elem->prev->next != (xmlNodePtr) elem)
303 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
304 }
305 if (elem->next == NULL) {
306 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
307 fprintf(output, "PBM: Elem has no next and not last of list\n");
308 } else {
309 if (elem->next->prev != (xmlNodePtr) elem)
310 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
311 }
312}
313
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000314static void
315xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000316 int i;
317 char shift[100];
318
319 for (i = 0;((i < depth) && (i < 25));i++)
320 shift[2 * i] = shift[2 * i + 1] = ' ';
321 shift[2 * i] = shift[2 * i + 1] = 0;
322
323 fprintf(output, shift);
324
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000325 if (ent == NULL) {
326 fprintf(output, "Entity declaration is NULL\n");
327 return;
328 }
Owen Taylor3473f882001-02-23 17:55:21 +0000329 if (ent->type != XML_ENTITY_DECL) {
330 fprintf(output, "PBM: not a Entity decl\n");
331 return;
332 }
333 if (ent->name != NULL) {
334 fprintf(output, "ENTITYDECL(");
335 xmlDebugDumpString(output, ent->name);
336 fprintf(output, ")");
337 } else
338 fprintf(output, "PBM ENTITYDECL noname!!!");
339 switch (ent->etype) {
340 case XML_INTERNAL_GENERAL_ENTITY:
341 fprintf(output, ", internal\n");
342 break;
343 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
344 fprintf(output, ", external parsed\n");
345 break;
346 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
347 fprintf(output, ", unparsed\n");
348 break;
349 case XML_INTERNAL_PARAMETER_ENTITY:
350 fprintf(output, ", parameter\n");
351 break;
352 case XML_EXTERNAL_PARAMETER_ENTITY:
353 fprintf(output, ", external parameter\n");
354 break;
355 case XML_INTERNAL_PREDEFINED_ENTITY:
356 fprintf(output, ", predefined\n");
357 break;
358 }
359 if (ent->ExternalID) {
360 fprintf(output, shift);
361 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
362 }
363 if (ent->SystemID) {
364 fprintf(output, shift);
365 fprintf(output, " SystemID=%s\n", ent->SystemID);
366 }
367 if (ent->URI != NULL) {
368 fprintf(output, shift);
369 fprintf(output, " URI=%s\n", ent->URI);
370 }
371 if (ent->content) {
372 fprintf(output, shift);
373 fprintf(output, " content=");
374 xmlDebugDumpString(output, ent->content);
375 fprintf(output, "\n");
376 }
377
378 /*
379 * Do a bit of checking
380 */
381 if (ent->parent == NULL)
382 fprintf(output, "PBM: Ent has no parent\n");
383 if (ent->doc == NULL)
384 fprintf(output, "PBM: Ent has no doc\n");
385 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
386 fprintf(output, "PBM: Ent doc differs from parent's one\n");
387 if (ent->prev == NULL) {
388 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
389 fprintf(output, "PBM: Ent has no prev and not first of list\n");
390 } else {
391 if (ent->prev->next != (xmlNodePtr) ent)
392 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
393 }
394 if (ent->next == NULL) {
395 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
396 fprintf(output, "PBM: Ent has no next and not last of list\n");
397 } else {
398 if (ent->next->prev != (xmlNodePtr) ent)
399 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
400 }
401}
402
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000403static void
404xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000405 int i;
406 char shift[100];
407
408 for (i = 0;((i < depth) && (i < 25));i++)
409 shift[2 * i] = shift[2 * i + 1] = ' ';
410 shift[2 * i] = shift[2 * i + 1] = 0;
411
412 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000413
414 if (ns == NULL) {
415 fprintf(output, "namespace node is NULL\n");
416 return;
417 }
Owen Taylor3473f882001-02-23 17:55:21 +0000418 if (ns->type != XML_NAMESPACE_DECL) {
419 fprintf(output, "invalid namespace node %d\n", ns->type);
420 return;
421 }
422 if (ns->href == NULL) {
423 if (ns->prefix != NULL)
424 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
425 else
426 fprintf(output, "incomplete default namespace href=NULL\n");
427 } else {
428 if (ns->prefix != NULL)
429 fprintf(output, "namespace %s href=", ns->prefix);
430 else
431 fprintf(output, "default namespace href=");
432
433 xmlDebugDumpString(output, ns->href);
434 fprintf(output, "\n");
435 }
436}
437
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000438static void
439xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000440 while (ns != NULL) {
441 xmlDebugDumpNamespace(output, ns, depth);
442 ns = ns->next;
443 }
444}
445
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000446static void
447xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000448 int i;
449 char shift[100];
450
451 for (i = 0;((i < depth) && (i < 25));i++)
452 shift[2 * i] = shift[2 * i + 1] = ' ';
453 shift[2 * i] = shift[2 * i + 1] = 0;
454
455 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000456
457 if (ent == NULL) {
458 fprintf(output, "Entity is NULL\n");
459 return;
460 }
Owen Taylor3473f882001-02-23 17:55:21 +0000461 switch (ent->etype) {
462 case XML_INTERNAL_GENERAL_ENTITY:
463 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
464 break;
465 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
466 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
467 break;
468 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
469 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
470 break;
471 case XML_INTERNAL_PARAMETER_ENTITY:
472 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
473 break;
474 case XML_EXTERNAL_PARAMETER_ENTITY:
475 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
476 break;
477 default:
478 fprintf(output, "ENTITY_%d ! ", ent->etype);
479 }
480 fprintf(output, "%s\n", ent->name);
481 if (ent->ExternalID) {
482 fprintf(output, shift);
483 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
484 }
485 if (ent->SystemID) {
486 fprintf(output, shift);
487 fprintf(output, "SystemID=%s\n", ent->SystemID);
488 }
489 if (ent->URI) {
490 fprintf(output, shift);
491 fprintf(output, "URI=%s\n", ent->URI);
492 }
493 if (ent->content) {
494 fprintf(output, shift);
495 fprintf(output, "content=");
496 xmlDebugDumpString(output, ent->content);
497 fprintf(output, "\n");
498 }
499}
500
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000501/**
502 * xmlDebugDumpAttr:
503 * @output: the FILE * for the output
504 * @attr: the attribute
505 * @depth: the indentation level.
506 *
507 * Dumps debug information for the attribute
508 */
509void
510xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000511 int i;
512 char shift[100];
513
514 for (i = 0;((i < depth) && (i < 25));i++)
515 shift[2 * i] = shift[2 * i + 1] = ' ';
516 shift[2 * i] = shift[2 * i + 1] = 0;
517
518 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000519
520 if (attr == NULL) {
521 fprintf(output, "Attr is NULL");
522 return;
523 }
Owen Taylor3473f882001-02-23 17:55:21 +0000524 fprintf(output, "ATTRIBUTE ");
525 xmlDebugDumpString(output, attr->name);
526 fprintf(output, "\n");
527 if (attr->children != NULL)
528 xmlDebugDumpNodeList(output, attr->children, depth + 1);
529
530 /*
531 * Do a bit of checking
532 */
533 if (attr->parent == NULL)
534 fprintf(output, "PBM: Attr has no parent\n");
535 if (attr->doc == NULL)
536 fprintf(output, "PBM: Attr has no doc\n");
537 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
538 fprintf(output, "PBM: Attr doc differs from parent's one\n");
539 if (attr->prev == NULL) {
540 if ((attr->parent != NULL) && (attr->parent->properties != attr))
541 fprintf(output, "PBM: Attr has no prev and not first of list\n");
542 } else {
543 if (attr->prev->next != attr)
544 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
545 }
546 if (attr->next != NULL) {
547 if (attr->next->prev != attr)
548 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
549 }
550}
551
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000552/**
553 * xmlDebugDumpAttrList:
554 * @output: the FILE * for the output
555 * @attr: the attribute list
556 * @depth: the indentation level.
557 *
558 * Dumps debug information for the attribute list
559 */
560void
561xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
562{
Daniel Veillard7db38712002-02-07 16:39:11 +0000563 if (output == NULL)
564 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000565 while (attr != NULL) {
566 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000567 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000568 }
569}
570
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000571/**
572 * xmlDebugDumpOneNode:
573 * @output: the FILE * for the output
574 * @node: the node
575 * @depth: the indentation level.
576 *
577 * Dumps debug information for the element node, it is not recursive
578 */
579void
580xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
581{
Owen Taylor3473f882001-02-23 17:55:21 +0000582 int i;
583 char shift[100];
584
Daniel Veillard7db38712002-02-07 16:39:11 +0000585 if (output == NULL)
586 output = stdout;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000587 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000588 shift[2 * i] = shift[2 * i + 1] = ' ';
589 shift[2 * i] = shift[2 * i + 1] = 0;
590
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000591 if (node == NULL) {
592 fprintf(output, shift);
593 fprintf(output, "node is NULL\n");
594 return;
595 }
Owen Taylor3473f882001-02-23 17:55:21 +0000596 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000597 case XML_ELEMENT_NODE:
598 fprintf(output, shift);
599 fprintf(output, "ELEMENT ");
600 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
601 xmlDebugDumpString(output, node->ns->prefix);
602 fprintf(output, ":");
603 }
604 xmlDebugDumpString(output, node->name);
605 fprintf(output, "\n");
606 break;
607 case XML_ATTRIBUTE_NODE:
608 fprintf(output, shift);
609 fprintf(output, "Error, ATTRIBUTE found here\n");
610 break;
611 case XML_TEXT_NODE:
612 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000613 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000614 fprintf(output, "TEXT no enc\n");
615 else
616 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000617 break;
618 case XML_CDATA_SECTION_NODE:
619 fprintf(output, shift);
620 fprintf(output, "CDATA_SECTION\n");
621 break;
622 case XML_ENTITY_REF_NODE:
623 fprintf(output, shift);
624 fprintf(output, "ENTITY_REF(%s)\n", node->name);
625 break;
626 case XML_ENTITY_NODE:
627 fprintf(output, shift);
628 fprintf(output, "ENTITY\n");
629 break;
630 case XML_PI_NODE:
631 fprintf(output, shift);
632 fprintf(output, "PI %s\n", node->name);
633 break;
634 case XML_COMMENT_NODE:
635 fprintf(output, shift);
636 fprintf(output, "COMMENT\n");
637 break;
638 case XML_DOCUMENT_NODE:
639 case XML_HTML_DOCUMENT_NODE:
640 fprintf(output, shift);
641 fprintf(output, "Error, DOCUMENT found here\n");
642 break;
643 case XML_DOCUMENT_TYPE_NODE:
644 fprintf(output, shift);
645 fprintf(output, "DOCUMENT_TYPE\n");
646 break;
647 case XML_DOCUMENT_FRAG_NODE:
648 fprintf(output, shift);
649 fprintf(output, "DOCUMENT_FRAG\n");
650 break;
651 case XML_NOTATION_NODE:
652 fprintf(output, shift);
653 fprintf(output, "NOTATION\n");
654 break;
655 case XML_DTD_NODE:
656 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
657 return;
658 case XML_ELEMENT_DECL:
659 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
660 return;
661 case XML_ATTRIBUTE_DECL:
662 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
663 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000664 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000665 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
666 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000667 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000668 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
669 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000670 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000671 fprintf(output, shift);
672 fprintf(output, "INCLUDE START\n");
673 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000674 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000675 fprintf(output, shift);
676 fprintf(output, "INCLUDE END\n");
677 return;
678 default:
679 fprintf(output, shift);
680 fprintf(output, "NODE_%d !!!\n", node->type);
681 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000682 }
683 if (node->doc == NULL) {
684 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000685 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000686 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000687 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000688 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
689 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000690 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000691 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000692 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
693 shift[2 * i] = shift[2 * i + 1] = ' ';
694 shift[2 * i + 2] = shift[2 * i + 3] = 0;
695 fprintf(output, shift);
696 fprintf(output, "content=");
697#ifndef XML_USE_BUFFER_CONTENT
698 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +0000699#else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000700 xmlDebugDumpString(output, xmlBufferContent(node->content));
Owen Taylor3473f882001-02-23 17:55:21 +0000701#endif
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000702 fprintf(output, "\n");
703 }
Owen Taylor3473f882001-02-23 17:55:21 +0000704 } else {
705 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000706
707 ent = xmlGetDocEntity(node->doc, node->name);
708 if (ent != NULL)
709 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000710 }
711 /*
712 * Do a bit of checking
713 */
714 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000715 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000716 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000717 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000718 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000719 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000720 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000721 if ((node->parent != NULL) && (node->parent->children != node))
722 fprintf(output,
723 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000724 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000725 if (node->prev->next != node)
726 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000727 }
728 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000729 if ((node->parent != NULL) && (node->parent->last != node))
730 fprintf(output,
731 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000732 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000733 if (node->next->prev != node)
734 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000735 }
736}
737
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000738/**
739 * xmlDebugDumpNode:
740 * @output: the FILE * for the output
741 * @node: the node
742 * @depth: the indentation level.
743 *
744 * Dumps debug information for the element node, it is recursive
745 */
746void
747xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
748{
Daniel Veillard7db38712002-02-07 16:39:11 +0000749 if (output == NULL)
750 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000751 if (node == NULL) {
752 int i;
753 char shift[100];
754
755 for (i = 0; ((i < depth) && (i < 25)); i++)
756 shift[2 * i] = shift[2 * i + 1] = ' ';
757 shift[2 * i] = shift[2 * i + 1] = 0;
758
759 fprintf(output, shift);
760 fprintf(output, "node is NULL\n");
761 return;
762 }
Owen Taylor3473f882001-02-23 17:55:21 +0000763 xmlDebugDumpOneNode(output, node, depth);
764 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000765 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000766}
767
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000768/**
769 * xmlDebugDumpNodeList:
770 * @output: the FILE * for the output
771 * @node: the node list
772 * @depth: the indentation level.
773 *
774 * Dumps debug information for the list of element node, it is recursive
775 */
776void
777xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
778{
Daniel Veillard7db38712002-02-07 16:39:11 +0000779 if (output == NULL)
780 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000781 while (node != NULL) {
782 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000783 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000784 }
785}
786
787
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000788/**
789 * xmlDebugDumpDocumentHead:
790 * @output: the FILE * for the output
791 * @doc: the document
792 *
793 * Dumps debug information cncerning the document, not recursive
794 */
795void
796xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
797{
798 if (output == NULL)
799 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000800 if (doc == NULL) {
801 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000802 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000803 }
804
805 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000806 case XML_ELEMENT_NODE:
807 fprintf(output, "Error, ELEMENT found here ");
808 break;
809 case XML_ATTRIBUTE_NODE:
810 fprintf(output, "Error, ATTRIBUTE found here\n");
811 break;
812 case XML_TEXT_NODE:
813 fprintf(output, "Error, TEXT\n");
814 break;
815 case XML_CDATA_SECTION_NODE:
816 fprintf(output, "Error, CDATA_SECTION\n");
817 break;
818 case XML_ENTITY_REF_NODE:
819 fprintf(output, "Error, ENTITY_REF\n");
820 break;
821 case XML_ENTITY_NODE:
822 fprintf(output, "Error, ENTITY\n");
823 break;
824 case XML_PI_NODE:
825 fprintf(output, "Error, PI\n");
826 break;
827 case XML_COMMENT_NODE:
828 fprintf(output, "Error, COMMENT\n");
829 break;
830 case XML_DOCUMENT_NODE:
831 fprintf(output, "DOCUMENT\n");
832 break;
833 case XML_HTML_DOCUMENT_NODE:
834 fprintf(output, "HTML DOCUMENT\n");
835 break;
836 case XML_DOCUMENT_TYPE_NODE:
837 fprintf(output, "Error, DOCUMENT_TYPE\n");
838 break;
839 case XML_DOCUMENT_FRAG_NODE:
840 fprintf(output, "Error, DOCUMENT_FRAG\n");
841 break;
842 case XML_NOTATION_NODE:
843 fprintf(output, "Error, NOTATION\n");
844 break;
845 default:
846 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000847 }
848 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000849 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000850 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000851 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000852 }
853 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000854 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000855 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000856 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000857 }
858 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000859 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000860 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000861 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000862 }
863 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000864 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000865 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000866 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000867 }
868 if (doc->standalone)
869 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000870 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000871 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
872}
873
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000874/**
875 * xmlDebugDumpDocument:
876 * @output: the FILE * for the output
877 * @doc: the document
878 *
879 * Dumps debug information for the document, it's recursive
880 */
881void
882xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
883{
884 if (output == NULL)
885 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000886 if (doc == NULL) {
887 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000888 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000889 }
890 xmlDebugDumpDocumentHead(output, doc);
891 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000892 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000893 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000894}
Owen Taylor3473f882001-02-23 17:55:21 +0000895
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000896/**
897 * xmlDebugDumpDTD:
898 * @output: the FILE * for the output
899 * @dtd: the DTD
900 *
901 * Dumps debug information for the DTD
902 */
903void
904xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
905{
Daniel Veillard7db38712002-02-07 16:39:11 +0000906 if (output == NULL)
907 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000908 if (dtd == NULL) {
909 fprintf(output, "DTD is NULL\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000910 return;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000911 }
Owen Taylor3473f882001-02-23 17:55:21 +0000912 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000913 fprintf(output, "PBM: not a DTD\n");
914 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000915 }
916 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000917 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000918 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000919 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000920 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000921 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000922 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000923 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000924 fprintf(output, "\n");
925 /*
926 * Do a bit of checking
927 */
928 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000929 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000930 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000931 if ((dtd->parent != NULL)
932 && (dtd->parent->children != (xmlNodePtr) dtd))
933 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000934 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000935 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000936 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000937 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000938 }
939 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000940 if ((dtd->parent != NULL)
941 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000942 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000943 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000944 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000945 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000946 }
947 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000948 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000949 else
950 xmlDebugDumpNodeList(output, dtd->children, 1);
951}
952
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000953static void
954xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000955 if (cur == NULL) {
956 fprintf(output, "Entity is NULL");
957 return;
958 }
Owen Taylor3473f882001-02-23 17:55:21 +0000959 fprintf(output, "%s : ", cur->name);
960 switch (cur->etype) {
961 case XML_INTERNAL_GENERAL_ENTITY:
962 fprintf(output, "INTERNAL GENERAL, ");
963 break;
964 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
965 fprintf(output, "EXTERNAL PARSED, ");
966 break;
967 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
968 fprintf(output, "EXTERNAL UNPARSED, ");
969 break;
970 case XML_INTERNAL_PARAMETER_ENTITY:
971 fprintf(output, "INTERNAL PARAMETER, ");
972 break;
973 case XML_EXTERNAL_PARAMETER_ENTITY:
974 fprintf(output, "EXTERNAL PARAMETER, ");
975 break;
976 default:
977 fprintf(output, "UNKNOWN TYPE %d",
978 cur->etype);
979 }
980 if (cur->ExternalID != NULL)
981 fprintf(output, "ID \"%s\"", cur->ExternalID);
982 if (cur->SystemID != NULL)
983 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
984 if (cur->orig != NULL)
985 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000986 if ((cur->type != XML_ELEMENT_NODE) &&
987 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000988 fprintf(output, "\n content \"%s\"", cur->content);
989 fprintf(output, "\n");
990}
991
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000992/**
993 * xmlDebugDumpEntities:
994 * @output: the FILE * for the output
995 * @doc: the document
996 *
997 * Dumps debug information for all the entities in use by the document
998 */
999void
1000xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1001{
1002 if (output == NULL)
1003 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001004 if (doc == NULL) {
1005 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001006 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001007 }
1008
1009 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001010 case XML_ELEMENT_NODE:
1011 fprintf(output, "Error, ELEMENT found here ");
1012 break;
1013 case XML_ATTRIBUTE_NODE:
1014 fprintf(output, "Error, ATTRIBUTE found here\n");
1015 break;
1016 case XML_TEXT_NODE:
1017 fprintf(output, "Error, TEXT\n");
1018 break;
1019 case XML_CDATA_SECTION_NODE:
1020 fprintf(output, "Error, CDATA_SECTION\n");
1021 break;
1022 case XML_ENTITY_REF_NODE:
1023 fprintf(output, "Error, ENTITY_REF\n");
1024 break;
1025 case XML_ENTITY_NODE:
1026 fprintf(output, "Error, ENTITY\n");
1027 break;
1028 case XML_PI_NODE:
1029 fprintf(output, "Error, PI\n");
1030 break;
1031 case XML_COMMENT_NODE:
1032 fprintf(output, "Error, COMMENT\n");
1033 break;
1034 case XML_DOCUMENT_NODE:
1035 fprintf(output, "DOCUMENT\n");
1036 break;
1037 case XML_HTML_DOCUMENT_NODE:
1038 fprintf(output, "HTML DOCUMENT\n");
1039 break;
1040 case XML_DOCUMENT_TYPE_NODE:
1041 fprintf(output, "Error, DOCUMENT_TYPE\n");
1042 break;
1043 case XML_DOCUMENT_FRAG_NODE:
1044 fprintf(output, "Error, DOCUMENT_FRAG\n");
1045 break;
1046 case XML_NOTATION_NODE:
1047 fprintf(output, "Error, NOTATION\n");
1048 break;
1049 default:
1050 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +00001051 }
1052 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001053 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1054 doc->intSubset->entities;
1055
1056 fprintf(output, "Entities in internal subset\n");
1057 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1058 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001059 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001060 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001061 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001062 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1063 doc->extSubset->entities;
1064
1065 fprintf(output, "Entities in external subset\n");
1066 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1067 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001068 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001069 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001070}
1071
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001072/**
1073 * xmlLsCountNode:
1074 * @node: the node to count
1075 *
1076 * Count the children of @node.
1077 *
1078 * Returns the number of children of @node.
1079 */
1080int
1081xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001082 int ret = 0;
1083 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001084
1085 if (node == NULL)
1086 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001087
1088 switch (node->type) {
1089 case XML_ELEMENT_NODE:
1090 list = node->children;
1091 break;
1092 case XML_DOCUMENT_NODE:
1093 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001094#ifdef LIBXML_DOCB_ENABLED
1095 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001096#endif
1097 list = ((xmlDocPtr) node)->children;
1098 break;
1099 case XML_ATTRIBUTE_NODE:
1100 list = ((xmlAttrPtr) node)->children;
1101 break;
1102 case XML_TEXT_NODE:
1103 case XML_CDATA_SECTION_NODE:
1104 case XML_PI_NODE:
1105 case XML_COMMENT_NODE:
1106 if (node->content != NULL) {
1107#ifndef XML_USE_BUFFER_CONTENT
1108 ret = xmlStrlen(node->content);
1109#else
1110 ret = xmlBufferLength(node->content);
1111#endif
1112 }
1113 break;
1114 case XML_ENTITY_REF_NODE:
1115 case XML_DOCUMENT_TYPE_NODE:
1116 case XML_ENTITY_NODE:
1117 case XML_DOCUMENT_FRAG_NODE:
1118 case XML_NOTATION_NODE:
1119 case XML_DTD_NODE:
1120 case XML_ELEMENT_DECL:
1121 case XML_ATTRIBUTE_DECL:
1122 case XML_ENTITY_DECL:
1123 case XML_NAMESPACE_DECL:
1124 case XML_XINCLUDE_START:
1125 case XML_XINCLUDE_END:
1126 ret = 1;
1127 break;
1128 }
1129 for (;list != NULL;ret++)
1130 list = list->next;
1131 return(ret);
1132}
1133
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001134/**
1135 * xmlLsOneNode:
1136 * @output: the FILE * for the output
1137 * @node: the node to dump
1138 *
1139 * Dump to @output the type and name of @node.
1140 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001141void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001142xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001143 if (node == NULL) {
1144 fprintf(output, "NULL\n");
1145 return;
1146 }
Owen Taylor3473f882001-02-23 17:55:21 +00001147 switch (node->type) {
1148 case XML_ELEMENT_NODE:
1149 fprintf(output, "-");
1150 break;
1151 case XML_ATTRIBUTE_NODE:
1152 fprintf(output, "a");
1153 break;
1154 case XML_TEXT_NODE:
1155 fprintf(output, "t");
1156 break;
1157 case XML_CDATA_SECTION_NODE:
1158 fprintf(output, "c");
1159 break;
1160 case XML_ENTITY_REF_NODE:
1161 fprintf(output, "e");
1162 break;
1163 case XML_ENTITY_NODE:
1164 fprintf(output, "E");
1165 break;
1166 case XML_PI_NODE:
1167 fprintf(output, "p");
1168 break;
1169 case XML_COMMENT_NODE:
1170 fprintf(output, "c");
1171 break;
1172 case XML_DOCUMENT_NODE:
1173 fprintf(output, "d");
1174 break;
1175 case XML_HTML_DOCUMENT_NODE:
1176 fprintf(output, "h");
1177 break;
1178 case XML_DOCUMENT_TYPE_NODE:
1179 fprintf(output, "T");
1180 break;
1181 case XML_DOCUMENT_FRAG_NODE:
1182 fprintf(output, "F");
1183 break;
1184 case XML_NOTATION_NODE:
1185 fprintf(output, "N");
1186 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001187 case XML_NAMESPACE_DECL:
1188 fprintf(output, "n");
1189 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001190 default:
1191 fprintf(output, "?");
1192 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001193 if (node->type != XML_NAMESPACE_DECL) {
1194 if (node->properties != NULL)
1195 fprintf(output, "a");
1196 else
1197 fprintf(output, "-");
1198 if (node->nsDef != NULL)
1199 fprintf(output, "n");
1200 else
1201 fprintf(output, "-");
1202 }
Owen Taylor3473f882001-02-23 17:55:21 +00001203
1204 fprintf(output, " %8d ", xmlLsCountNode(node));
1205
1206 switch (node->type) {
1207 case XML_ELEMENT_NODE:
1208 if (node->name != NULL)
1209 fprintf(output, "%s", node->name);
1210 break;
1211 case XML_ATTRIBUTE_NODE:
1212 if (node->name != NULL)
1213 fprintf(output, "%s", node->name);
1214 break;
1215 case XML_TEXT_NODE:
1216 if (node->content != NULL) {
1217#ifndef XML_USE_BUFFER_CONTENT
1218 xmlDebugDumpString(output, node->content);
1219#else
1220 xmlDebugDumpString(output, xmlBufferContent(node->content));
1221#endif
1222 }
1223 break;
1224 case XML_CDATA_SECTION_NODE:
1225 break;
1226 case XML_ENTITY_REF_NODE:
1227 if (node->name != NULL)
1228 fprintf(output, "%s", node->name);
1229 break;
1230 case XML_ENTITY_NODE:
1231 if (node->name != NULL)
1232 fprintf(output, "%s", node->name);
1233 break;
1234 case XML_PI_NODE:
1235 if (node->name != NULL)
1236 fprintf(output, "%s", node->name);
1237 break;
1238 case XML_COMMENT_NODE:
1239 break;
1240 case XML_DOCUMENT_NODE:
1241 break;
1242 case XML_HTML_DOCUMENT_NODE:
1243 break;
1244 case XML_DOCUMENT_TYPE_NODE:
1245 break;
1246 case XML_DOCUMENT_FRAG_NODE:
1247 break;
1248 case XML_NOTATION_NODE:
1249 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001250 case XML_NAMESPACE_DECL: {
1251 xmlNsPtr ns = (xmlNsPtr) node;
1252
1253 if (ns->prefix == NULL)
1254 fprintf(output, "default -> %s", ns->href);
1255 else
1256 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1257 break;
1258 }
Owen Taylor3473f882001-02-23 17:55:21 +00001259 default:
1260 if (node->name != NULL)
1261 fprintf(output, "%s", node->name);
1262 }
1263 fprintf(output, "\n");
1264}
1265
Daniel Veillard78d12092001-10-11 09:12:24 +00001266/**
1267 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001268 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001269 *
1270 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001271 *
1272 * Returns a pointer to either "True" or "False"
1273 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001274const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001275xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001276{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001277 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001278 return("True");
1279 else
1280 return("False");
1281}
1282
Owen Taylor3473f882001-02-23 17:55:21 +00001283/****************************************************************
1284 * *
1285 * The XML shell related functions *
1286 * *
1287 ****************************************************************/
1288
Daniel Veillard78d12092001-10-11 09:12:24 +00001289
1290
Owen Taylor3473f882001-02-23 17:55:21 +00001291/*
1292 * TODO: Improvement/cleanups for the XML shell
1293 * - allow to shell out an editor on a subpart
1294 * - cleanup function registrations (with help) and calling
1295 * - provide registration routines
1296 */
1297
1298/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001299 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001300 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001301 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001302 *
1303 * Print the xpath error to libxml default error channel
1304 */
1305void
1306xmlShellPrintXPathError(int errorType, const char *arg)
1307{
1308 const char *default_arg = "Result";
1309
1310 if (!arg)
1311 arg = default_arg;
1312
1313 switch (errorType) {
1314 case XPATH_UNDEFINED:
1315 xmlGenericError(xmlGenericErrorContext,
1316 "%s: no such node\n", arg);
1317 break;
1318
1319 case XPATH_BOOLEAN:
1320 xmlGenericError(xmlGenericErrorContext,
1321 "%s is a Boolean\n", arg);
1322 break;
1323 case XPATH_NUMBER:
1324 xmlGenericError(xmlGenericErrorContext,
1325 "%s is a number\n", arg);
1326 break;
1327 case XPATH_STRING:
1328 xmlGenericError(xmlGenericErrorContext,
1329 "%s is a string\n", arg);
1330 break;
1331 case XPATH_POINT:
1332 xmlGenericError(xmlGenericErrorContext,
1333 "%s is a point\n", arg);
1334 break;
1335 case XPATH_RANGE:
1336 xmlGenericError(xmlGenericErrorContext,
1337 "%s is a range\n", arg);
1338 break;
1339 case XPATH_LOCATIONSET:
1340 xmlGenericError(xmlGenericErrorContext,
1341 "%s is a range\n", arg);
1342 break;
1343 case XPATH_USERS:
1344 xmlGenericError(xmlGenericErrorContext,
1345 "%s is user-defined\n", arg);
1346 break;
1347 case XPATH_XSLT_TREE:
1348 xmlGenericError(xmlGenericErrorContext,
1349 "%s is an XSLT value tree\n", arg);
1350 break;
1351 }
1352 xmlGenericError(xmlGenericErrorContext,
1353 "Try casting the result string function (xpath builtin)\n",
1354 arg);
1355}
1356
1357
1358/**
1359 * xmlShellPrintNode:
1360 * @node : a non-null node to print to stdout
1361 *
1362 * Print node to stdout
1363 */
1364void
1365xmlShellPrintNode(xmlNodePtr node)
1366{
1367 if (!node)
1368 return;
1369
1370 if (node->type == XML_DOCUMENT_NODE)
1371 xmlDocDump(stdout, (xmlDocPtr) node);
1372 else if (node->type == XML_ATTRIBUTE_NODE)
1373 xmlDebugDumpAttrList(stdout, (xmlAttrPtr) node, 0);
1374 else
1375 xmlElemDump(stdout, node->doc, node);
1376
1377 fprintf(stdout, "\n");
1378}
1379
1380
1381/**
1382 * xmlShellPrintXPathResult:
Daniel Veillard9d06d302002-01-22 18:15:52 +00001383 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001384 *
1385 * Prints result to stdout
1386 */
1387void
1388xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1389{
1390 int i = 0;
1391
1392 if (list != NULL) {
1393 switch (list->type) {
1394 case XPATH_NODESET:{
1395 int indx;
1396
1397 if (list->nodesetval) {
1398 for (indx = 0; indx < list->nodesetval->nodeNr;
1399 indx++) {
1400 if (i > 0)
1401 fprintf(stderr, " -------\n");
1402 xmlShellPrintNode(list->nodesetval->
1403 nodeTab[indx]);
1404 }
1405 } else {
1406 xmlGenericError(xmlGenericErrorContext,
1407 "Empty node set\n");
1408 }
1409 break;
1410 }
1411 case XPATH_BOOLEAN:
1412 xmlGenericError(xmlGenericErrorContext,
1413 "Is a Boolean:%s\n",
1414 xmlBoolToText(list->boolval));
1415 break;
1416 case XPATH_NUMBER:
1417 xmlGenericError(xmlGenericErrorContext,
1418 "Is a number:%0g\n", list->floatval);
1419 break;
1420 case XPATH_STRING:
1421 xmlGenericError(xmlGenericErrorContext,
1422 "Is a string:%s\n", list->stringval);
1423 break;
1424
1425 default:
1426 xmlShellPrintXPathError(list->type, NULL);
1427 }
1428 }
1429}
1430
1431/**
Owen Taylor3473f882001-02-23 17:55:21 +00001432 * xmlShellList:
1433 * @ctxt: the shell context
1434 * @arg: unused
1435 * @node: a node
1436 * @node2: unused
1437 *
1438 * Implements the XML shell function "ls"
1439 * Does an Unix like listing of the given node (like a directory)
1440 *
1441 * Returns 0
1442 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001443int
1444xmlShellList(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1445 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1446 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1447{
Owen Taylor3473f882001-02-23 17:55:21 +00001448 xmlNodePtr cur;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001449 if (node == NULL) {
1450 fprintf(stdout, "NULL\n");
1451 return (0);
1452 }
Owen Taylor3473f882001-02-23 17:55:21 +00001453 if ((node->type == XML_DOCUMENT_NODE) ||
1454 (node->type == XML_HTML_DOCUMENT_NODE)) {
1455 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001456 } else if (node->type == XML_NAMESPACE_DECL) {
1457 xmlLsOneNode(stdout, node);
1458 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001459 } else if (node->children != NULL) {
1460 cur = node->children;
1461 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001462 xmlLsOneNode(stdout, node);
1463 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001464 }
1465 while (cur != NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001466 xmlLsOneNode(stdout, cur);
1467 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001468 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001469 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001470}
1471
1472/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001473 * xmlShellBase:
1474 * @ctxt: the shell context
1475 * @arg: unused
1476 * @node: a node
1477 * @node2: unused
1478 *
1479 * Implements the XML shell function "base"
1480 * dumps the current XML base of the node
1481 *
1482 * Returns 0
1483 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001484int
1485xmlShellBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1486 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1487 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1488{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001489 xmlChar *base;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001490 if (node == NULL) {
1491 fprintf(stdout, "NULL\n");
1492 return (0);
1493 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001494
1495 base = xmlNodeGetBase(node->doc, node);
1496
1497 if (base == NULL) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001498 fprintf(stdout, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001499 } else {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001500 fprintf(stdout, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001501 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001502 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001503 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001504}
1505
1506/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001507 * xmlShellSetBase:
1508 * @ctxt: the shell context
1509 * @arg: the new base
1510 * @node: a node
1511 * @node2: unused
1512 *
1513 * Implements the XML shell function "setbase"
1514 * change the current XML base of the node
1515 *
1516 * Returns 0
1517 */
1518static int
1519xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1520 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1521 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1522{
1523 xmlNodeSetBase(node, (xmlChar*) arg);
1524 return (0);
1525}
1526
1527/**
Owen Taylor3473f882001-02-23 17:55:21 +00001528 * xmlShellDir:
1529 * @ctxt: the shell context
1530 * @arg: unused
1531 * @node: a node
1532 * @node2: unused
1533 *
1534 * Implements the XML shell function "dir"
1535 * dumps informations about the node (namespace, attributes, content).
1536 *
1537 * Returns 0
1538 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001539int
1540xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1541 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1542 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1543{
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001544 if (node == NULL) {
1545 fprintf(stdout, "NULL\n");
1546 return (0);
1547 }
Owen Taylor3473f882001-02-23 17:55:21 +00001548 if ((node->type == XML_DOCUMENT_NODE) ||
1549 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001550 xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001551 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001552 xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001553 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001554 xmlDebugDumpOneNode(stdout, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001555 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001556 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001557}
1558
1559/**
1560 * xmlShellCat:
1561 * @ctxt: the shell context
1562 * @arg: unused
1563 * @node: a node
1564 * @node2: unused
1565 *
1566 * Implements the XML shell function "cat"
1567 * dumps the serialization node content (XML or HTML).
1568 *
1569 * Returns 0
1570 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001571int
1572xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1573 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1574{
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001575 if (node == NULL) {
1576 fprintf(stdout, "NULL\n");
1577 return (0);
1578 }
Owen Taylor3473f882001-02-23 17:55:21 +00001579 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1580#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001581 if (node->type == XML_HTML_DOCUMENT_NODE)
1582 htmlDocDump(stdout, (htmlDocPtr) node);
1583 else
1584 htmlNodeDumpFile(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001585#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001586 if (node->type == XML_DOCUMENT_NODE)
1587 xmlDocDump(stdout, (xmlDocPtr) node);
1588 else
1589 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001590#endif /* LIBXML_HTML_ENABLED */
1591 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001592 if (node->type == XML_DOCUMENT_NODE)
1593 xmlDocDump(stdout, (xmlDocPtr) node);
1594 else
1595 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001596 }
Daniel Veillardcd337f02001-11-22 18:20:37 +00001597 fprintf(stdout, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001598 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001599}
1600
1601/**
1602 * xmlShellLoad:
1603 * @ctxt: the shell context
1604 * @filename: the file name
1605 * @node: unused
1606 * @node2: unused
1607 *
1608 * Implements the XML shell function "load"
1609 * loads a new document specified by the filename
1610 *
1611 * Returns 0 or -1 if loading failed
1612 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001613int
1614xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1615 xmlNodePtr node ATTRIBUTE_UNUSED,
1616 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1617{
Owen Taylor3473f882001-02-23 17:55:21 +00001618 xmlDocPtr doc;
1619 int html = 0;
1620
1621 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001622 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001623
1624 if (html) {
1625#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001626 doc = htmlParseFile(filename, NULL);
1627#else
Daniel Veillardcd337f02001-11-22 18:20:37 +00001628 fprintf(stdout, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001629 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001630#endif /* LIBXML_HTML_ENABLED */
1631 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001632 doc = xmlParseFile(filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001633 }
1634 if (doc != NULL) {
1635 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001636 xmlFreeDoc(ctxt->doc);
1637 }
1638 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001639#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001640 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001641#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001642 xmlFree(ctxt->filename);
1643 ctxt->doc = doc;
1644 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001645#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001646 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001647#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001648 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001649 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001650 return (-1);
1651 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001652}
1653
1654/**
1655 * xmlShellWrite:
1656 * @ctxt: the shell context
1657 * @filename: the file name
1658 * @node: a node in the tree
1659 * @node2: unused
1660 *
1661 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001662 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001663 * of the subtree under the @node specified
1664 *
1665 * Returns 0 or -1 in case of error
1666 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001667int
Owen Taylor3473f882001-02-23 17:55:21 +00001668xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001669 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1670{
Owen Taylor3473f882001-02-23 17:55:21 +00001671 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001672 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001673 if ((filename == NULL) || (filename[0] == 0)) {
1674 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001675 "Write command requires a filename argument\n");
1676 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001677 }
1678#ifdef W_OK
1679 if (access((char *) filename, W_OK)) {
1680 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001681 "Cannot write to %s\n", filename);
1682 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001683 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001684#endif
1685 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001686 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001687 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1688 xmlGenericError(xmlGenericErrorContext,
1689 "Failed to write to %s\n", filename);
1690 return (-1);
1691 }
1692 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001693 case XML_HTML_DOCUMENT_NODE:
1694#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001695 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1696 xmlGenericError(xmlGenericErrorContext,
1697 "Failed to write to %s\n", filename);
1698 return (-1);
1699 }
Owen Taylor3473f882001-02-23 17:55:21 +00001700#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001701 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1702 xmlGenericError(xmlGenericErrorContext,
1703 "Failed to write to %s\n", filename);
1704 return (-1);
1705 }
Owen Taylor3473f882001-02-23 17:55:21 +00001706#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001707 break;
1708 default:{
1709 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001710
Daniel Veillard78d12092001-10-11 09:12:24 +00001711 f = fopen((char *) filename, "w");
1712 if (f == NULL) {
1713 xmlGenericError(xmlGenericErrorContext,
1714 "Failed to write to %s\n", filename);
1715 return (-1);
1716 }
1717 xmlElemDump(f, ctxt->doc, node);
1718 fclose(f);
1719 }
Owen Taylor3473f882001-02-23 17:55:21 +00001720 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001721 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001722}
1723
1724/**
1725 * xmlShellSave:
1726 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001727 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001728 * @node: unused
1729 * @node2: unused
1730 *
1731 * Implements the XML shell function "save"
1732 * Write the current document to the filename, or it's original name
1733 *
1734 * Returns 0 or -1 in case of error
1735 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001736int
1737xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1738 xmlNodePtr node ATTRIBUTE_UNUSED,
1739 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1740{
Owen Taylor3473f882001-02-23 17:55:21 +00001741 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001742 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001743 if ((filename == NULL) || (filename[0] == 0))
1744 filename = ctxt->filename;
1745#ifdef W_OK
1746 if (access((char *) filename, W_OK)) {
1747 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001748 "Cannot save to %s\n", filename);
1749 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001750 }
1751#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001752 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001753 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001754 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1755 xmlGenericError(xmlGenericErrorContext,
1756 "Failed to save to %s\n", filename);
1757 }
1758 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001759 case XML_HTML_DOCUMENT_NODE:
1760#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001761 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1762 xmlGenericError(xmlGenericErrorContext,
1763 "Failed to save to %s\n", filename);
1764 }
Owen Taylor3473f882001-02-23 17:55:21 +00001765#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001766 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1767 xmlGenericError(xmlGenericErrorContext,
1768 "Failed to save to %s\n", filename);
1769 }
Owen Taylor3473f882001-02-23 17:55:21 +00001770#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001771 break;
1772 default:
1773 xmlGenericError(xmlGenericErrorContext,
1774 "To save to subparts of a document use the 'write' command\n");
1775 return (-1);
1776
Owen Taylor3473f882001-02-23 17:55:21 +00001777 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001778 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001779}
1780
1781/**
1782 * xmlShellValidate:
1783 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001784 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001785 * @node: unused
1786 * @node2: unused
1787 *
1788 * Implements the XML shell function "validate"
1789 * Validate the document, if a DTD path is provided, then the validation
1790 * is done against the given DTD.
1791 *
1792 * Returns 0 or -1 in case of error
1793 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001794int
1795xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1796 xmlNodePtr node ATTRIBUTE_UNUSED,
1797 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1798{
Owen Taylor3473f882001-02-23 17:55:21 +00001799 xmlValidCtxt vctxt;
1800 int res = -1;
1801
1802 vctxt.userData = stderr;
1803 vctxt.error = (xmlValidityErrorFunc) fprintf;
1804 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1805
1806 if ((dtd == NULL) || (dtd[0] == 0)) {
1807 res = xmlValidateDocument(&vctxt, ctxt->doc);
1808 } else {
1809 xmlDtdPtr subset;
1810
Daniel Veillard78d12092001-10-11 09:12:24 +00001811 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1812 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001813 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1814
Daniel Veillard78d12092001-10-11 09:12:24 +00001815 xmlFreeDtd(subset);
1816 }
Owen Taylor3473f882001-02-23 17:55:21 +00001817 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001818 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00001819}
1820
1821/**
1822 * xmlShellDu:
1823 * @ctxt: the shell context
1824 * @arg: unused
1825 * @tree: a node defining a subtree
1826 * @node2: unused
1827 *
1828 * Implements the XML shell function "du"
1829 * show the structure of the subtree under node @tree
1830 * If @tree is null, the command works on the current node.
1831 *
1832 * Returns 0 or -1 in case of error
1833 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001834int
1835xmlShellDu(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1836 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1837 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1838{
Owen Taylor3473f882001-02-23 17:55:21 +00001839 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00001840 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00001841
Daniel Veillard78d12092001-10-11 09:12:24 +00001842 if (tree == NULL)
1843 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001844 node = tree;
1845 while (node != NULL) {
1846 if ((node->type == XML_DOCUMENT_NODE) ||
1847 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001848 fprintf(stdout, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001849 } else if (node->type == XML_ELEMENT_NODE) {
1850 for (i = 0; i < indent; i++)
Daniel Veillardcd337f02001-11-22 18:20:37 +00001851 fprintf(stdout, " ");
1852 fprintf(stdout, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00001853 } else {
1854 }
Owen Taylor3473f882001-02-23 17:55:21 +00001855
Daniel Veillard78d12092001-10-11 09:12:24 +00001856 /*
1857 * Browse the full subtree, deep first
1858 */
Owen Taylor3473f882001-02-23 17:55:21 +00001859
1860 if ((node->type == XML_DOCUMENT_NODE) ||
1861 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001862 node = ((xmlDocPtr) node)->children;
1863 } else if ((node->children != NULL)
1864 && (node->type != XML_ENTITY_REF_NODE)) {
1865 /* deep first */
1866 node = node->children;
1867 indent++;
1868 } else if ((node != tree) && (node->next != NULL)) {
1869 /* then siblings */
1870 node = node->next;
1871 } else if (node != tree) {
1872 /* go up to parents->next if needed */
1873 while (node != tree) {
1874 if (node->parent != NULL) {
1875 node = node->parent;
1876 indent--;
1877 }
1878 if ((node != tree) && (node->next != NULL)) {
1879 node = node->next;
1880 break;
1881 }
1882 if (node->parent == NULL) {
1883 node = NULL;
1884 break;
1885 }
1886 if (node == tree) {
1887 node = NULL;
1888 break;
1889 }
1890 }
1891 /* exit condition */
1892 if (node == tree)
1893 node = NULL;
1894 } else
1895 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001896 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001897 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001898}
1899
1900/**
1901 * xmlShellPwd:
1902 * @ctxt: the shell context
1903 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00001904 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00001905 * @node2: unused
1906 *
1907 * Implements the XML shell function "pwd"
1908 * Show the full path from the root to the node, if needed building
1909 * thumblers when similar elements exists at a given ancestor level.
1910 * The output is compatible with XPath commands.
1911 *
1912 * Returns 0 or -1 in case of error
1913 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001914int
1915xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
1916 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1917{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001918 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00001919
Daniel Veillard78d12092001-10-11 09:12:24 +00001920 if (node == NULL)
1921 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001922
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001923 path = xmlGetNodePath(node);
1924 if (path == NULL)
1925 return (-1);
1926
1927 /*
1928 * This test prevents buffer overflow, because this routine
1929 * is only called by xmlShell, in which the second argument is
1930 * 500 chars long.
1931 * It is a dirty hack before a cleaner solution is found.
1932 * Documentation should mention that the second argument must
1933 * be at least 500 chars long, and could be stripped if too long.
1934 */
1935 snprintf(buffer, 499, "%s", path);
1936 buffer[499] = '0';
1937 xmlFree(path);
1938
Daniel Veillard78d12092001-10-11 09:12:24 +00001939 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001940}
1941
1942/**
1943 * xmlShell
1944 * @doc: the initial document
1945 * @filename: the output buffer
1946 * @input: the line reading function
1947 * @output: the output FILE*
1948 *
1949 * Implements the XML shell
1950 * This allow to load, validate, view, modify and save a document
1951 * using a environment similar to a UNIX commandline.
1952 */
1953void
1954xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00001955 FILE * output)
1956{
Owen Taylor3473f882001-02-23 17:55:21 +00001957 char prompt[500] = "/ > ";
1958 char *cmdline = NULL, *cur;
1959 int nbargs;
1960 char command[100];
1961 char arg[400];
1962 int i;
1963 xmlShellCtxtPtr ctxt;
1964 xmlXPathObjectPtr list;
1965
1966 if (doc == NULL)
1967 return;
1968 if (filename == NULL)
1969 return;
1970 if (input == NULL)
1971 return;
1972 if (output == NULL)
1973 return;
1974 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00001975 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00001976 return;
1977 ctxt->loaded = 0;
1978 ctxt->doc = doc;
1979 ctxt->input = input;
1980 ctxt->output = output;
1981 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00001982 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001983
1984#ifdef LIBXML_XPATH_ENABLED
1985 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1986 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001987 xmlFree(ctxt);
1988 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001989 }
1990#endif /* LIBXML_XPATH_ENABLED */
1991 while (1) {
1992 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Daniel Veillard78d12092001-10-11 09:12:24 +00001993 sprintf(prompt, "%s > ", "/");
1994 else if (ctxt->node->name)
1995 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001996 else
Daniel Veillard78d12092001-10-11 09:12:24 +00001997 sprintf(prompt, "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00001998 prompt[sizeof(prompt) - 1] = 0;
1999
Daniel Veillard78d12092001-10-11 09:12:24 +00002000 /*
2001 * Get a new command line
2002 */
Owen Taylor3473f882001-02-23 17:55:21 +00002003 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00002004 if (cmdline == NULL)
2005 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002006
Daniel Veillard78d12092001-10-11 09:12:24 +00002007 /*
2008 * Parse the command itself
2009 */
2010 cur = cmdline;
2011 nbargs = 0;
2012 while ((*cur == ' ') || (*cur == '\t'))
2013 cur++;
2014 i = 0;
2015 while ((*cur != ' ') && (*cur != '\t') &&
2016 (*cur != '\n') && (*cur != '\r')) {
2017 if (*cur == 0)
2018 break;
2019 command[i++] = *cur++;
2020 }
2021 command[i] = 0;
2022 if (i == 0)
2023 continue;
2024 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002025
Daniel Veillard78d12092001-10-11 09:12:24 +00002026 /*
2027 * Parse the argument
2028 */
2029 while ((*cur == ' ') || (*cur == '\t'))
2030 cur++;
2031 i = 0;
2032 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2033 if (*cur == 0)
2034 break;
2035 arg[i++] = *cur++;
2036 }
2037 arg[i] = 0;
2038 if (i != 0)
2039 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002040
Daniel Veillard78d12092001-10-11 09:12:24 +00002041 /*
2042 * start interpreting the command
2043 */
Owen Taylor3473f882001-02-23 17:55:21 +00002044 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002045 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002046 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002047 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002048 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002049 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002050 if (!strcmp(command, "help")) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00002051 fprintf(stdout, "\tbase display XML base of the node\n");
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002052 fprintf(stdout, "\tsetbase URI change the XML base of the node\n");
Daniel Veillardcd337f02001-11-22 18:20:37 +00002053 fprintf(stdout, "\tbye leave shell\n");
2054 fprintf(stdout, "\tcat [node] display node or current node\n");
2055 fprintf(stdout, "\tcd [path] change directory to path or to root\n");
2056 fprintf(stdout, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2057 fprintf(stdout, "\tdu [path] show the structure of the subtree under path or the current node\n");
2058 fprintf(stdout, "\texit leave shell\n");
2059 fprintf(stdout, "\thelp display this help\n");
2060 fprintf(stdout, "\tfree display memory usage\n");
2061 fprintf(stdout, "\tload [name] load a new document with name\n");
2062 fprintf(stdout, "\tls [path] list contents of path or the current directory\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002063#ifdef LIBXML_XPATH_ENABLED
2064 fprintf(stdout, "\txpath expr evaluate the XPath expression in that context and print the result\n");
2065#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcd337f02001-11-22 18:20:37 +00002066 fprintf(stdout, "\tpwd display current working directory\n");
2067 fprintf(stdout, "\tquit leave shell\n");
2068 fprintf(stdout, "\tsave [name] save this document to name or the original name\n");
2069 fprintf(stdout, "\tvalidate check the document for errors\n");
2070 fprintf(stdout, "\twrite [name] write the current node to the filename\n");
Daniel Veillard5004f422001-11-08 13:53:05 +00002071 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002072 xmlShellValidate(ctxt, arg, NULL, NULL);
2073 } else if (!strcmp(command, "load")) {
2074 xmlShellLoad(ctxt, arg, NULL, NULL);
2075 } else if (!strcmp(command, "save")) {
2076 xmlShellSave(ctxt, arg, NULL, NULL);
2077 } else if (!strcmp(command, "write")) {
2078 xmlShellWrite(ctxt, arg, NULL, NULL);
2079 } else if (!strcmp(command, "free")) {
2080 if (arg[0] == 0) {
2081 xmlMemShow(stdout, 0);
2082 } else {
2083 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002084
Daniel Veillard78d12092001-10-11 09:12:24 +00002085 sscanf(arg, "%d", &len);
2086 xmlMemShow(stdout, len);
2087 }
2088 } else if (!strcmp(command, "pwd")) {
2089 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002090
Daniel Veillard78d12092001-10-11 09:12:24 +00002091 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillardcd337f02001-11-22 18:20:37 +00002092 fprintf(stdout, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002093 } else if (!strcmp(command, "du")) {
2094 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2095 } else if (!strcmp(command, "base")) {
2096 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002097#ifdef LIBXML_XPATH_ENABLED
2098 } else if (!strcmp(command, "xpath")) {
2099 if (arg[0] == 0) {
2100 xmlGenericError(xmlGenericErrorContext,
2101 "xpath: expression required\n");
2102 } else {
2103 ctxt->pctxt->node = ctxt->node;
2104 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2105 xmlXPathDebugDumpObject(stdout, list, 0);
2106 xmlXPathFreeObject(list);
2107 }
2108#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002109 } else if (!strcmp(command, "setbase")) {
2110 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002111 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2112 int dir = (!strcmp(command, "dir"));
2113
2114 if (arg[0] == 0) {
2115 if (dir)
2116 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2117 else
2118 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2119 } else {
2120 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002121#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002122 ctxt->pctxt->node = ctxt->node;
2123 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2124#else
2125 list = NULL;
2126#endif /* LIBXML_XPATH_ENABLED */
2127 if (list != NULL) {
2128 switch (list->type) {
2129 case XPATH_UNDEFINED:
2130 xmlGenericError(xmlGenericErrorContext,
2131 "%s: no such node\n", arg);
2132 break;
2133 case XPATH_NODESET:{
2134 int indx;
2135
Daniel Veillarda6825e82001-11-07 13:33:59 +00002136 if (list->nodesetval == NULL)
2137 break;
2138
Daniel Veillard78d12092001-10-11 09:12:24 +00002139 for (indx = 0;
2140 indx < list->nodesetval->nodeNr;
2141 indx++) {
2142 if (dir)
2143 xmlShellDir(ctxt, NULL,
2144 list->nodesetval->
2145 nodeTab[indx], NULL);
2146 else
2147 xmlShellList(ctxt, NULL,
2148 list->nodesetval->
2149 nodeTab[indx], NULL);
2150 }
2151 break;
2152 }
2153 case XPATH_BOOLEAN:
2154 xmlGenericError(xmlGenericErrorContext,
2155 "%s is a Boolean\n", arg);
2156 break;
2157 case XPATH_NUMBER:
2158 xmlGenericError(xmlGenericErrorContext,
2159 "%s is a number\n", arg);
2160 break;
2161 case XPATH_STRING:
2162 xmlGenericError(xmlGenericErrorContext,
2163 "%s is a string\n", arg);
2164 break;
2165 case XPATH_POINT:
2166 xmlGenericError(xmlGenericErrorContext,
2167 "%s is a point\n", arg);
2168 break;
2169 case XPATH_RANGE:
2170 xmlGenericError(xmlGenericErrorContext,
2171 "%s is a range\n", arg);
2172 break;
2173 case XPATH_LOCATIONSET:
2174 xmlGenericError(xmlGenericErrorContext,
2175 "%s is a range\n", arg);
2176 break;
2177 case XPATH_USERS:
2178 xmlGenericError(xmlGenericErrorContext,
2179 "%s is user-defined\n", arg);
2180 break;
2181 case XPATH_XSLT_TREE:
2182 xmlGenericError(xmlGenericErrorContext,
2183 "%s is an XSLT value tree\n",
2184 arg);
2185 break;
2186 }
2187#ifdef LIBXML_XPATH_ENABLED
2188 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002189#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002190 } else {
2191 xmlGenericError(xmlGenericErrorContext,
2192 "%s: no such node\n", arg);
2193 }
2194 ctxt->pctxt->node = NULL;
2195 }
2196 } else if (!strcmp(command, "cd")) {
2197 if (arg[0] == 0) {
2198 ctxt->node = (xmlNodePtr) ctxt->doc;
2199 } else {
2200#ifdef LIBXML_XPATH_ENABLED
2201 ctxt->pctxt->node = ctxt->node;
2202 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2203#else
2204 list = NULL;
2205#endif /* LIBXML_XPATH_ENABLED */
2206 if (list != NULL) {
2207 switch (list->type) {
2208 case XPATH_UNDEFINED:
2209 xmlGenericError(xmlGenericErrorContext,
2210 "%s: no such node\n", arg);
2211 break;
2212 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002213 if (list->nodesetval != NULL) {
2214 if (list->nodesetval->nodeNr == 1) {
2215 ctxt->node = list->nodesetval->nodeTab[0];
2216 } else
2217 xmlGenericError(xmlGenericErrorContext,
2218 "%s is a %d Node Set\n",
2219 arg,
2220 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002221 } else
2222 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002223 "%s is an empty Node Set\n",
2224 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002225 break;
2226 case XPATH_BOOLEAN:
2227 xmlGenericError(xmlGenericErrorContext,
2228 "%s is a Boolean\n", arg);
2229 break;
2230 case XPATH_NUMBER:
2231 xmlGenericError(xmlGenericErrorContext,
2232 "%s is a number\n", arg);
2233 break;
2234 case XPATH_STRING:
2235 xmlGenericError(xmlGenericErrorContext,
2236 "%s is a string\n", arg);
2237 break;
2238 case XPATH_POINT:
2239 xmlGenericError(xmlGenericErrorContext,
2240 "%s is a point\n", arg);
2241 break;
2242 case XPATH_RANGE:
2243 xmlGenericError(xmlGenericErrorContext,
2244 "%s is a range\n", arg);
2245 break;
2246 case XPATH_LOCATIONSET:
2247 xmlGenericError(xmlGenericErrorContext,
2248 "%s is a range\n", arg);
2249 break;
2250 case XPATH_USERS:
2251 xmlGenericError(xmlGenericErrorContext,
2252 "%s is user-defined\n", arg);
2253 break;
2254 case XPATH_XSLT_TREE:
2255 xmlGenericError(xmlGenericErrorContext,
2256 "%s is an XSLT value tree\n",
2257 arg);
2258 break;
2259 }
2260#ifdef LIBXML_XPATH_ENABLED
2261 xmlXPathFreeObject(list);
2262#endif
2263 } else {
2264 xmlGenericError(xmlGenericErrorContext,
2265 "%s: no such node\n", arg);
2266 }
2267 ctxt->pctxt->node = NULL;
2268 }
2269 } else if (!strcmp(command, "cat")) {
2270 if (arg[0] == 0) {
2271 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2272 } else {
2273 ctxt->pctxt->node = ctxt->node;
2274#ifdef LIBXML_XPATH_ENABLED
2275 ctxt->pctxt->node = ctxt->node;
2276 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2277#else
2278 list = NULL;
2279#endif /* LIBXML_XPATH_ENABLED */
2280 if (list != NULL) {
2281 switch (list->type) {
2282 case XPATH_UNDEFINED:
2283 xmlGenericError(xmlGenericErrorContext,
2284 "%s: no such node\n", arg);
2285 break;
2286 case XPATH_NODESET:{
2287 int indx;
2288
Daniel Veillarda6825e82001-11-07 13:33:59 +00002289 if (list->nodesetval == NULL)
2290 break;
2291
Daniel Veillard78d12092001-10-11 09:12:24 +00002292 for (indx = 0;
2293 indx < list->nodesetval->nodeNr;
2294 indx++) {
2295 if (i > 0)
Daniel Veillardcd337f02001-11-22 18:20:37 +00002296 fprintf(stdout, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002297 xmlShellCat(ctxt, NULL,
2298 list->nodesetval->
2299 nodeTab[indx], NULL);
2300 }
2301 break;
2302 }
2303 case XPATH_BOOLEAN:
2304 xmlGenericError(xmlGenericErrorContext,
2305 "%s is a Boolean\n", arg);
2306 break;
2307 case XPATH_NUMBER:
2308 xmlGenericError(xmlGenericErrorContext,
2309 "%s is a number\n", arg);
2310 break;
2311 case XPATH_STRING:
2312 xmlGenericError(xmlGenericErrorContext,
2313 "%s is a string\n", arg);
2314 break;
2315 case XPATH_POINT:
2316 xmlGenericError(xmlGenericErrorContext,
2317 "%s is a point\n", arg);
2318 break;
2319 case XPATH_RANGE:
2320 xmlGenericError(xmlGenericErrorContext,
2321 "%s is a range\n", arg);
2322 break;
2323 case XPATH_LOCATIONSET:
2324 xmlGenericError(xmlGenericErrorContext,
2325 "%s is a range\n", arg);
2326 break;
2327 case XPATH_USERS:
2328 xmlGenericError(xmlGenericErrorContext,
2329 "%s is user-defined\n", arg);
2330 break;
2331 case XPATH_XSLT_TREE:
2332 xmlGenericError(xmlGenericErrorContext,
2333 "%s is an XSLT value tree\n",
2334 arg);
2335 break;
2336 }
2337#ifdef LIBXML_XPATH_ENABLED
2338 xmlXPathFreeObject(list);
2339#endif
2340 } else {
2341 xmlGenericError(xmlGenericErrorContext,
2342 "%s: no such node\n", arg);
2343 }
2344 ctxt->pctxt->node = NULL;
2345 }
2346 } else {
2347 xmlGenericError(xmlGenericErrorContext,
2348 "Unknown command %s\n", command);
2349 }
2350 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002351 }
2352#ifdef LIBXML_XPATH_ENABLED
2353 xmlXPathFreeContext(ctxt->pctxt);
2354#endif /* LIBXML_XPATH_ENABLED */
2355 if (ctxt->loaded) {
2356 xmlFreeDoc(ctxt->doc);
2357 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002358 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002359 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002360 xmlFree(ctxt);
2361 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002362 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002363}
2364
2365#endif /* LIBXML_DEBUG_ENABLED */