blob: 613dadc6e08119592cb9d97cf7b5b3566d851bec [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * debugXML.c : This is a set of routines used for debugging the tree
3 * produced by the XML parser.
4 *
5 * See Copyright for the status of this software.
6 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00007 * Daniel Veillard <daniel@veillard.com>
Owen Taylor3473f882001-02-23 17:55:21 +00008 */
9
Bjorn Reese70a9da52001-04-21 16:57:29 +000010#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000011#ifdef LIBXML_DEBUG_ENABLED
12
Owen Taylor3473f882001-02-23 17:55:21 +000013#include <string.h>
14#ifdef HAVE_STDLIB_H
15#include <stdlib.h>
16#endif
17#ifdef HAVE_STRING_H
18#include <string.h>
19#endif
20#include <libxml/xmlmemory.h>
21#include <libxml/tree.h>
22#include <libxml/parser.h>
Daniel Veillard567e1b42001-08-01 15:53:47 +000023#include <libxml/parserInternals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000024#include <libxml/valid.h>
25#include <libxml/debugXML.h>
26#include <libxml/HTMLtree.h>
27#include <libxml/HTMLparser.h>
28#include <libxml/xmlerror.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000029#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000030
Daniel Veillard5e2dace2001-07-18 19:30:27 +000031/**
32 * xmlDebugDumpString:
33 * @output: the FILE * for the output
34 * @str: the string
35 *
36 * Dumps informations about the string, shorten it if necessary
37 */
38void
39xmlDebugDumpString(FILE * output, const xmlChar * str)
40{
Owen Taylor3473f882001-02-23 17:55:21 +000041 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000042
Owen Taylor3473f882001-02-23 17:55:21 +000043 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000044 fprintf(output, "(NULL)");
45 return;
Owen Taylor3473f882001-02-23 17:55:21 +000046 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000047 for (i = 0; i < 40; i++)
48 if (str[i] == 0)
49 return;
50 else if (IS_BLANK(str[i]))
51 fputc(' ', output);
52 else if (str[i] >= 0x80)
53 fprintf(output, "#%X", str[i]);
54 else
55 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000056 fprintf(output, "...");
57}
58
Daniel Veillard56a4cb82001-03-24 17:00:36 +000059static void
60xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000061 int i;
62 char shift[100];
63
64 for (i = 0;((i < depth) && (i < 25));i++)
65 shift[2 * i] = shift[2 * i + 1] = ' ';
66 shift[2 * i] = shift[2 * i + 1] = 0;
67
68 fprintf(output, shift);
69
70 if (dtd->type != XML_DTD_NODE) {
71 fprintf(output, "PBM: not a DTD\n");
72 return;
73 }
74 if (dtd->name != NULL)
75 fprintf(output, "DTD(%s)", dtd->name);
76 else
77 fprintf(output, "DTD");
78 if (dtd->ExternalID != NULL)
79 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
80 if (dtd->SystemID != NULL)
81 fprintf(output, ", SYSTEM %s", dtd->SystemID);
82 fprintf(output, "\n");
83 /*
84 * Do a bit of checking
85 */
86 if (dtd->parent == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000087 fprintf(output, "PBM: DTD has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +000088 if (dtd->doc == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000089 fprintf(output, "PBM: DTD has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +000090 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +000091 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +000092 if (dtd->prev == NULL) {
93 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +000094 fprintf(output, "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +000095 } else {
96 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000097 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +000098 }
99 if (dtd->next == NULL) {
100 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000101 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000102 } else {
103 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000104 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000105 }
106}
107
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000108static void
109xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000110 int i;
111 char shift[100];
112
113 for (i = 0;((i < depth) && (i < 25));i++)
114 shift[2 * i] = shift[2 * i + 1] = ' ';
115 shift[2 * i] = shift[2 * i + 1] = 0;
116
117 fprintf(output, shift);
118
119 if (attr->type != XML_ATTRIBUTE_DECL) {
120 fprintf(output, "PBM: not a Attr\n");
121 return;
122 }
123 if (attr->name != NULL)
124 fprintf(output, "ATTRDECL(%s)", attr->name);
125 else
126 fprintf(output, "PBM ATTRDECL noname!!!");
127 if (attr->elem != NULL)
128 fprintf(output, " for %s", attr->elem);
129 else
130 fprintf(output, " PBM noelem!!!");
131 switch (attr->atype) {
132 case XML_ATTRIBUTE_CDATA:
133 fprintf(output, " CDATA");
134 break;
135 case XML_ATTRIBUTE_ID:
136 fprintf(output, " ID");
137 break;
138 case XML_ATTRIBUTE_IDREF:
139 fprintf(output, " IDREF");
140 break;
141 case XML_ATTRIBUTE_IDREFS:
142 fprintf(output, " IDREFS");
143 break;
144 case XML_ATTRIBUTE_ENTITY:
145 fprintf(output, " ENTITY");
146 break;
147 case XML_ATTRIBUTE_ENTITIES:
148 fprintf(output, " ENTITIES");
149 break;
150 case XML_ATTRIBUTE_NMTOKEN:
151 fprintf(output, " NMTOKEN");
152 break;
153 case XML_ATTRIBUTE_NMTOKENS:
154 fprintf(output, " NMTOKENS");
155 break;
156 case XML_ATTRIBUTE_ENUMERATION:
157 fprintf(output, " ENUMERATION");
158 break;
159 case XML_ATTRIBUTE_NOTATION:
160 fprintf(output, " NOTATION ");
161 break;
162 }
163 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000164 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000165 xmlEnumerationPtr cur = attr->tree;
166
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000167 for (indx = 0;indx < 5; indx++) {
168 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000169 fprintf(output, "|%s", cur->name);
170 else
171 fprintf(output, " (%s", cur->name);
172 cur = cur->next;
173 if (cur == NULL) break;
174 }
175 if (cur == NULL)
176 fprintf(output, ")");
177 else
178 fprintf(output, "...)");
179 }
180 switch (attr->def) {
181 case XML_ATTRIBUTE_NONE:
182 break;
183 case XML_ATTRIBUTE_REQUIRED:
184 fprintf(output, " REQUIRED");
185 break;
186 case XML_ATTRIBUTE_IMPLIED:
187 fprintf(output, " IMPLIED");
188 break;
189 case XML_ATTRIBUTE_FIXED:
190 fprintf(output, " FIXED");
191 break;
192 }
193 if (attr->defaultValue != NULL) {
194 fprintf(output, "\"");
195 xmlDebugDumpString(output, attr->defaultValue);
196 fprintf(output, "\"");
197 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000198 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000199
200 /*
201 * Do a bit of checking
202 */
203 if (attr->parent == NULL)
204 fprintf(output, "PBM: Attr has no parent\n");
205 if (attr->doc == NULL)
206 fprintf(output, "PBM: Attr has no doc\n");
207 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
208 fprintf(output, "PBM: Attr doc differs from parent's one\n");
209 if (attr->prev == NULL) {
210 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
211 fprintf(output, "PBM: Attr has no prev and not first of list\n");
212 } else {
213 if (attr->prev->next != (xmlNodePtr) attr)
214 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
215 }
216 if (attr->next == NULL) {
217 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
218 fprintf(output, "PBM: Attr has no next and not last of list\n");
219 } else {
220 if (attr->next->prev != (xmlNodePtr) attr)
221 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
222 }
223}
224
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000225static void
226xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000227 int i;
228 char shift[100];
229
230 for (i = 0;((i < depth) && (i < 25));i++)
231 shift[2 * i] = shift[2 * i + 1] = ' ';
232 shift[2 * i] = shift[2 * i + 1] = 0;
233
234 fprintf(output, shift);
235
236 if (elem->type != XML_ELEMENT_DECL) {
237 fprintf(output, "PBM: not a Elem\n");
238 return;
239 }
240 if (elem->name != NULL) {
241 fprintf(output, "ELEMDECL(");
242 xmlDebugDumpString(output, elem->name);
243 fprintf(output, ")");
244 } else
245 fprintf(output, "PBM ELEMDECL noname!!!");
246 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000247 case XML_ELEMENT_TYPE_UNDEFINED:
248 fprintf(output, ", UNDEFINED");
249 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000250 case XML_ELEMENT_TYPE_EMPTY:
251 fprintf(output, ", EMPTY");
252 break;
253 case XML_ELEMENT_TYPE_ANY:
254 fprintf(output, ", ANY");
255 break;
256 case XML_ELEMENT_TYPE_MIXED:
257 fprintf(output, ", MIXED ");
258 break;
259 case XML_ELEMENT_TYPE_ELEMENT:
260 fprintf(output, ", MIXED ");
261 break;
262 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000263 if ((elem->type != XML_ELEMENT_NODE) &&
264 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000265 char buf[5001];
266
267 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000268 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000269 buf[5000] = 0;
270 fprintf(output, "%s", buf);
271 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000272 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000273
274 /*
275 * Do a bit of checking
276 */
277 if (elem->parent == NULL)
278 fprintf(output, "PBM: Elem has no parent\n");
279 if (elem->doc == NULL)
280 fprintf(output, "PBM: Elem has no doc\n");
281 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
282 fprintf(output, "PBM: Elem doc differs from parent's one\n");
283 if (elem->prev == NULL) {
284 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
285 fprintf(output, "PBM: Elem has no prev and not first of list\n");
286 } else {
287 if (elem->prev->next != (xmlNodePtr) elem)
288 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
289 }
290 if (elem->next == NULL) {
291 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
292 fprintf(output, "PBM: Elem has no next and not last of list\n");
293 } else {
294 if (elem->next->prev != (xmlNodePtr) elem)
295 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
296 }
297}
298
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000299static void
300xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000301 int i;
302 char shift[100];
303
304 for (i = 0;((i < depth) && (i < 25));i++)
305 shift[2 * i] = shift[2 * i + 1] = ' ';
306 shift[2 * i] = shift[2 * i + 1] = 0;
307
308 fprintf(output, shift);
309
310 if (ent->type != XML_ENTITY_DECL) {
311 fprintf(output, "PBM: not a Entity decl\n");
312 return;
313 }
314 if (ent->name != NULL) {
315 fprintf(output, "ENTITYDECL(");
316 xmlDebugDumpString(output, ent->name);
317 fprintf(output, ")");
318 } else
319 fprintf(output, "PBM ENTITYDECL noname!!!");
320 switch (ent->etype) {
321 case XML_INTERNAL_GENERAL_ENTITY:
322 fprintf(output, ", internal\n");
323 break;
324 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
325 fprintf(output, ", external parsed\n");
326 break;
327 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
328 fprintf(output, ", unparsed\n");
329 break;
330 case XML_INTERNAL_PARAMETER_ENTITY:
331 fprintf(output, ", parameter\n");
332 break;
333 case XML_EXTERNAL_PARAMETER_ENTITY:
334 fprintf(output, ", external parameter\n");
335 break;
336 case XML_INTERNAL_PREDEFINED_ENTITY:
337 fprintf(output, ", predefined\n");
338 break;
339 }
340 if (ent->ExternalID) {
341 fprintf(output, shift);
342 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
343 }
344 if (ent->SystemID) {
345 fprintf(output, shift);
346 fprintf(output, " SystemID=%s\n", ent->SystemID);
347 }
348 if (ent->URI != NULL) {
349 fprintf(output, shift);
350 fprintf(output, " URI=%s\n", ent->URI);
351 }
352 if (ent->content) {
353 fprintf(output, shift);
354 fprintf(output, " content=");
355 xmlDebugDumpString(output, ent->content);
356 fprintf(output, "\n");
357 }
358
359 /*
360 * Do a bit of checking
361 */
362 if (ent->parent == NULL)
363 fprintf(output, "PBM: Ent has no parent\n");
364 if (ent->doc == NULL)
365 fprintf(output, "PBM: Ent has no doc\n");
366 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
367 fprintf(output, "PBM: Ent doc differs from parent's one\n");
368 if (ent->prev == NULL) {
369 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
370 fprintf(output, "PBM: Ent has no prev and not first of list\n");
371 } else {
372 if (ent->prev->next != (xmlNodePtr) ent)
373 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
374 }
375 if (ent->next == NULL) {
376 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
377 fprintf(output, "PBM: Ent has no next and not last of list\n");
378 } else {
379 if (ent->next->prev != (xmlNodePtr) ent)
380 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
381 }
382}
383
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000384static void
385xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000386 int i;
387 char shift[100];
388
389 for (i = 0;((i < depth) && (i < 25));i++)
390 shift[2 * i] = shift[2 * i + 1] = ' ';
391 shift[2 * i] = shift[2 * i + 1] = 0;
392
393 fprintf(output, shift);
394 if (ns->type != XML_NAMESPACE_DECL) {
395 fprintf(output, "invalid namespace node %d\n", ns->type);
396 return;
397 }
398 if (ns->href == NULL) {
399 if (ns->prefix != NULL)
400 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
401 else
402 fprintf(output, "incomplete default namespace href=NULL\n");
403 } else {
404 if (ns->prefix != NULL)
405 fprintf(output, "namespace %s href=", ns->prefix);
406 else
407 fprintf(output, "default namespace href=");
408
409 xmlDebugDumpString(output, ns->href);
410 fprintf(output, "\n");
411 }
412}
413
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000414static void
415xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000416 while (ns != NULL) {
417 xmlDebugDumpNamespace(output, ns, depth);
418 ns = ns->next;
419 }
420}
421
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000422static void
423xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000424 int i;
425 char shift[100];
426
427 for (i = 0;((i < depth) && (i < 25));i++)
428 shift[2 * i] = shift[2 * i + 1] = ' ';
429 shift[2 * i] = shift[2 * i + 1] = 0;
430
431 fprintf(output, shift);
432 switch (ent->etype) {
433 case XML_INTERNAL_GENERAL_ENTITY:
434 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
435 break;
436 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
437 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
438 break;
439 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
440 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
441 break;
442 case XML_INTERNAL_PARAMETER_ENTITY:
443 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
444 break;
445 case XML_EXTERNAL_PARAMETER_ENTITY:
446 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
447 break;
448 default:
449 fprintf(output, "ENTITY_%d ! ", ent->etype);
450 }
451 fprintf(output, "%s\n", ent->name);
452 if (ent->ExternalID) {
453 fprintf(output, shift);
454 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
455 }
456 if (ent->SystemID) {
457 fprintf(output, shift);
458 fprintf(output, "SystemID=%s\n", ent->SystemID);
459 }
460 if (ent->URI) {
461 fprintf(output, shift);
462 fprintf(output, "URI=%s\n", ent->URI);
463 }
464 if (ent->content) {
465 fprintf(output, shift);
466 fprintf(output, "content=");
467 xmlDebugDumpString(output, ent->content);
468 fprintf(output, "\n");
469 }
470}
471
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000472/**
473 * xmlDebugDumpAttr:
474 * @output: the FILE * for the output
475 * @attr: the attribute
476 * @depth: the indentation level.
477 *
478 * Dumps debug information for the attribute
479 */
480void
481xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000482 int i;
483 char shift[100];
484
485 for (i = 0;((i < depth) && (i < 25));i++)
486 shift[2 * i] = shift[2 * i + 1] = ' ';
487 shift[2 * i] = shift[2 * i + 1] = 0;
488
489 fprintf(output, shift);
490
491 fprintf(output, "ATTRIBUTE ");
492 xmlDebugDumpString(output, attr->name);
493 fprintf(output, "\n");
494 if (attr->children != NULL)
495 xmlDebugDumpNodeList(output, attr->children, depth + 1);
496
497 /*
498 * Do a bit of checking
499 */
500 if (attr->parent == NULL)
501 fprintf(output, "PBM: Attr has no parent\n");
502 if (attr->doc == NULL)
503 fprintf(output, "PBM: Attr has no doc\n");
504 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
505 fprintf(output, "PBM: Attr doc differs from parent's one\n");
506 if (attr->prev == NULL) {
507 if ((attr->parent != NULL) && (attr->parent->properties != attr))
508 fprintf(output, "PBM: Attr has no prev and not first of list\n");
509 } else {
510 if (attr->prev->next != attr)
511 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
512 }
513 if (attr->next != NULL) {
514 if (attr->next->prev != attr)
515 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
516 }
517}
518
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000519/**
520 * xmlDebugDumpAttrList:
521 * @output: the FILE * for the output
522 * @attr: the attribute list
523 * @depth: the indentation level.
524 *
525 * Dumps debug information for the attribute list
526 */
527void
528xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
529{
Owen Taylor3473f882001-02-23 17:55:21 +0000530 while (attr != NULL) {
531 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000532 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000533 }
534}
535
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000536/**
537 * xmlDebugDumpOneNode:
538 * @output: the FILE * for the output
539 * @node: the node
540 * @depth: the indentation level.
541 *
542 * Dumps debug information for the element node, it is not recursive
543 */
544void
545xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
546{
Owen Taylor3473f882001-02-23 17:55:21 +0000547 int i;
548 char shift[100];
549
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000550 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000551 shift[2 * i] = shift[2 * i + 1] = ' ';
552 shift[2 * i] = shift[2 * i + 1] = 0;
553
554 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000555 case XML_ELEMENT_NODE:
556 fprintf(output, shift);
557 fprintf(output, "ELEMENT ");
558 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
559 xmlDebugDumpString(output, node->ns->prefix);
560 fprintf(output, ":");
561 }
562 xmlDebugDumpString(output, node->name);
563 fprintf(output, "\n");
564 break;
565 case XML_ATTRIBUTE_NODE:
566 fprintf(output, shift);
567 fprintf(output, "Error, ATTRIBUTE found here\n");
568 break;
569 case XML_TEXT_NODE:
570 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000571 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000572 fprintf(output, "TEXT no enc\n");
573 else
574 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000575 break;
576 case XML_CDATA_SECTION_NODE:
577 fprintf(output, shift);
578 fprintf(output, "CDATA_SECTION\n");
579 break;
580 case XML_ENTITY_REF_NODE:
581 fprintf(output, shift);
582 fprintf(output, "ENTITY_REF(%s)\n", node->name);
583 break;
584 case XML_ENTITY_NODE:
585 fprintf(output, shift);
586 fprintf(output, "ENTITY\n");
587 break;
588 case XML_PI_NODE:
589 fprintf(output, shift);
590 fprintf(output, "PI %s\n", node->name);
591 break;
592 case XML_COMMENT_NODE:
593 fprintf(output, shift);
594 fprintf(output, "COMMENT\n");
595 break;
596 case XML_DOCUMENT_NODE:
597 case XML_HTML_DOCUMENT_NODE:
598 fprintf(output, shift);
599 fprintf(output, "Error, DOCUMENT found here\n");
600 break;
601 case XML_DOCUMENT_TYPE_NODE:
602 fprintf(output, shift);
603 fprintf(output, "DOCUMENT_TYPE\n");
604 break;
605 case XML_DOCUMENT_FRAG_NODE:
606 fprintf(output, shift);
607 fprintf(output, "DOCUMENT_FRAG\n");
608 break;
609 case XML_NOTATION_NODE:
610 fprintf(output, shift);
611 fprintf(output, "NOTATION\n");
612 break;
613 case XML_DTD_NODE:
614 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
615 return;
616 case XML_ELEMENT_DECL:
617 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
618 return;
619 case XML_ATTRIBUTE_DECL:
620 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
621 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000622 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000623 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
624 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000625 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000626 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
627 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000628 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000629 fprintf(output, shift);
630 fprintf(output, "INCLUDE START\n");
631 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000632 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000633 fprintf(output, shift);
634 fprintf(output, "INCLUDE END\n");
635 return;
636 default:
637 fprintf(output, shift);
638 fprintf(output, "NODE_%d !!!\n", node->type);
639 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000640 }
641 if (node->doc == NULL) {
642 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000643 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000644 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000645 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000646 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
647 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000648 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000649 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000650 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
651 shift[2 * i] = shift[2 * i + 1] = ' ';
652 shift[2 * i + 2] = shift[2 * i + 3] = 0;
653 fprintf(output, shift);
654 fprintf(output, "content=");
655#ifndef XML_USE_BUFFER_CONTENT
656 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +0000657#else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000658 xmlDebugDumpString(output, xmlBufferContent(node->content));
Owen Taylor3473f882001-02-23 17:55:21 +0000659#endif
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000660 fprintf(output, "\n");
661 }
Owen Taylor3473f882001-02-23 17:55:21 +0000662 } else {
663 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000664
665 ent = xmlGetDocEntity(node->doc, node->name);
666 if (ent != NULL)
667 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000668 }
669 /*
670 * Do a bit of checking
671 */
672 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000673 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000674 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000675 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000676 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000677 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000678 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000679 if ((node->parent != NULL) && (node->parent->children != node))
680 fprintf(output,
681 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000682 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000683 if (node->prev->next != node)
684 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000685 }
686 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000687 if ((node->parent != NULL) && (node->parent->last != node))
688 fprintf(output,
689 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000690 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000691 if (node->next->prev != node)
692 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000693 }
694}
695
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000696/**
697 * xmlDebugDumpNode:
698 * @output: the FILE * for the output
699 * @node: the node
700 * @depth: the indentation level.
701 *
702 * Dumps debug information for the element node, it is recursive
703 */
704void
705xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
706{
Owen Taylor3473f882001-02-23 17:55:21 +0000707 xmlDebugDumpOneNode(output, node, depth);
708 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000709 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000710}
711
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000712/**
713 * xmlDebugDumpNodeList:
714 * @output: the FILE * for the output
715 * @node: the node list
716 * @depth: the indentation level.
717 *
718 * Dumps debug information for the list of element node, it is recursive
719 */
720void
721xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
722{
Owen Taylor3473f882001-02-23 17:55:21 +0000723 while (node != NULL) {
724 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000725 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000726 }
727}
728
729
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000730/**
731 * xmlDebugDumpDocumentHead:
732 * @output: the FILE * for the output
733 * @doc: the document
734 *
735 * Dumps debug information cncerning the document, not recursive
736 */
737void
738xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
739{
740 if (output == NULL)
741 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000742 if (doc == NULL) {
743 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000744 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000745 }
746
747 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000748 case XML_ELEMENT_NODE:
749 fprintf(output, "Error, ELEMENT found here ");
750 break;
751 case XML_ATTRIBUTE_NODE:
752 fprintf(output, "Error, ATTRIBUTE found here\n");
753 break;
754 case XML_TEXT_NODE:
755 fprintf(output, "Error, TEXT\n");
756 break;
757 case XML_CDATA_SECTION_NODE:
758 fprintf(output, "Error, CDATA_SECTION\n");
759 break;
760 case XML_ENTITY_REF_NODE:
761 fprintf(output, "Error, ENTITY_REF\n");
762 break;
763 case XML_ENTITY_NODE:
764 fprintf(output, "Error, ENTITY\n");
765 break;
766 case XML_PI_NODE:
767 fprintf(output, "Error, PI\n");
768 break;
769 case XML_COMMENT_NODE:
770 fprintf(output, "Error, COMMENT\n");
771 break;
772 case XML_DOCUMENT_NODE:
773 fprintf(output, "DOCUMENT\n");
774 break;
775 case XML_HTML_DOCUMENT_NODE:
776 fprintf(output, "HTML DOCUMENT\n");
777 break;
778 case XML_DOCUMENT_TYPE_NODE:
779 fprintf(output, "Error, DOCUMENT_TYPE\n");
780 break;
781 case XML_DOCUMENT_FRAG_NODE:
782 fprintf(output, "Error, DOCUMENT_FRAG\n");
783 break;
784 case XML_NOTATION_NODE:
785 fprintf(output, "Error, NOTATION\n");
786 break;
787 default:
788 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000789 }
790 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000791 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000792 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000793 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000794 }
795 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000796 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000797 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000798 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000799 }
800 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000801 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000802 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000803 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000804 }
805 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000806 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000807 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000808 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000809 }
810 if (doc->standalone)
811 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000812 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000813 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
814}
815
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000816/**
817 * xmlDebugDumpDocument:
818 * @output: the FILE * for the output
819 * @doc: the document
820 *
821 * Dumps debug information for the document, it's recursive
822 */
823void
824xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
825{
826 if (output == NULL)
827 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000828 if (doc == NULL) {
829 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000830 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000831 }
832 xmlDebugDumpDocumentHead(output, doc);
833 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000834 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000835 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000836}
Owen Taylor3473f882001-02-23 17:55:21 +0000837
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000838/**
839 * xmlDebugDumpDTD:
840 * @output: the FILE * for the output
841 * @dtd: the DTD
842 *
843 * Dumps debug information for the DTD
844 */
845void
846xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
847{
Owen Taylor3473f882001-02-23 17:55:21 +0000848 if (dtd == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000849 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000850 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000851 fprintf(output, "PBM: not a DTD\n");
852 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000853 }
854 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000855 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000856 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000857 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000858 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000859 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000860 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000861 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000862 fprintf(output, "\n");
863 /*
864 * Do a bit of checking
865 */
866 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000867 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000868 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000869 if ((dtd->parent != NULL)
870 && (dtd->parent->children != (xmlNodePtr) dtd))
871 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000872 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000873 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000874 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000875 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000876 }
877 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000878 if ((dtd->parent != NULL)
879 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000880 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000881 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000882 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000883 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000884 }
885 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000886 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000887 else
888 xmlDebugDumpNodeList(output, dtd->children, 1);
889}
890
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000891static void
892xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Owen Taylor3473f882001-02-23 17:55:21 +0000893 fprintf(output, "%s : ", cur->name);
894 switch (cur->etype) {
895 case XML_INTERNAL_GENERAL_ENTITY:
896 fprintf(output, "INTERNAL GENERAL, ");
897 break;
898 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
899 fprintf(output, "EXTERNAL PARSED, ");
900 break;
901 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
902 fprintf(output, "EXTERNAL UNPARSED, ");
903 break;
904 case XML_INTERNAL_PARAMETER_ENTITY:
905 fprintf(output, "INTERNAL PARAMETER, ");
906 break;
907 case XML_EXTERNAL_PARAMETER_ENTITY:
908 fprintf(output, "EXTERNAL PARAMETER, ");
909 break;
910 default:
911 fprintf(output, "UNKNOWN TYPE %d",
912 cur->etype);
913 }
914 if (cur->ExternalID != NULL)
915 fprintf(output, "ID \"%s\"", cur->ExternalID);
916 if (cur->SystemID != NULL)
917 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
918 if (cur->orig != NULL)
919 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000920 if ((cur->type != XML_ELEMENT_NODE) &&
921 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000922 fprintf(output, "\n content \"%s\"", cur->content);
923 fprintf(output, "\n");
924}
925
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000926/**
927 * xmlDebugDumpEntities:
928 * @output: the FILE * for the output
929 * @doc: the document
930 *
931 * Dumps debug information for all the entities in use by the document
932 */
933void
934xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
935{
936 if (output == NULL)
937 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000938 if (doc == NULL) {
939 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000940 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000941 }
942
943 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000944 case XML_ELEMENT_NODE:
945 fprintf(output, "Error, ELEMENT found here ");
946 break;
947 case XML_ATTRIBUTE_NODE:
948 fprintf(output, "Error, ATTRIBUTE found here\n");
949 break;
950 case XML_TEXT_NODE:
951 fprintf(output, "Error, TEXT\n");
952 break;
953 case XML_CDATA_SECTION_NODE:
954 fprintf(output, "Error, CDATA_SECTION\n");
955 break;
956 case XML_ENTITY_REF_NODE:
957 fprintf(output, "Error, ENTITY_REF\n");
958 break;
959 case XML_ENTITY_NODE:
960 fprintf(output, "Error, ENTITY\n");
961 break;
962 case XML_PI_NODE:
963 fprintf(output, "Error, PI\n");
964 break;
965 case XML_COMMENT_NODE:
966 fprintf(output, "Error, COMMENT\n");
967 break;
968 case XML_DOCUMENT_NODE:
969 fprintf(output, "DOCUMENT\n");
970 break;
971 case XML_HTML_DOCUMENT_NODE:
972 fprintf(output, "HTML DOCUMENT\n");
973 break;
974 case XML_DOCUMENT_TYPE_NODE:
975 fprintf(output, "Error, DOCUMENT_TYPE\n");
976 break;
977 case XML_DOCUMENT_FRAG_NODE:
978 fprintf(output, "Error, DOCUMENT_FRAG\n");
979 break;
980 case XML_NOTATION_NODE:
981 fprintf(output, "Error, NOTATION\n");
982 break;
983 default:
984 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000985 }
986 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000987 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
988 doc->intSubset->entities;
989
990 fprintf(output, "Entities in internal subset\n");
991 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
992 output);
Owen Taylor3473f882001-02-23 17:55:21 +0000993 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000994 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000995 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000996 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
997 doc->extSubset->entities;
998
999 fprintf(output, "Entities in external subset\n");
1000 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1001 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001002 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001003 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001004}
1005
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001006/**
1007 * xmlLsCountNode:
1008 * @node: the node to count
1009 *
1010 * Count the children of @node.
1011 *
1012 * Returns the number of children of @node.
1013 */
1014int
1015xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001016 int ret = 0;
1017 xmlNodePtr list = NULL;
1018
1019 switch (node->type) {
1020 case XML_ELEMENT_NODE:
1021 list = node->children;
1022 break;
1023 case XML_DOCUMENT_NODE:
1024 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001025#ifdef LIBXML_DOCB_ENABLED
1026 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001027#endif
1028 list = ((xmlDocPtr) node)->children;
1029 break;
1030 case XML_ATTRIBUTE_NODE:
1031 list = ((xmlAttrPtr) node)->children;
1032 break;
1033 case XML_TEXT_NODE:
1034 case XML_CDATA_SECTION_NODE:
1035 case XML_PI_NODE:
1036 case XML_COMMENT_NODE:
1037 if (node->content != NULL) {
1038#ifndef XML_USE_BUFFER_CONTENT
1039 ret = xmlStrlen(node->content);
1040#else
1041 ret = xmlBufferLength(node->content);
1042#endif
1043 }
1044 break;
1045 case XML_ENTITY_REF_NODE:
1046 case XML_DOCUMENT_TYPE_NODE:
1047 case XML_ENTITY_NODE:
1048 case XML_DOCUMENT_FRAG_NODE:
1049 case XML_NOTATION_NODE:
1050 case XML_DTD_NODE:
1051 case XML_ELEMENT_DECL:
1052 case XML_ATTRIBUTE_DECL:
1053 case XML_ENTITY_DECL:
1054 case XML_NAMESPACE_DECL:
1055 case XML_XINCLUDE_START:
1056 case XML_XINCLUDE_END:
1057 ret = 1;
1058 break;
1059 }
1060 for (;list != NULL;ret++)
1061 list = list->next;
1062 return(ret);
1063}
1064
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001065/**
1066 * xmlLsOneNode:
1067 * @output: the FILE * for the output
1068 * @node: the node to dump
1069 *
1070 * Dump to @output the type and name of @node.
1071 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001072void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001073xmlLsOneNode(FILE *output, xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001074 switch (node->type) {
1075 case XML_ELEMENT_NODE:
1076 fprintf(output, "-");
1077 break;
1078 case XML_ATTRIBUTE_NODE:
1079 fprintf(output, "a");
1080 break;
1081 case XML_TEXT_NODE:
1082 fprintf(output, "t");
1083 break;
1084 case XML_CDATA_SECTION_NODE:
1085 fprintf(output, "c");
1086 break;
1087 case XML_ENTITY_REF_NODE:
1088 fprintf(output, "e");
1089 break;
1090 case XML_ENTITY_NODE:
1091 fprintf(output, "E");
1092 break;
1093 case XML_PI_NODE:
1094 fprintf(output, "p");
1095 break;
1096 case XML_COMMENT_NODE:
1097 fprintf(output, "c");
1098 break;
1099 case XML_DOCUMENT_NODE:
1100 fprintf(output, "d");
1101 break;
1102 case XML_HTML_DOCUMENT_NODE:
1103 fprintf(output, "h");
1104 break;
1105 case XML_DOCUMENT_TYPE_NODE:
1106 fprintf(output, "T");
1107 break;
1108 case XML_DOCUMENT_FRAG_NODE:
1109 fprintf(output, "F");
1110 break;
1111 case XML_NOTATION_NODE:
1112 fprintf(output, "N");
1113 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001114 case XML_NAMESPACE_DECL:
1115 fprintf(output, "n");
1116 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001117 default:
1118 fprintf(output, "?");
1119 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001120 if (node->type != XML_NAMESPACE_DECL) {
1121 if (node->properties != NULL)
1122 fprintf(output, "a");
1123 else
1124 fprintf(output, "-");
1125 if (node->nsDef != NULL)
1126 fprintf(output, "n");
1127 else
1128 fprintf(output, "-");
1129 }
Owen Taylor3473f882001-02-23 17:55:21 +00001130
1131 fprintf(output, " %8d ", xmlLsCountNode(node));
1132
1133 switch (node->type) {
1134 case XML_ELEMENT_NODE:
1135 if (node->name != NULL)
1136 fprintf(output, "%s", node->name);
1137 break;
1138 case XML_ATTRIBUTE_NODE:
1139 if (node->name != NULL)
1140 fprintf(output, "%s", node->name);
1141 break;
1142 case XML_TEXT_NODE:
1143 if (node->content != NULL) {
1144#ifndef XML_USE_BUFFER_CONTENT
1145 xmlDebugDumpString(output, node->content);
1146#else
1147 xmlDebugDumpString(output, xmlBufferContent(node->content));
1148#endif
1149 }
1150 break;
1151 case XML_CDATA_SECTION_NODE:
1152 break;
1153 case XML_ENTITY_REF_NODE:
1154 if (node->name != NULL)
1155 fprintf(output, "%s", node->name);
1156 break;
1157 case XML_ENTITY_NODE:
1158 if (node->name != NULL)
1159 fprintf(output, "%s", node->name);
1160 break;
1161 case XML_PI_NODE:
1162 if (node->name != NULL)
1163 fprintf(output, "%s", node->name);
1164 break;
1165 case XML_COMMENT_NODE:
1166 break;
1167 case XML_DOCUMENT_NODE:
1168 break;
1169 case XML_HTML_DOCUMENT_NODE:
1170 break;
1171 case XML_DOCUMENT_TYPE_NODE:
1172 break;
1173 case XML_DOCUMENT_FRAG_NODE:
1174 break;
1175 case XML_NOTATION_NODE:
1176 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001177 case XML_NAMESPACE_DECL: {
1178 xmlNsPtr ns = (xmlNsPtr) node;
1179
1180 if (ns->prefix == NULL)
1181 fprintf(output, "default -> %s", ns->href);
1182 else
1183 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1184 break;
1185 }
Owen Taylor3473f882001-02-23 17:55:21 +00001186 default:
1187 if (node->name != NULL)
1188 fprintf(output, "%s", node->name);
1189 }
1190 fprintf(output, "\n");
1191}
1192
Daniel Veillard78d12092001-10-11 09:12:24 +00001193/**
1194 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001195 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001196 *
1197 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001198 *
1199 * Returns a pointer to either "True" or "False"
1200 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001201const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001202xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001203{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001204 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001205 return("True");
1206 else
1207 return("False");
1208}
1209
Owen Taylor3473f882001-02-23 17:55:21 +00001210/****************************************************************
1211 * *
1212 * The XML shell related functions *
1213 * *
1214 ****************************************************************/
1215
Daniel Veillard78d12092001-10-11 09:12:24 +00001216
1217
Owen Taylor3473f882001-02-23 17:55:21 +00001218/*
1219 * TODO: Improvement/cleanups for the XML shell
1220 * - allow to shell out an editor on a subpart
1221 * - cleanup function registrations (with help) and calling
1222 * - provide registration routines
1223 */
1224
1225/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001226 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001227 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001228 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001229 *
1230 * Print the xpath error to libxml default error channel
1231 */
1232void
1233xmlShellPrintXPathError(int errorType, const char *arg)
1234{
1235 const char *default_arg = "Result";
1236
1237 if (!arg)
1238 arg = default_arg;
1239
1240 switch (errorType) {
1241 case XPATH_UNDEFINED:
1242 xmlGenericError(xmlGenericErrorContext,
1243 "%s: no such node\n", arg);
1244 break;
1245
1246 case XPATH_BOOLEAN:
1247 xmlGenericError(xmlGenericErrorContext,
1248 "%s is a Boolean\n", arg);
1249 break;
1250 case XPATH_NUMBER:
1251 xmlGenericError(xmlGenericErrorContext,
1252 "%s is a number\n", arg);
1253 break;
1254 case XPATH_STRING:
1255 xmlGenericError(xmlGenericErrorContext,
1256 "%s is a string\n", arg);
1257 break;
1258 case XPATH_POINT:
1259 xmlGenericError(xmlGenericErrorContext,
1260 "%s is a point\n", arg);
1261 break;
1262 case XPATH_RANGE:
1263 xmlGenericError(xmlGenericErrorContext,
1264 "%s is a range\n", arg);
1265 break;
1266 case XPATH_LOCATIONSET:
1267 xmlGenericError(xmlGenericErrorContext,
1268 "%s is a range\n", arg);
1269 break;
1270 case XPATH_USERS:
1271 xmlGenericError(xmlGenericErrorContext,
1272 "%s is user-defined\n", arg);
1273 break;
1274 case XPATH_XSLT_TREE:
1275 xmlGenericError(xmlGenericErrorContext,
1276 "%s is an XSLT value tree\n", arg);
1277 break;
1278 }
1279 xmlGenericError(xmlGenericErrorContext,
1280 "Try casting the result string function (xpath builtin)\n",
1281 arg);
1282}
1283
1284
1285/**
1286 * xmlShellPrintNode:
1287 * @node : a non-null node to print to stdout
1288 *
1289 * Print node to stdout
1290 */
1291void
1292xmlShellPrintNode(xmlNodePtr node)
1293{
1294 if (!node)
1295 return;
1296
1297 if (node->type == XML_DOCUMENT_NODE)
1298 xmlDocDump(stdout, (xmlDocPtr) node);
1299 else if (node->type == XML_ATTRIBUTE_NODE)
1300 xmlDebugDumpAttrList(stdout, (xmlAttrPtr) node, 0);
1301 else
1302 xmlElemDump(stdout, node->doc, node);
1303
1304 fprintf(stdout, "\n");
1305}
1306
1307
1308/**
1309 * xmlShellPrintXPathResult:
Daniel Veillard9d06d302002-01-22 18:15:52 +00001310 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001311 *
1312 * Prints result to stdout
1313 */
1314void
1315xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1316{
1317 int i = 0;
1318
1319 if (list != NULL) {
1320 switch (list->type) {
1321 case XPATH_NODESET:{
1322 int indx;
1323
1324 if (list->nodesetval) {
1325 for (indx = 0; indx < list->nodesetval->nodeNr;
1326 indx++) {
1327 if (i > 0)
1328 fprintf(stderr, " -------\n");
1329 xmlShellPrintNode(list->nodesetval->
1330 nodeTab[indx]);
1331 }
1332 } else {
1333 xmlGenericError(xmlGenericErrorContext,
1334 "Empty node set\n");
1335 }
1336 break;
1337 }
1338 case XPATH_BOOLEAN:
1339 xmlGenericError(xmlGenericErrorContext,
1340 "Is a Boolean:%s\n",
1341 xmlBoolToText(list->boolval));
1342 break;
1343 case XPATH_NUMBER:
1344 xmlGenericError(xmlGenericErrorContext,
1345 "Is a number:%0g\n", list->floatval);
1346 break;
1347 case XPATH_STRING:
1348 xmlGenericError(xmlGenericErrorContext,
1349 "Is a string:%s\n", list->stringval);
1350 break;
1351
1352 default:
1353 xmlShellPrintXPathError(list->type, NULL);
1354 }
1355 }
1356}
1357
1358/**
Owen Taylor3473f882001-02-23 17:55:21 +00001359 * xmlShellList:
1360 * @ctxt: the shell context
1361 * @arg: unused
1362 * @node: a node
1363 * @node2: unused
1364 *
1365 * Implements the XML shell function "ls"
1366 * Does an Unix like listing of the given node (like a directory)
1367 *
1368 * Returns 0
1369 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001370int
1371xmlShellList(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1372 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1373 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1374{
Owen Taylor3473f882001-02-23 17:55:21 +00001375 xmlNodePtr cur;
1376
1377 if ((node->type == XML_DOCUMENT_NODE) ||
1378 (node->type == XML_HTML_DOCUMENT_NODE)) {
1379 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001380 } else if (node->type == XML_NAMESPACE_DECL) {
1381 xmlLsOneNode(stdout, node);
1382 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001383 } else if (node->children != NULL) {
1384 cur = node->children;
1385 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001386 xmlLsOneNode(stdout, node);
1387 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001388 }
1389 while (cur != NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001390 xmlLsOneNode(stdout, cur);
1391 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001392 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001393 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001394}
1395
1396/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001397 * xmlShellBase:
1398 * @ctxt: the shell context
1399 * @arg: unused
1400 * @node: a node
1401 * @node2: unused
1402 *
1403 * Implements the XML shell function "base"
1404 * dumps the current XML base of the node
1405 *
1406 * Returns 0
1407 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001408int
1409xmlShellBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1410 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1411 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1412{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001413 xmlChar *base;
1414
1415 base = xmlNodeGetBase(node->doc, node);
1416
1417 if (base == NULL) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001418 fprintf(stdout, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001419 } else {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001420 fprintf(stdout, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001421 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001422 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001423 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001424}
1425
1426/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001427 * xmlShellSetBase:
1428 * @ctxt: the shell context
1429 * @arg: the new base
1430 * @node: a node
1431 * @node2: unused
1432 *
1433 * Implements the XML shell function "setbase"
1434 * change the current XML base of the node
1435 *
1436 * Returns 0
1437 */
1438static int
1439xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1440 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1441 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1442{
1443 xmlNodeSetBase(node, (xmlChar*) arg);
1444 return (0);
1445}
1446
1447/**
Owen Taylor3473f882001-02-23 17:55:21 +00001448 * xmlShellDir:
1449 * @ctxt: the shell context
1450 * @arg: unused
1451 * @node: a node
1452 * @node2: unused
1453 *
1454 * Implements the XML shell function "dir"
1455 * dumps informations about the node (namespace, attributes, content).
1456 *
1457 * Returns 0
1458 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001459int
1460xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1461 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1462 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1463{
Owen Taylor3473f882001-02-23 17:55:21 +00001464 if ((node->type == XML_DOCUMENT_NODE) ||
1465 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001466 xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001467 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001468 xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001469 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001470 xmlDebugDumpOneNode(stdout, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001471 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001472 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001473}
1474
1475/**
1476 * xmlShellCat:
1477 * @ctxt: the shell context
1478 * @arg: unused
1479 * @node: a node
1480 * @node2: unused
1481 *
1482 * Implements the XML shell function "cat"
1483 * dumps the serialization node content (XML or HTML).
1484 *
1485 * Returns 0
1486 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001487int
1488xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1489 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1490{
Owen Taylor3473f882001-02-23 17:55:21 +00001491 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1492#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001493 if (node->type == XML_HTML_DOCUMENT_NODE)
1494 htmlDocDump(stdout, (htmlDocPtr) node);
1495 else
1496 htmlNodeDumpFile(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001497#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001498 if (node->type == XML_DOCUMENT_NODE)
1499 xmlDocDump(stdout, (xmlDocPtr) node);
1500 else
1501 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001502#endif /* LIBXML_HTML_ENABLED */
1503 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001504 if (node->type == XML_DOCUMENT_NODE)
1505 xmlDocDump(stdout, (xmlDocPtr) node);
1506 else
1507 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001508 }
Daniel Veillardcd337f02001-11-22 18:20:37 +00001509 fprintf(stdout, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001510 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001511}
1512
1513/**
1514 * xmlShellLoad:
1515 * @ctxt: the shell context
1516 * @filename: the file name
1517 * @node: unused
1518 * @node2: unused
1519 *
1520 * Implements the XML shell function "load"
1521 * loads a new document specified by the filename
1522 *
1523 * Returns 0 or -1 if loading failed
1524 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001525int
1526xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1527 xmlNodePtr node ATTRIBUTE_UNUSED,
1528 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1529{
Owen Taylor3473f882001-02-23 17:55:21 +00001530 xmlDocPtr doc;
1531 int html = 0;
1532
1533 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001534 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001535
1536 if (html) {
1537#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001538 doc = htmlParseFile(filename, NULL);
1539#else
Daniel Veillardcd337f02001-11-22 18:20:37 +00001540 fprintf(stdout, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001541 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001542#endif /* LIBXML_HTML_ENABLED */
1543 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001544 doc = xmlParseFile(filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001545 }
1546 if (doc != NULL) {
1547 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001548 xmlFreeDoc(ctxt->doc);
1549 }
1550 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001551#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001552 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001553#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001554 xmlFree(ctxt->filename);
1555 ctxt->doc = doc;
1556 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001557#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001558 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001559#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001560 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001561 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001562 return (-1);
1563 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001564}
1565
1566/**
1567 * xmlShellWrite:
1568 * @ctxt: the shell context
1569 * @filename: the file name
1570 * @node: a node in the tree
1571 * @node2: unused
1572 *
1573 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001574 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001575 * of the subtree under the @node specified
1576 *
1577 * Returns 0 or -1 in case of error
1578 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001579int
Owen Taylor3473f882001-02-23 17:55:21 +00001580xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001581 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1582{
Owen Taylor3473f882001-02-23 17:55:21 +00001583 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001584 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001585 if ((filename == NULL) || (filename[0] == 0)) {
1586 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001587 "Write command requires a filename argument\n");
1588 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001589 }
1590#ifdef W_OK
1591 if (access((char *) filename, W_OK)) {
1592 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001593 "Cannot write to %s\n", filename);
1594 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001595 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001596#endif
1597 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001598 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001599 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1600 xmlGenericError(xmlGenericErrorContext,
1601 "Failed to write to %s\n", filename);
1602 return (-1);
1603 }
1604 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001605 case XML_HTML_DOCUMENT_NODE:
1606#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001607 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1608 xmlGenericError(xmlGenericErrorContext,
1609 "Failed to write to %s\n", filename);
1610 return (-1);
1611 }
Owen Taylor3473f882001-02-23 17:55:21 +00001612#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001613 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1614 xmlGenericError(xmlGenericErrorContext,
1615 "Failed to write to %s\n", filename);
1616 return (-1);
1617 }
Owen Taylor3473f882001-02-23 17:55:21 +00001618#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001619 break;
1620 default:{
1621 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001622
Daniel Veillard78d12092001-10-11 09:12:24 +00001623 f = fopen((char *) filename, "w");
1624 if (f == NULL) {
1625 xmlGenericError(xmlGenericErrorContext,
1626 "Failed to write to %s\n", filename);
1627 return (-1);
1628 }
1629 xmlElemDump(f, ctxt->doc, node);
1630 fclose(f);
1631 }
Owen Taylor3473f882001-02-23 17:55:21 +00001632 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001633 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001634}
1635
1636/**
1637 * xmlShellSave:
1638 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001639 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001640 * @node: unused
1641 * @node2: unused
1642 *
1643 * Implements the XML shell function "save"
1644 * Write the current document to the filename, or it's original name
1645 *
1646 * Returns 0 or -1 in case of error
1647 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001648int
1649xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1650 xmlNodePtr node ATTRIBUTE_UNUSED,
1651 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1652{
Owen Taylor3473f882001-02-23 17:55:21 +00001653 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001654 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001655 if ((filename == NULL) || (filename[0] == 0))
1656 filename = ctxt->filename;
1657#ifdef W_OK
1658 if (access((char *) filename, W_OK)) {
1659 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001660 "Cannot save to %s\n", filename);
1661 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001662 }
1663#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001664 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001665 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001666 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1667 xmlGenericError(xmlGenericErrorContext,
1668 "Failed to save to %s\n", filename);
1669 }
1670 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001671 case XML_HTML_DOCUMENT_NODE:
1672#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001673 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1674 xmlGenericError(xmlGenericErrorContext,
1675 "Failed to save to %s\n", filename);
1676 }
Owen Taylor3473f882001-02-23 17:55:21 +00001677#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001678 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1679 xmlGenericError(xmlGenericErrorContext,
1680 "Failed to save to %s\n", filename);
1681 }
Owen Taylor3473f882001-02-23 17:55:21 +00001682#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001683 break;
1684 default:
1685 xmlGenericError(xmlGenericErrorContext,
1686 "To save to subparts of a document use the 'write' command\n");
1687 return (-1);
1688
Owen Taylor3473f882001-02-23 17:55:21 +00001689 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001690 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001691}
1692
1693/**
1694 * xmlShellValidate:
1695 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001696 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001697 * @node: unused
1698 * @node2: unused
1699 *
1700 * Implements the XML shell function "validate"
1701 * Validate the document, if a DTD path is provided, then the validation
1702 * is done against the given DTD.
1703 *
1704 * Returns 0 or -1 in case of error
1705 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001706int
1707xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1708 xmlNodePtr node ATTRIBUTE_UNUSED,
1709 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1710{
Owen Taylor3473f882001-02-23 17:55:21 +00001711 xmlValidCtxt vctxt;
1712 int res = -1;
1713
1714 vctxt.userData = stderr;
1715 vctxt.error = (xmlValidityErrorFunc) fprintf;
1716 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1717
1718 if ((dtd == NULL) || (dtd[0] == 0)) {
1719 res = xmlValidateDocument(&vctxt, ctxt->doc);
1720 } else {
1721 xmlDtdPtr subset;
1722
Daniel Veillard78d12092001-10-11 09:12:24 +00001723 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1724 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001725 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1726
Daniel Veillard78d12092001-10-11 09:12:24 +00001727 xmlFreeDtd(subset);
1728 }
Owen Taylor3473f882001-02-23 17:55:21 +00001729 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001730 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00001731}
1732
1733/**
1734 * xmlShellDu:
1735 * @ctxt: the shell context
1736 * @arg: unused
1737 * @tree: a node defining a subtree
1738 * @node2: unused
1739 *
1740 * Implements the XML shell function "du"
1741 * show the structure of the subtree under node @tree
1742 * If @tree is null, the command works on the current node.
1743 *
1744 * Returns 0 or -1 in case of error
1745 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001746int
1747xmlShellDu(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1748 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1749 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1750{
Owen Taylor3473f882001-02-23 17:55:21 +00001751 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00001752 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00001753
Daniel Veillard78d12092001-10-11 09:12:24 +00001754 if (tree == NULL)
1755 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001756 node = tree;
1757 while (node != NULL) {
1758 if ((node->type == XML_DOCUMENT_NODE) ||
1759 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001760 fprintf(stdout, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001761 } else if (node->type == XML_ELEMENT_NODE) {
1762 for (i = 0; i < indent; i++)
Daniel Veillardcd337f02001-11-22 18:20:37 +00001763 fprintf(stdout, " ");
1764 fprintf(stdout, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00001765 } else {
1766 }
Owen Taylor3473f882001-02-23 17:55:21 +00001767
Daniel Veillard78d12092001-10-11 09:12:24 +00001768 /*
1769 * Browse the full subtree, deep first
1770 */
Owen Taylor3473f882001-02-23 17:55:21 +00001771
1772 if ((node->type == XML_DOCUMENT_NODE) ||
1773 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001774 node = ((xmlDocPtr) node)->children;
1775 } else if ((node->children != NULL)
1776 && (node->type != XML_ENTITY_REF_NODE)) {
1777 /* deep first */
1778 node = node->children;
1779 indent++;
1780 } else if ((node != tree) && (node->next != NULL)) {
1781 /* then siblings */
1782 node = node->next;
1783 } else if (node != tree) {
1784 /* go up to parents->next if needed */
1785 while (node != tree) {
1786 if (node->parent != NULL) {
1787 node = node->parent;
1788 indent--;
1789 }
1790 if ((node != tree) && (node->next != NULL)) {
1791 node = node->next;
1792 break;
1793 }
1794 if (node->parent == NULL) {
1795 node = NULL;
1796 break;
1797 }
1798 if (node == tree) {
1799 node = NULL;
1800 break;
1801 }
1802 }
1803 /* exit condition */
1804 if (node == tree)
1805 node = NULL;
1806 } else
1807 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001808 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001809 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001810}
1811
1812/**
1813 * xmlShellPwd:
1814 * @ctxt: the shell context
1815 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00001816 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00001817 * @node2: unused
1818 *
1819 * Implements the XML shell function "pwd"
1820 * Show the full path from the root to the node, if needed building
1821 * thumblers when similar elements exists at a given ancestor level.
1822 * The output is compatible with XPath commands.
1823 *
1824 * Returns 0 or -1 in case of error
1825 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001826int
1827xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
1828 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1829{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001830 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00001831
Daniel Veillard78d12092001-10-11 09:12:24 +00001832 if (node == NULL)
1833 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001834
Daniel Veillardc6e013a2001-11-10 10:08:57 +00001835 path = xmlGetNodePath(node);
1836 if (path == NULL)
1837 return (-1);
1838
1839 /*
1840 * This test prevents buffer overflow, because this routine
1841 * is only called by xmlShell, in which the second argument is
1842 * 500 chars long.
1843 * It is a dirty hack before a cleaner solution is found.
1844 * Documentation should mention that the second argument must
1845 * be at least 500 chars long, and could be stripped if too long.
1846 */
1847 snprintf(buffer, 499, "%s", path);
1848 buffer[499] = '0';
1849 xmlFree(path);
1850
Daniel Veillard78d12092001-10-11 09:12:24 +00001851 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001852}
1853
1854/**
1855 * xmlShell
1856 * @doc: the initial document
1857 * @filename: the output buffer
1858 * @input: the line reading function
1859 * @output: the output FILE*
1860 *
1861 * Implements the XML shell
1862 * This allow to load, validate, view, modify and save a document
1863 * using a environment similar to a UNIX commandline.
1864 */
1865void
1866xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00001867 FILE * output)
1868{
Owen Taylor3473f882001-02-23 17:55:21 +00001869 char prompt[500] = "/ > ";
1870 char *cmdline = NULL, *cur;
1871 int nbargs;
1872 char command[100];
1873 char arg[400];
1874 int i;
1875 xmlShellCtxtPtr ctxt;
1876 xmlXPathObjectPtr list;
1877
1878 if (doc == NULL)
1879 return;
1880 if (filename == NULL)
1881 return;
1882 if (input == NULL)
1883 return;
1884 if (output == NULL)
1885 return;
1886 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00001887 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00001888 return;
1889 ctxt->loaded = 0;
1890 ctxt->doc = doc;
1891 ctxt->input = input;
1892 ctxt->output = output;
1893 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00001894 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001895
1896#ifdef LIBXML_XPATH_ENABLED
1897 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1898 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001899 xmlFree(ctxt);
1900 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001901 }
1902#endif /* LIBXML_XPATH_ENABLED */
1903 while (1) {
1904 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Daniel Veillard78d12092001-10-11 09:12:24 +00001905 sprintf(prompt, "%s > ", "/");
1906 else if (ctxt->node->name)
1907 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001908 else
Daniel Veillard78d12092001-10-11 09:12:24 +00001909 sprintf(prompt, "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00001910 prompt[sizeof(prompt) - 1] = 0;
1911
Daniel Veillard78d12092001-10-11 09:12:24 +00001912 /*
1913 * Get a new command line
1914 */
Owen Taylor3473f882001-02-23 17:55:21 +00001915 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00001916 if (cmdline == NULL)
1917 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001918
Daniel Veillard78d12092001-10-11 09:12:24 +00001919 /*
1920 * Parse the command itself
1921 */
1922 cur = cmdline;
1923 nbargs = 0;
1924 while ((*cur == ' ') || (*cur == '\t'))
1925 cur++;
1926 i = 0;
1927 while ((*cur != ' ') && (*cur != '\t') &&
1928 (*cur != '\n') && (*cur != '\r')) {
1929 if (*cur == 0)
1930 break;
1931 command[i++] = *cur++;
1932 }
1933 command[i] = 0;
1934 if (i == 0)
1935 continue;
1936 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00001937
Daniel Veillard78d12092001-10-11 09:12:24 +00001938 /*
1939 * Parse the argument
1940 */
1941 while ((*cur == ' ') || (*cur == '\t'))
1942 cur++;
1943 i = 0;
1944 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
1945 if (*cur == 0)
1946 break;
1947 arg[i++] = *cur++;
1948 }
1949 arg[i] = 0;
1950 if (i != 0)
1951 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00001952
Daniel Veillard78d12092001-10-11 09:12:24 +00001953 /*
1954 * start interpreting the command
1955 */
Owen Taylor3473f882001-02-23 17:55:21 +00001956 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00001957 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001958 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00001959 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001960 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00001961 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00001962 if (!strcmp(command, "help")) {
Daniel Veillardcd337f02001-11-22 18:20:37 +00001963 fprintf(stdout, "\tbase display XML base of the node\n");
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001964 fprintf(stdout, "\tsetbase URI change the XML base of the node\n");
Daniel Veillardcd337f02001-11-22 18:20:37 +00001965 fprintf(stdout, "\tbye leave shell\n");
1966 fprintf(stdout, "\tcat [node] display node or current node\n");
1967 fprintf(stdout, "\tcd [path] change directory to path or to root\n");
1968 fprintf(stdout, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
1969 fprintf(stdout, "\tdu [path] show the structure of the subtree under path or the current node\n");
1970 fprintf(stdout, "\texit leave shell\n");
1971 fprintf(stdout, "\thelp display this help\n");
1972 fprintf(stdout, "\tfree display memory usage\n");
1973 fprintf(stdout, "\tload [name] load a new document with name\n");
1974 fprintf(stdout, "\tls [path] list contents of path or the current directory\n");
1975 fprintf(stdout, "\tpwd display current working directory\n");
1976 fprintf(stdout, "\tquit leave shell\n");
1977 fprintf(stdout, "\tsave [name] save this document to name or the original name\n");
1978 fprintf(stdout, "\tvalidate check the document for errors\n");
1979 fprintf(stdout, "\twrite [name] write the current node to the filename\n");
Daniel Veillard5004f422001-11-08 13:53:05 +00001980 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001981 xmlShellValidate(ctxt, arg, NULL, NULL);
1982 } else if (!strcmp(command, "load")) {
1983 xmlShellLoad(ctxt, arg, NULL, NULL);
1984 } else if (!strcmp(command, "save")) {
1985 xmlShellSave(ctxt, arg, NULL, NULL);
1986 } else if (!strcmp(command, "write")) {
1987 xmlShellWrite(ctxt, arg, NULL, NULL);
1988 } else if (!strcmp(command, "free")) {
1989 if (arg[0] == 0) {
1990 xmlMemShow(stdout, 0);
1991 } else {
1992 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00001993
Daniel Veillard78d12092001-10-11 09:12:24 +00001994 sscanf(arg, "%d", &len);
1995 xmlMemShow(stdout, len);
1996 }
1997 } else if (!strcmp(command, "pwd")) {
1998 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00001999
Daniel Veillard78d12092001-10-11 09:12:24 +00002000 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillardcd337f02001-11-22 18:20:37 +00002001 fprintf(stdout, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002002 } else if (!strcmp(command, "du")) {
2003 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2004 } else if (!strcmp(command, "base")) {
2005 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002006 } else if (!strcmp(command, "setbase")) {
2007 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002008 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2009 int dir = (!strcmp(command, "dir"));
2010
2011 if (arg[0] == 0) {
2012 if (dir)
2013 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2014 else
2015 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2016 } else {
2017 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002018#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002019 ctxt->pctxt->node = ctxt->node;
2020 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2021#else
2022 list = NULL;
2023#endif /* LIBXML_XPATH_ENABLED */
2024 if (list != NULL) {
2025 switch (list->type) {
2026 case XPATH_UNDEFINED:
2027 xmlGenericError(xmlGenericErrorContext,
2028 "%s: no such node\n", arg);
2029 break;
2030 case XPATH_NODESET:{
2031 int indx;
2032
Daniel Veillarda6825e82001-11-07 13:33:59 +00002033 if (list->nodesetval == NULL)
2034 break;
2035
Daniel Veillard78d12092001-10-11 09:12:24 +00002036 for (indx = 0;
2037 indx < list->nodesetval->nodeNr;
2038 indx++) {
2039 if (dir)
2040 xmlShellDir(ctxt, NULL,
2041 list->nodesetval->
2042 nodeTab[indx], NULL);
2043 else
2044 xmlShellList(ctxt, NULL,
2045 list->nodesetval->
2046 nodeTab[indx], NULL);
2047 }
2048 break;
2049 }
2050 case XPATH_BOOLEAN:
2051 xmlGenericError(xmlGenericErrorContext,
2052 "%s is a Boolean\n", arg);
2053 break;
2054 case XPATH_NUMBER:
2055 xmlGenericError(xmlGenericErrorContext,
2056 "%s is a number\n", arg);
2057 break;
2058 case XPATH_STRING:
2059 xmlGenericError(xmlGenericErrorContext,
2060 "%s is a string\n", arg);
2061 break;
2062 case XPATH_POINT:
2063 xmlGenericError(xmlGenericErrorContext,
2064 "%s is a point\n", arg);
2065 break;
2066 case XPATH_RANGE:
2067 xmlGenericError(xmlGenericErrorContext,
2068 "%s is a range\n", arg);
2069 break;
2070 case XPATH_LOCATIONSET:
2071 xmlGenericError(xmlGenericErrorContext,
2072 "%s is a range\n", arg);
2073 break;
2074 case XPATH_USERS:
2075 xmlGenericError(xmlGenericErrorContext,
2076 "%s is user-defined\n", arg);
2077 break;
2078 case XPATH_XSLT_TREE:
2079 xmlGenericError(xmlGenericErrorContext,
2080 "%s is an XSLT value tree\n",
2081 arg);
2082 break;
2083 }
2084#ifdef LIBXML_XPATH_ENABLED
2085 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002086#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002087 } else {
2088 xmlGenericError(xmlGenericErrorContext,
2089 "%s: no such node\n", arg);
2090 }
2091 ctxt->pctxt->node = NULL;
2092 }
2093 } else if (!strcmp(command, "cd")) {
2094 if (arg[0] == 0) {
2095 ctxt->node = (xmlNodePtr) ctxt->doc;
2096 } else {
2097#ifdef LIBXML_XPATH_ENABLED
2098 ctxt->pctxt->node = ctxt->node;
2099 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2100#else
2101 list = NULL;
2102#endif /* LIBXML_XPATH_ENABLED */
2103 if (list != NULL) {
2104 switch (list->type) {
2105 case XPATH_UNDEFINED:
2106 xmlGenericError(xmlGenericErrorContext,
2107 "%s: no such node\n", arg);
2108 break;
2109 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002110 if (list->nodesetval != NULL) {
2111 if (list->nodesetval->nodeNr == 1) {
2112 ctxt->node = list->nodesetval->nodeTab[0];
2113 } else
2114 xmlGenericError(xmlGenericErrorContext,
2115 "%s is a %d Node Set\n",
2116 arg,
2117 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002118 } else
2119 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002120 "%s is an empty Node Set\n",
2121 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002122 break;
2123 case XPATH_BOOLEAN:
2124 xmlGenericError(xmlGenericErrorContext,
2125 "%s is a Boolean\n", arg);
2126 break;
2127 case XPATH_NUMBER:
2128 xmlGenericError(xmlGenericErrorContext,
2129 "%s is a number\n", arg);
2130 break;
2131 case XPATH_STRING:
2132 xmlGenericError(xmlGenericErrorContext,
2133 "%s is a string\n", arg);
2134 break;
2135 case XPATH_POINT:
2136 xmlGenericError(xmlGenericErrorContext,
2137 "%s is a point\n", arg);
2138 break;
2139 case XPATH_RANGE:
2140 xmlGenericError(xmlGenericErrorContext,
2141 "%s is a range\n", arg);
2142 break;
2143 case XPATH_LOCATIONSET:
2144 xmlGenericError(xmlGenericErrorContext,
2145 "%s is a range\n", arg);
2146 break;
2147 case XPATH_USERS:
2148 xmlGenericError(xmlGenericErrorContext,
2149 "%s is user-defined\n", arg);
2150 break;
2151 case XPATH_XSLT_TREE:
2152 xmlGenericError(xmlGenericErrorContext,
2153 "%s is an XSLT value tree\n",
2154 arg);
2155 break;
2156 }
2157#ifdef LIBXML_XPATH_ENABLED
2158 xmlXPathFreeObject(list);
2159#endif
2160 } else {
2161 xmlGenericError(xmlGenericErrorContext,
2162 "%s: no such node\n", arg);
2163 }
2164 ctxt->pctxt->node = NULL;
2165 }
2166 } else if (!strcmp(command, "cat")) {
2167 if (arg[0] == 0) {
2168 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2169 } else {
2170 ctxt->pctxt->node = ctxt->node;
2171#ifdef LIBXML_XPATH_ENABLED
2172 ctxt->pctxt->node = ctxt->node;
2173 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2174#else
2175 list = NULL;
2176#endif /* LIBXML_XPATH_ENABLED */
2177 if (list != NULL) {
2178 switch (list->type) {
2179 case XPATH_UNDEFINED:
2180 xmlGenericError(xmlGenericErrorContext,
2181 "%s: no such node\n", arg);
2182 break;
2183 case XPATH_NODESET:{
2184 int indx;
2185
Daniel Veillarda6825e82001-11-07 13:33:59 +00002186 if (list->nodesetval == NULL)
2187 break;
2188
Daniel Veillard78d12092001-10-11 09:12:24 +00002189 for (indx = 0;
2190 indx < list->nodesetval->nodeNr;
2191 indx++) {
2192 if (i > 0)
Daniel Veillardcd337f02001-11-22 18:20:37 +00002193 fprintf(stdout, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002194 xmlShellCat(ctxt, NULL,
2195 list->nodesetval->
2196 nodeTab[indx], NULL);
2197 }
2198 break;
2199 }
2200 case XPATH_BOOLEAN:
2201 xmlGenericError(xmlGenericErrorContext,
2202 "%s is a Boolean\n", arg);
2203 break;
2204 case XPATH_NUMBER:
2205 xmlGenericError(xmlGenericErrorContext,
2206 "%s is a number\n", arg);
2207 break;
2208 case XPATH_STRING:
2209 xmlGenericError(xmlGenericErrorContext,
2210 "%s is a string\n", arg);
2211 break;
2212 case XPATH_POINT:
2213 xmlGenericError(xmlGenericErrorContext,
2214 "%s is a point\n", arg);
2215 break;
2216 case XPATH_RANGE:
2217 xmlGenericError(xmlGenericErrorContext,
2218 "%s is a range\n", arg);
2219 break;
2220 case XPATH_LOCATIONSET:
2221 xmlGenericError(xmlGenericErrorContext,
2222 "%s is a range\n", arg);
2223 break;
2224 case XPATH_USERS:
2225 xmlGenericError(xmlGenericErrorContext,
2226 "%s is user-defined\n", arg);
2227 break;
2228 case XPATH_XSLT_TREE:
2229 xmlGenericError(xmlGenericErrorContext,
2230 "%s is an XSLT value tree\n",
2231 arg);
2232 break;
2233 }
2234#ifdef LIBXML_XPATH_ENABLED
2235 xmlXPathFreeObject(list);
2236#endif
2237 } else {
2238 xmlGenericError(xmlGenericErrorContext,
2239 "%s: no such node\n", arg);
2240 }
2241 ctxt->pctxt->node = NULL;
2242 }
2243 } else {
2244 xmlGenericError(xmlGenericErrorContext,
2245 "Unknown command %s\n", command);
2246 }
2247 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002248 }
2249#ifdef LIBXML_XPATH_ENABLED
2250 xmlXPathFreeContext(ctxt->pctxt);
2251#endif /* LIBXML_XPATH_ENABLED */
2252 if (ctxt->loaded) {
2253 xmlFreeDoc(ctxt->doc);
2254 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002255 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002256 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002257 xmlFree(ctxt);
2258 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002259 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002260}
2261
2262#endif /* LIBXML_DEBUG_ENABLED */