blob: 512a366e59fc57820df4a4614e81f2afab00289e [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>
23#include <libxml/valid.h>
24#include <libxml/debugXML.h>
25#include <libxml/HTMLtree.h>
26#include <libxml/HTMLparser.h>
27#include <libxml/xmlerror.h>
28
29#define IS_BLANK(c) \
30 (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
31
32void xmlDebugDumpString(FILE *output, const xmlChar *str) {
33 int i;
34 if (str == NULL) {
35 fprintf(output, "(NULL)");
36 return;
37 }
38 for (i = 0;i < 40;i++)
39 if (str[i] == 0) return;
40 else if (IS_BLANK(str[i])) fputc(' ', output);
41 else if (str[i] >= 0x80)
42 fprintf(output, "#%X", str[i]);
43 else fputc(str[i], output);
44 fprintf(output, "...");
45}
46
Daniel Veillard56a4cb82001-03-24 17:00:36 +000047static void
48xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000049 int i;
50 char shift[100];
51
52 for (i = 0;((i < depth) && (i < 25));i++)
53 shift[2 * i] = shift[2 * i + 1] = ' ';
54 shift[2 * i] = shift[2 * i + 1] = 0;
55
56 fprintf(output, shift);
57
58 if (dtd->type != XML_DTD_NODE) {
59 fprintf(output, "PBM: not a DTD\n");
60 return;
61 }
62 if (dtd->name != NULL)
63 fprintf(output, "DTD(%s)", dtd->name);
64 else
65 fprintf(output, "DTD");
66 if (dtd->ExternalID != NULL)
67 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
68 if (dtd->SystemID != NULL)
69 fprintf(output, ", SYSTEM %s", dtd->SystemID);
70 fprintf(output, "\n");
71 /*
72 * Do a bit of checking
73 */
74 if (dtd->parent == NULL)
75 fprintf(output, "PBM: Dtd has no parent\n");
76 if (dtd->doc == NULL)
77 fprintf(output, "PBM: Dtd has no doc\n");
78 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
79 fprintf(output, "PBM: Dtd doc differs from parent's one\n");
80 if (dtd->prev == NULL) {
81 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
82 fprintf(output, "PBM: Dtd has no prev and not first of list\n");
83 } else {
84 if (dtd->prev->next != (xmlNodePtr) dtd)
85 fprintf(output, "PBM: Dtd prev->next : back link wrong\n");
86 }
87 if (dtd->next == NULL) {
88 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
89 fprintf(output, "PBM: Dtd has no next and not last of list\n");
90 } else {
91 if (dtd->next->prev != (xmlNodePtr) dtd)
92 fprintf(output, "PBM: Dtd next->prev : forward link wrong\n");
93 }
94}
95
Daniel Veillard56a4cb82001-03-24 17:00:36 +000096static void
97xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000098 int i;
99 char shift[100];
100
101 for (i = 0;((i < depth) && (i < 25));i++)
102 shift[2 * i] = shift[2 * i + 1] = ' ';
103 shift[2 * i] = shift[2 * i + 1] = 0;
104
105 fprintf(output, shift);
106
107 if (attr->type != XML_ATTRIBUTE_DECL) {
108 fprintf(output, "PBM: not a Attr\n");
109 return;
110 }
111 if (attr->name != NULL)
112 fprintf(output, "ATTRDECL(%s)", attr->name);
113 else
114 fprintf(output, "PBM ATTRDECL noname!!!");
115 if (attr->elem != NULL)
116 fprintf(output, " for %s", attr->elem);
117 else
118 fprintf(output, " PBM noelem!!!");
119 switch (attr->atype) {
120 case XML_ATTRIBUTE_CDATA:
121 fprintf(output, " CDATA");
122 break;
123 case XML_ATTRIBUTE_ID:
124 fprintf(output, " ID");
125 break;
126 case XML_ATTRIBUTE_IDREF:
127 fprintf(output, " IDREF");
128 break;
129 case XML_ATTRIBUTE_IDREFS:
130 fprintf(output, " IDREFS");
131 break;
132 case XML_ATTRIBUTE_ENTITY:
133 fprintf(output, " ENTITY");
134 break;
135 case XML_ATTRIBUTE_ENTITIES:
136 fprintf(output, " ENTITIES");
137 break;
138 case XML_ATTRIBUTE_NMTOKEN:
139 fprintf(output, " NMTOKEN");
140 break;
141 case XML_ATTRIBUTE_NMTOKENS:
142 fprintf(output, " NMTOKENS");
143 break;
144 case XML_ATTRIBUTE_ENUMERATION:
145 fprintf(output, " ENUMERATION");
146 break;
147 case XML_ATTRIBUTE_NOTATION:
148 fprintf(output, " NOTATION ");
149 break;
150 }
151 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000152 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000153 xmlEnumerationPtr cur = attr->tree;
154
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000155 for (indx = 0;indx < 5; indx++) {
156 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000157 fprintf(output, "|%s", cur->name);
158 else
159 fprintf(output, " (%s", cur->name);
160 cur = cur->next;
161 if (cur == NULL) break;
162 }
163 if (cur == NULL)
164 fprintf(output, ")");
165 else
166 fprintf(output, "...)");
167 }
168 switch (attr->def) {
169 case XML_ATTRIBUTE_NONE:
170 break;
171 case XML_ATTRIBUTE_REQUIRED:
172 fprintf(output, " REQUIRED");
173 break;
174 case XML_ATTRIBUTE_IMPLIED:
175 fprintf(output, " IMPLIED");
176 break;
177 case XML_ATTRIBUTE_FIXED:
178 fprintf(output, " FIXED");
179 break;
180 }
181 if (attr->defaultValue != NULL) {
182 fprintf(output, "\"");
183 xmlDebugDumpString(output, attr->defaultValue);
184 fprintf(output, "\"");
185 }
186 printf("\n");
187
188 /*
189 * Do a bit of checking
190 */
191 if (attr->parent == NULL)
192 fprintf(output, "PBM: Attr has no parent\n");
193 if (attr->doc == NULL)
194 fprintf(output, "PBM: Attr has no doc\n");
195 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
196 fprintf(output, "PBM: Attr doc differs from parent's one\n");
197 if (attr->prev == NULL) {
198 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
199 fprintf(output, "PBM: Attr has no prev and not first of list\n");
200 } else {
201 if (attr->prev->next != (xmlNodePtr) attr)
202 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
203 }
204 if (attr->next == NULL) {
205 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
206 fprintf(output, "PBM: Attr has no next and not last of list\n");
207 } else {
208 if (attr->next->prev != (xmlNodePtr) attr)
209 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
210 }
211}
212
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000213static void
214xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000215 int i;
216 char shift[100];
217
218 for (i = 0;((i < depth) && (i < 25));i++)
219 shift[2 * i] = shift[2 * i + 1] = ' ';
220 shift[2 * i] = shift[2 * i + 1] = 0;
221
222 fprintf(output, shift);
223
224 if (elem->type != XML_ELEMENT_DECL) {
225 fprintf(output, "PBM: not a Elem\n");
226 return;
227 }
228 if (elem->name != NULL) {
229 fprintf(output, "ELEMDECL(");
230 xmlDebugDumpString(output, elem->name);
231 fprintf(output, ")");
232 } else
233 fprintf(output, "PBM ELEMDECL noname!!!");
234 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000235 case XML_ELEMENT_TYPE_UNDEFINED:
236 fprintf(output, ", UNDEFINED");
237 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000238 case XML_ELEMENT_TYPE_EMPTY:
239 fprintf(output, ", EMPTY");
240 break;
241 case XML_ELEMENT_TYPE_ANY:
242 fprintf(output, ", ANY");
243 break;
244 case XML_ELEMENT_TYPE_MIXED:
245 fprintf(output, ", MIXED ");
246 break;
247 case XML_ELEMENT_TYPE_ELEMENT:
248 fprintf(output, ", MIXED ");
249 break;
250 }
251 if (elem->content != NULL) {
252 char buf[5001];
253
254 buf[0] = 0;
255 xmlSprintfElementContent(buf, elem->content, 1);
256 buf[5000] = 0;
257 fprintf(output, "%s", buf);
258 }
259 printf("\n");
260
261 /*
262 * Do a bit of checking
263 */
264 if (elem->parent == NULL)
265 fprintf(output, "PBM: Elem has no parent\n");
266 if (elem->doc == NULL)
267 fprintf(output, "PBM: Elem has no doc\n");
268 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
269 fprintf(output, "PBM: Elem doc differs from parent's one\n");
270 if (elem->prev == NULL) {
271 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
272 fprintf(output, "PBM: Elem has no prev and not first of list\n");
273 } else {
274 if (elem->prev->next != (xmlNodePtr) elem)
275 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
276 }
277 if (elem->next == NULL) {
278 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
279 fprintf(output, "PBM: Elem has no next and not last of list\n");
280 } else {
281 if (elem->next->prev != (xmlNodePtr) elem)
282 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
283 }
284}
285
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000286static void
287xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000288 int i;
289 char shift[100];
290
291 for (i = 0;((i < depth) && (i < 25));i++)
292 shift[2 * i] = shift[2 * i + 1] = ' ';
293 shift[2 * i] = shift[2 * i + 1] = 0;
294
295 fprintf(output, shift);
296
297 if (ent->type != XML_ENTITY_DECL) {
298 fprintf(output, "PBM: not a Entity decl\n");
299 return;
300 }
301 if (ent->name != NULL) {
302 fprintf(output, "ENTITYDECL(");
303 xmlDebugDumpString(output, ent->name);
304 fprintf(output, ")");
305 } else
306 fprintf(output, "PBM ENTITYDECL noname!!!");
307 switch (ent->etype) {
308 case XML_INTERNAL_GENERAL_ENTITY:
309 fprintf(output, ", internal\n");
310 break;
311 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
312 fprintf(output, ", external parsed\n");
313 break;
314 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
315 fprintf(output, ", unparsed\n");
316 break;
317 case XML_INTERNAL_PARAMETER_ENTITY:
318 fprintf(output, ", parameter\n");
319 break;
320 case XML_EXTERNAL_PARAMETER_ENTITY:
321 fprintf(output, ", external parameter\n");
322 break;
323 case XML_INTERNAL_PREDEFINED_ENTITY:
324 fprintf(output, ", predefined\n");
325 break;
326 }
327 if (ent->ExternalID) {
328 fprintf(output, shift);
329 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
330 }
331 if (ent->SystemID) {
332 fprintf(output, shift);
333 fprintf(output, " SystemID=%s\n", ent->SystemID);
334 }
335 if (ent->URI != NULL) {
336 fprintf(output, shift);
337 fprintf(output, " URI=%s\n", ent->URI);
338 }
339 if (ent->content) {
340 fprintf(output, shift);
341 fprintf(output, " content=");
342 xmlDebugDumpString(output, ent->content);
343 fprintf(output, "\n");
344 }
345
346 /*
347 * Do a bit of checking
348 */
349 if (ent->parent == NULL)
350 fprintf(output, "PBM: Ent has no parent\n");
351 if (ent->doc == NULL)
352 fprintf(output, "PBM: Ent has no doc\n");
353 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
354 fprintf(output, "PBM: Ent doc differs from parent's one\n");
355 if (ent->prev == NULL) {
356 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
357 fprintf(output, "PBM: Ent has no prev and not first of list\n");
358 } else {
359 if (ent->prev->next != (xmlNodePtr) ent)
360 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
361 }
362 if (ent->next == NULL) {
363 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
364 fprintf(output, "PBM: Ent has no next and not last of list\n");
365 } else {
366 if (ent->next->prev != (xmlNodePtr) ent)
367 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
368 }
369}
370
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000371static void
372xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000373 int i;
374 char shift[100];
375
376 for (i = 0;((i < depth) && (i < 25));i++)
377 shift[2 * i] = shift[2 * i + 1] = ' ';
378 shift[2 * i] = shift[2 * i + 1] = 0;
379
380 fprintf(output, shift);
381 if (ns->type != XML_NAMESPACE_DECL) {
382 fprintf(output, "invalid namespace node %d\n", ns->type);
383 return;
384 }
385 if (ns->href == NULL) {
386 if (ns->prefix != NULL)
387 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
388 else
389 fprintf(output, "incomplete default namespace href=NULL\n");
390 } else {
391 if (ns->prefix != NULL)
392 fprintf(output, "namespace %s href=", ns->prefix);
393 else
394 fprintf(output, "default namespace href=");
395
396 xmlDebugDumpString(output, ns->href);
397 fprintf(output, "\n");
398 }
399}
400
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000401static void
402xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000403 while (ns != NULL) {
404 xmlDebugDumpNamespace(output, ns, depth);
405 ns = ns->next;
406 }
407}
408
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000409static void
410xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000411 int i;
412 char shift[100];
413
414 for (i = 0;((i < depth) && (i < 25));i++)
415 shift[2 * i] = shift[2 * i + 1] = ' ';
416 shift[2 * i] = shift[2 * i + 1] = 0;
417
418 fprintf(output, shift);
419 switch (ent->etype) {
420 case XML_INTERNAL_GENERAL_ENTITY:
421 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
422 break;
423 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
424 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
425 break;
426 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
427 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
428 break;
429 case XML_INTERNAL_PARAMETER_ENTITY:
430 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
431 break;
432 case XML_EXTERNAL_PARAMETER_ENTITY:
433 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
434 break;
435 default:
436 fprintf(output, "ENTITY_%d ! ", ent->etype);
437 }
438 fprintf(output, "%s\n", ent->name);
439 if (ent->ExternalID) {
440 fprintf(output, shift);
441 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
442 }
443 if (ent->SystemID) {
444 fprintf(output, shift);
445 fprintf(output, "SystemID=%s\n", ent->SystemID);
446 }
447 if (ent->URI) {
448 fprintf(output, shift);
449 fprintf(output, "URI=%s\n", ent->URI);
450 }
451 if (ent->content) {
452 fprintf(output, shift);
453 fprintf(output, "content=");
454 xmlDebugDumpString(output, ent->content);
455 fprintf(output, "\n");
456 }
457}
458
459void xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
460 int i;
461 char shift[100];
462
463 for (i = 0;((i < depth) && (i < 25));i++)
464 shift[2 * i] = shift[2 * i + 1] = ' ';
465 shift[2 * i] = shift[2 * i + 1] = 0;
466
467 fprintf(output, shift);
468
469 fprintf(output, "ATTRIBUTE ");
470 xmlDebugDumpString(output, attr->name);
471 fprintf(output, "\n");
472 if (attr->children != NULL)
473 xmlDebugDumpNodeList(output, attr->children, depth + 1);
474
475 /*
476 * Do a bit of checking
477 */
478 if (attr->parent == NULL)
479 fprintf(output, "PBM: Attr has no parent\n");
480 if (attr->doc == NULL)
481 fprintf(output, "PBM: Attr has no doc\n");
482 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
483 fprintf(output, "PBM: Attr doc differs from parent's one\n");
484 if (attr->prev == NULL) {
485 if ((attr->parent != NULL) && (attr->parent->properties != attr))
486 fprintf(output, "PBM: Attr has no prev and not first of list\n");
487 } else {
488 if (attr->prev->next != attr)
489 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
490 }
491 if (attr->next != NULL) {
492 if (attr->next->prev != attr)
493 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
494 }
495}
496
497void xmlDebugDumpAttrList(FILE *output, xmlAttrPtr attr, int depth) {
498 while (attr != NULL) {
499 xmlDebugDumpAttr(output, attr, depth);
500 attr = attr->next;
501 }
502}
503
504void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) {
505 int i;
506 char shift[100];
507
508 for (i = 0;((i < depth) && (i < 25));i++)
509 shift[2 * i] = shift[2 * i + 1] = ' ';
510 shift[2 * i] = shift[2 * i + 1] = 0;
511
512 switch (node->type) {
513 case XML_ELEMENT_NODE:
514 fprintf(output, shift);
515 fprintf(output, "ELEMENT ");
516 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
517 xmlDebugDumpString(output, node->ns->prefix);
518 fprintf(output, ":");
519 }
520 xmlDebugDumpString(output, node->name);
521 fprintf(output, "\n");
522 break;
523 case XML_ATTRIBUTE_NODE:
524 fprintf(output, shift);
525 fprintf(output, "Error, ATTRIBUTE found here\n");
526 break;
527 case XML_TEXT_NODE:
528 fprintf(output, shift);
529 fprintf(output, "TEXT\n");
530 break;
531 case XML_CDATA_SECTION_NODE:
532 fprintf(output, shift);
533 fprintf(output, "CDATA_SECTION\n");
534 break;
535 case XML_ENTITY_REF_NODE:
536 fprintf(output, shift);
537 fprintf(output, "ENTITY_REF(%s)\n", node->name);
538 break;
539 case XML_ENTITY_NODE:
540 fprintf(output, shift);
541 fprintf(output, "ENTITY\n");
542 break;
543 case XML_PI_NODE:
544 fprintf(output, shift);
545 fprintf(output, "PI %s\n", node->name);
546 break;
547 case XML_COMMENT_NODE:
548 fprintf(output, shift);
549 fprintf(output, "COMMENT\n");
550 break;
551 case XML_DOCUMENT_NODE:
552 case XML_HTML_DOCUMENT_NODE:
553 fprintf(output, shift);
554 fprintf(output, "Error, DOCUMENT found here\n");
555 break;
556 case XML_DOCUMENT_TYPE_NODE:
557 fprintf(output, shift);
558 fprintf(output, "DOCUMENT_TYPE\n");
559 break;
560 case XML_DOCUMENT_FRAG_NODE:
561 fprintf(output, shift);
562 fprintf(output, "DOCUMENT_FRAG\n");
563 break;
564 case XML_NOTATION_NODE:
565 fprintf(output, shift);
566 fprintf(output, "NOTATION\n");
567 break;
568 case XML_DTD_NODE:
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000569 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
Owen Taylor3473f882001-02-23 17:55:21 +0000570 return;
571 case XML_ELEMENT_DECL:
572 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
573 return;
574 case XML_ATTRIBUTE_DECL:
575 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
576 return;
577 case XML_ENTITY_DECL:
578 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
579 return;
580 case XML_NAMESPACE_DECL:
581 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
582 return;
583 case XML_XINCLUDE_START:
584 fprintf(output, shift);
585 fprintf(output, "INCLUDE START\n");
586 return;
587 case XML_XINCLUDE_END:
588 fprintf(output, shift);
589 fprintf(output, "INCLUDE END\n");
590 return;
591 default:
592 fprintf(output, shift);
593 fprintf(output, "NODE_%d !!!\n", node->type);
594 return;
595 }
596 if (node->doc == NULL) {
597 fprintf(output, shift);
598 fprintf(output, "doc == NULL !!!\n");
599 }
600 if (node->nsDef != NULL)
601 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
602 if (node->properties != NULL)
603 xmlDebugDumpAttrList(output, node->properties, depth + 1);
604 if (node->type != XML_ENTITY_REF_NODE) {
605 if (node->content != NULL) {
606 shift[2 * i] = shift[2 * i + 1] = ' ' ;
607 shift[2 * i + 2] = shift[2 * i + 3] = 0 ;
608 fprintf(output, shift);
609 fprintf(output, "content=");
610#ifndef XML_USE_BUFFER_CONTENT
611 xmlDebugDumpString(output, node->content);
612#else
613 xmlDebugDumpString(output, xmlBufferContent(node->content));
614#endif
615 fprintf(output, "\n");
616 }
617 } else {
618 xmlEntityPtr ent;
619 ent = xmlGetDocEntity(node->doc, node->name);
620 if (ent != NULL)
621 xmlDebugDumpEntity(output, ent, depth + 1);
622 }
623 /*
624 * Do a bit of checking
625 */
626 if (node->parent == NULL)
627 fprintf(output, "PBM: Node has no parent\n");
628 if (node->doc == NULL)
629 fprintf(output, "PBM: Node has no doc\n");
630 if ((node->parent != NULL) && (node->doc != node->parent->doc))
631 fprintf(output, "PBM: Node doc differs from parent's one\n");
632 if (node->prev == NULL) {
633 if ((node->parent != NULL) && (node->parent->children != node))
634 fprintf(output, "PBM: Node has no prev and not first of list\n");
635 } else {
636 if (node->prev->next != node)
637 fprintf(output, "PBM: Node prev->next : back link wrong\n");
638 }
639 if (node->next == NULL) {
640 if ((node->parent != NULL) && (node->parent->last != node))
641 fprintf(output, "PBM: Node has no next and not last of list\n");
642 } else {
643 if (node->next->prev != node)
644 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
645 }
646}
647
648void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth) {
649 xmlDebugDumpOneNode(output, node, depth);
650 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
651 xmlDebugDumpNodeList(output, node->children, depth + 1);
652}
653
654void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth) {
655 while (node != NULL) {
656 xmlDebugDumpNode(output, node, depth);
657 node = node->next;
658 }
659}
660
661
662void xmlDebugDumpDocumentHead(FILE *output, xmlDocPtr doc) {
663 if (output == NULL) output = stdout;
664 if (doc == NULL) {
665 fprintf(output, "DOCUMENT == NULL !\n");
666 return;
667 }
668
669 switch (doc->type) {
670 case XML_ELEMENT_NODE:
671 fprintf(output, "Error, ELEMENT found here ");
672 break;
673 case XML_ATTRIBUTE_NODE:
674 fprintf(output, "Error, ATTRIBUTE found here\n");
675 break;
676 case XML_TEXT_NODE:
677 fprintf(output, "Error, TEXT\n");
678 break;
679 case XML_CDATA_SECTION_NODE:
680 fprintf(output, "Error, CDATA_SECTION\n");
681 break;
682 case XML_ENTITY_REF_NODE:
683 fprintf(output, "Error, ENTITY_REF\n");
684 break;
685 case XML_ENTITY_NODE:
686 fprintf(output, "Error, ENTITY\n");
687 break;
688 case XML_PI_NODE:
689 fprintf(output, "Error, PI\n");
690 break;
691 case XML_COMMENT_NODE:
692 fprintf(output, "Error, COMMENT\n");
693 break;
694 case XML_DOCUMENT_NODE:
695 fprintf(output, "DOCUMENT\n");
696 break;
697 case XML_HTML_DOCUMENT_NODE:
698 fprintf(output, "HTML DOCUMENT\n");
699 break;
700 case XML_DOCUMENT_TYPE_NODE:
701 fprintf(output, "Error, DOCUMENT_TYPE\n");
702 break;
703 case XML_DOCUMENT_FRAG_NODE:
704 fprintf(output, "Error, DOCUMENT_FRAG\n");
705 break;
706 case XML_NOTATION_NODE:
707 fprintf(output, "Error, NOTATION\n");
708 break;
709 default:
710 fprintf(output, "NODE_%d\n", doc->type);
711 }
712 if (doc->name != NULL) {
713 fprintf(output, "name=");
714 xmlDebugDumpString(output, BAD_CAST doc->name);
715 fprintf(output, "\n");
716 }
717 if (doc->version != NULL) {
718 fprintf(output, "version=");
719 xmlDebugDumpString(output, doc->version);
720 fprintf(output, "\n");
721 }
722 if (doc->encoding != NULL) {
723 fprintf(output, "encoding=");
724 xmlDebugDumpString(output, doc->encoding);
725 fprintf(output, "\n");
726 }
727 if (doc->URL != NULL) {
728 fprintf(output, "URL=");
729 xmlDebugDumpString(output, doc->URL);
730 fprintf(output, "\n");
731 }
732 if (doc->standalone)
733 fprintf(output, "standalone=true\n");
734 if (doc->oldNs != NULL)
735 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
736}
737
738void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
739 if (output == NULL) output = stdout;
740 if (doc == NULL) {
741 fprintf(output, "DOCUMENT == NULL !\n");
742 return;
743 }
744 xmlDebugDumpDocumentHead(output, doc);
745 if (((doc->type == XML_DOCUMENT_NODE) ||
746 (doc->type == XML_HTML_DOCUMENT_NODE)) &&
747 (doc->children != NULL))
748 xmlDebugDumpNodeList(output, doc->children, 1);
749}
750
751void xmlDebugDumpDTD(FILE *output, xmlDtdPtr dtd) {
752 if (dtd == NULL)
753 return;
754 if (dtd->type != XML_DTD_NODE) {
755 fprintf(output, "PBM: not a DTD\n");
756 return;
757 }
758 if (dtd->name != NULL)
759 fprintf(output, "DTD(%s)", dtd->name);
760 else
761 fprintf(output, "DTD");
762 if (dtd->ExternalID != NULL)
763 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
764 if (dtd->SystemID != NULL)
765 fprintf(output, ", SYSTEM %s", dtd->SystemID);
766 fprintf(output, "\n");
767 /*
768 * Do a bit of checking
769 */
770 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
771 fprintf(output, "PBM: Dtd doc differs from parent's one\n");
772 if (dtd->prev == NULL) {
773 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
774 fprintf(output, "PBM: Dtd has no prev and not first of list\n");
775 } else {
776 if (dtd->prev->next != (xmlNodePtr) dtd)
777 fprintf(output, "PBM: Dtd prev->next : back link wrong\n");
778 }
779 if (dtd->next == NULL) {
780 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
781 fprintf(output, "PBM: Dtd has no next and not last of list\n");
782 } else {
783 if (dtd->next->prev != (xmlNodePtr) dtd)
784 fprintf(output, "PBM: Dtd next->prev : forward link wrong\n");
785 }
786 if (dtd->children == NULL)
787 fprintf(output, " DTD is empty\n");
788 else
789 xmlDebugDumpNodeList(output, dtd->children, 1);
790}
791
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000792static void
793xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Owen Taylor3473f882001-02-23 17:55:21 +0000794 fprintf(output, "%s : ", cur->name);
795 switch (cur->etype) {
796 case XML_INTERNAL_GENERAL_ENTITY:
797 fprintf(output, "INTERNAL GENERAL, ");
798 break;
799 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
800 fprintf(output, "EXTERNAL PARSED, ");
801 break;
802 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
803 fprintf(output, "EXTERNAL UNPARSED, ");
804 break;
805 case XML_INTERNAL_PARAMETER_ENTITY:
806 fprintf(output, "INTERNAL PARAMETER, ");
807 break;
808 case XML_EXTERNAL_PARAMETER_ENTITY:
809 fprintf(output, "EXTERNAL PARAMETER, ");
810 break;
811 default:
812 fprintf(output, "UNKNOWN TYPE %d",
813 cur->etype);
814 }
815 if (cur->ExternalID != NULL)
816 fprintf(output, "ID \"%s\"", cur->ExternalID);
817 if (cur->SystemID != NULL)
818 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
819 if (cur->orig != NULL)
820 fprintf(output, "\n orig \"%s\"", cur->orig);
821 if (cur->content != NULL)
822 fprintf(output, "\n content \"%s\"", cur->content);
823 fprintf(output, "\n");
824}
825
826void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
827 if (output == NULL) output = stdout;
828 if (doc == NULL) {
829 fprintf(output, "DOCUMENT == NULL !\n");
830 return;
831 }
832
833 switch (doc->type) {
834 case XML_ELEMENT_NODE:
835 fprintf(output, "Error, ELEMENT found here ");
836 break;
837 case XML_ATTRIBUTE_NODE:
838 fprintf(output, "Error, ATTRIBUTE found here\n");
839 break;
840 case XML_TEXT_NODE:
841 fprintf(output, "Error, TEXT\n");
842 break;
843 case XML_CDATA_SECTION_NODE:
844 fprintf(output, "Error, CDATA_SECTION\n");
845 break;
846 case XML_ENTITY_REF_NODE:
847 fprintf(output, "Error, ENTITY_REF\n");
848 break;
849 case XML_ENTITY_NODE:
850 fprintf(output, "Error, ENTITY\n");
851 break;
852 case XML_PI_NODE:
853 fprintf(output, "Error, PI\n");
854 break;
855 case XML_COMMENT_NODE:
856 fprintf(output, "Error, COMMENT\n");
857 break;
858 case XML_DOCUMENT_NODE:
859 fprintf(output, "DOCUMENT\n");
860 break;
861 case XML_HTML_DOCUMENT_NODE:
862 fprintf(output, "HTML DOCUMENT\n");
863 break;
864 case XML_DOCUMENT_TYPE_NODE:
865 fprintf(output, "Error, DOCUMENT_TYPE\n");
866 break;
867 case XML_DOCUMENT_FRAG_NODE:
868 fprintf(output, "Error, DOCUMENT_FRAG\n");
869 break;
870 case XML_NOTATION_NODE:
871 fprintf(output, "Error, NOTATION\n");
872 break;
873 default:
874 fprintf(output, "NODE_%d\n", doc->type);
875 }
876 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
877 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
878 doc->intSubset->entities;
879 fprintf(output, "Entities in internal subset\n");
880 xmlHashScan(table, (xmlHashScanner)xmlDebugDumpEntityCallback, output);
881 } else
882 fprintf(output, "No entities in internal subset\n");
883 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
884 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
885 doc->extSubset->entities;
886 fprintf(output, "Entities in external subset\n");
887 xmlHashScan(table, (xmlHashScanner)xmlDebugDumpEntityCallback, output);
888 } else
889 fprintf(output, "No entities in external subset\n");
890}
891
892static int xmlLsCountNode(xmlNodePtr node) {
893 int ret = 0;
894 xmlNodePtr list = NULL;
895
896 switch (node->type) {
897 case XML_ELEMENT_NODE:
898 list = node->children;
899 break;
900 case XML_DOCUMENT_NODE:
901 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +0000902#ifdef LIBXML_DOCB_ENABLED
903 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +0000904#endif
905 list = ((xmlDocPtr) node)->children;
906 break;
907 case XML_ATTRIBUTE_NODE:
908 list = ((xmlAttrPtr) node)->children;
909 break;
910 case XML_TEXT_NODE:
911 case XML_CDATA_SECTION_NODE:
912 case XML_PI_NODE:
913 case XML_COMMENT_NODE:
914 if (node->content != NULL) {
915#ifndef XML_USE_BUFFER_CONTENT
916 ret = xmlStrlen(node->content);
917#else
918 ret = xmlBufferLength(node->content);
919#endif
920 }
921 break;
922 case XML_ENTITY_REF_NODE:
923 case XML_DOCUMENT_TYPE_NODE:
924 case XML_ENTITY_NODE:
925 case XML_DOCUMENT_FRAG_NODE:
926 case XML_NOTATION_NODE:
927 case XML_DTD_NODE:
928 case XML_ELEMENT_DECL:
929 case XML_ATTRIBUTE_DECL:
930 case XML_ENTITY_DECL:
931 case XML_NAMESPACE_DECL:
932 case XML_XINCLUDE_START:
933 case XML_XINCLUDE_END:
934 ret = 1;
935 break;
936 }
937 for (;list != NULL;ret++)
938 list = list->next;
939 return(ret);
940}
941
942void xmlLsOneNode(FILE *output, xmlNodePtr node) {
943 switch (node->type) {
944 case XML_ELEMENT_NODE:
945 fprintf(output, "-");
946 break;
947 case XML_ATTRIBUTE_NODE:
948 fprintf(output, "a");
949 break;
950 case XML_TEXT_NODE:
951 fprintf(output, "t");
952 break;
953 case XML_CDATA_SECTION_NODE:
954 fprintf(output, "c");
955 break;
956 case XML_ENTITY_REF_NODE:
957 fprintf(output, "e");
958 break;
959 case XML_ENTITY_NODE:
960 fprintf(output, "E");
961 break;
962 case XML_PI_NODE:
963 fprintf(output, "p");
964 break;
965 case XML_COMMENT_NODE:
966 fprintf(output, "c");
967 break;
968 case XML_DOCUMENT_NODE:
969 fprintf(output, "d");
970 break;
971 case XML_HTML_DOCUMENT_NODE:
972 fprintf(output, "h");
973 break;
974 case XML_DOCUMENT_TYPE_NODE:
975 fprintf(output, "T");
976 break;
977 case XML_DOCUMENT_FRAG_NODE:
978 fprintf(output, "F");
979 break;
980 case XML_NOTATION_NODE:
981 fprintf(output, "N");
982 break;
983 default:
984 fprintf(output, "?");
985 }
986 if (node->properties != NULL)
987 fprintf(output, "a");
988 else
989 fprintf(output, "-");
990 if (node->nsDef != NULL)
991 fprintf(output, "n");
992 else
993 fprintf(output, "-");
994
995 fprintf(output, " %8d ", xmlLsCountNode(node));
996
997 switch (node->type) {
998 case XML_ELEMENT_NODE:
999 if (node->name != NULL)
1000 fprintf(output, "%s", node->name);
1001 break;
1002 case XML_ATTRIBUTE_NODE:
1003 if (node->name != NULL)
1004 fprintf(output, "%s", node->name);
1005 break;
1006 case XML_TEXT_NODE:
1007 if (node->content != NULL) {
1008#ifndef XML_USE_BUFFER_CONTENT
1009 xmlDebugDumpString(output, node->content);
1010#else
1011 xmlDebugDumpString(output, xmlBufferContent(node->content));
1012#endif
1013 }
1014 break;
1015 case XML_CDATA_SECTION_NODE:
1016 break;
1017 case XML_ENTITY_REF_NODE:
1018 if (node->name != NULL)
1019 fprintf(output, "%s", node->name);
1020 break;
1021 case XML_ENTITY_NODE:
1022 if (node->name != NULL)
1023 fprintf(output, "%s", node->name);
1024 break;
1025 case XML_PI_NODE:
1026 if (node->name != NULL)
1027 fprintf(output, "%s", node->name);
1028 break;
1029 case XML_COMMENT_NODE:
1030 break;
1031 case XML_DOCUMENT_NODE:
1032 break;
1033 case XML_HTML_DOCUMENT_NODE:
1034 break;
1035 case XML_DOCUMENT_TYPE_NODE:
1036 break;
1037 case XML_DOCUMENT_FRAG_NODE:
1038 break;
1039 case XML_NOTATION_NODE:
1040 break;
1041 default:
1042 if (node->name != NULL)
1043 fprintf(output, "%s", node->name);
1044 }
1045 fprintf(output, "\n");
1046}
1047
1048/****************************************************************
1049 * *
1050 * The XML shell related functions *
1051 * *
1052 ****************************************************************/
1053
1054/*
1055 * TODO: Improvement/cleanups for the XML shell
1056 * - allow to shell out an editor on a subpart
1057 * - cleanup function registrations (with help) and calling
1058 * - provide registration routines
1059 */
1060
1061/**
1062 * xmlShellList:
1063 * @ctxt: the shell context
1064 * @arg: unused
1065 * @node: a node
1066 * @node2: unused
1067 *
1068 * Implements the XML shell function "ls"
1069 * Does an Unix like listing of the given node (like a directory)
1070 *
1071 * Returns 0
1072 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001073static int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001074xmlShellList(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED , char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1075 xmlNodePtr node2 ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001076 xmlNodePtr cur;
1077
1078 if ((node->type == XML_DOCUMENT_NODE) ||
1079 (node->type == XML_HTML_DOCUMENT_NODE)) {
1080 cur = ((xmlDocPtr) node)->children;
1081 } else if (node->children != NULL) {
1082 cur = node->children;
1083 } else {
1084 xmlLsOneNode(stdout, node);
1085 return(0);
1086 }
1087 while (cur != NULL) {
1088 xmlLsOneNode(stdout, cur);
1089 cur = cur->next;
1090 }
1091 return(0);
1092}
1093
1094/**
1095 * xmlShellDir:
1096 * @ctxt: the shell context
1097 * @arg: unused
1098 * @node: a node
1099 * @node2: unused
1100 *
1101 * Implements the XML shell function "dir"
1102 * dumps informations about the node (namespace, attributes, content).
1103 *
1104 * Returns 0
1105 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001106static int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001107xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1108 xmlNodePtr node2 ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001109 if ((node->type == XML_DOCUMENT_NODE) ||
1110 (node->type == XML_HTML_DOCUMENT_NODE)) {
1111 xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
1112 } else if (node->type == XML_ATTRIBUTE_NODE) {
1113 xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
1114 } else {
1115 xmlDebugDumpOneNode(stdout, node, 0);
1116 }
1117 return(0);
1118}
1119
1120/**
1121 * xmlShellCat:
1122 * @ctxt: the shell context
1123 * @arg: unused
1124 * @node: a node
1125 * @node2: unused
1126 *
1127 * Implements the XML shell function "cat"
1128 * dumps the serialization node content (XML or HTML).
1129 *
1130 * Returns 0
1131 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001132static int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001133xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1134 xmlNodePtr node2 ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001135 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1136#ifdef LIBXML_HTML_ENABLED
1137 if (node->type == XML_HTML_DOCUMENT_NODE)
1138 htmlDocDump(stdout, (htmlDocPtr) node);
1139 else
1140 htmlNodeDumpFile(stdout, ctxt->doc, node);
1141#else
1142 if (node->type == XML_DOCUMENT_NODE)
1143 xmlDocDump(stdout, (xmlDocPtr) node);
1144 else
1145 xmlElemDump(stdout, ctxt->doc, node);
1146#endif /* LIBXML_HTML_ENABLED */
1147 } else {
1148 if (node->type == XML_DOCUMENT_NODE)
1149 xmlDocDump(stdout, (xmlDocPtr) node);
1150 else
1151 xmlElemDump(stdout, ctxt->doc, node);
1152 }
1153 printf("\n");
1154 return(0);
1155}
1156
1157/**
1158 * xmlShellLoad:
1159 * @ctxt: the shell context
1160 * @filename: the file name
1161 * @node: unused
1162 * @node2: unused
1163 *
1164 * Implements the XML shell function "load"
1165 * loads a new document specified by the filename
1166 *
1167 * Returns 0 or -1 if loading failed
1168 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001169static int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001170xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node ATTRIBUTE_UNUSED,
1171 xmlNodePtr node2 ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001172 xmlDocPtr doc;
1173 int html = 0;
1174
1175 if (ctxt->doc != NULL)
1176 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
1177
1178 if (html) {
1179#ifdef LIBXML_HTML_ENABLED
1180 doc = htmlParseFile(filename, NULL);
1181#else
1182 printf("HTML support not compiled in\n");
1183 doc = NULL;
1184#endif /* LIBXML_HTML_ENABLED */
1185 } else {
1186 doc = xmlParseFile(filename);
1187 }
1188 if (doc != NULL) {
1189 if (ctxt->loaded == 1) {
1190 xmlFreeDoc(ctxt->doc);
1191 }
1192 ctxt->loaded = 1;
1193#ifdef LIBXML_XPATH_ENABLED
1194 xmlXPathFreeContext(ctxt->pctxt);
1195#endif /* LIBXML_XPATH_ENABLED */
1196 xmlFree(ctxt->filename);
1197 ctxt->doc = doc;
1198 ctxt->node = (xmlNodePtr) doc;
1199#ifdef LIBXML_XPATH_ENABLED
1200 ctxt->pctxt = xmlXPathNewContext(doc);
1201#endif /* LIBXML_XPATH_ENABLED */
1202 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1203 } else
1204 return(-1);
1205 return(0);
1206}
1207
1208/**
1209 * xmlShellWrite:
1210 * @ctxt: the shell context
1211 * @filename: the file name
1212 * @node: a node in the tree
1213 * @node2: unused
1214 *
1215 * Implements the XML shell function "write"
1216 * Write the current node to the filename, it saves the serailization
1217 * of the subtree under the @node specified
1218 *
1219 * Returns 0 or -1 in case of error
1220 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001221static int
Owen Taylor3473f882001-02-23 17:55:21 +00001222xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001223 xmlNodePtr node2 ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001224 if (node == NULL)
1225 return(-1);
1226 if ((filename == NULL) || (filename[0] == 0)) {
1227 xmlGenericError(xmlGenericErrorContext,
1228 "Write command requires a filename argument\n");
1229 return(-1);
1230 }
1231#ifdef W_OK
1232 if (access((char *) filename, W_OK)) {
1233 xmlGenericError(xmlGenericErrorContext,
1234 "Cannot write to %s\n", filename);
1235 return(-1);
1236 }
1237#endif
1238 switch(node->type) {
1239 case XML_DOCUMENT_NODE:
1240 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1241 xmlGenericError(xmlGenericErrorContext,
1242 "Failed to write to %s\n", filename);
1243 return(-1);
1244 }
1245 break;
1246 case XML_HTML_DOCUMENT_NODE:
1247#ifdef LIBXML_HTML_ENABLED
1248 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1249 xmlGenericError(xmlGenericErrorContext,
1250 "Failed to write to %s\n", filename);
1251 return(-1);
1252 }
1253#else
1254 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1255 xmlGenericError(xmlGenericErrorContext,
1256 "Failed to write to %s\n", filename);
1257 return(-1);
1258 }
1259#endif /* LIBXML_HTML_ENABLED */
1260 break;
1261 default: {
1262 FILE *f;
1263
1264 f = fopen((char *) filename, "w");
1265 if (f == NULL) {
1266 xmlGenericError(xmlGenericErrorContext,
1267 "Failed to write to %s\n", filename);
1268 return(-1);
1269 }
1270 xmlElemDump(f, ctxt->doc, node);
1271 fclose(f);
1272 }
1273 }
1274 return(0);
1275}
1276
1277/**
1278 * xmlShellSave:
1279 * @ctxt: the shell context
1280 * @filename: the file name (optionnal)
1281 * @node: unused
1282 * @node2: unused
1283 *
1284 * Implements the XML shell function "save"
1285 * Write the current document to the filename, or it's original name
1286 *
1287 * Returns 0 or -1 in case of error
1288 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001289static int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001290xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node ATTRIBUTE_UNUSED,
1291 xmlNodePtr node2 ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001292 if (ctxt->doc == NULL)
1293 return(-1);
1294 if ((filename == NULL) || (filename[0] == 0))
1295 filename = ctxt->filename;
1296#ifdef W_OK
1297 if (access((char *) filename, W_OK)) {
1298 xmlGenericError(xmlGenericErrorContext,
1299 "Cannot save to %s\n", filename);
1300 return(-1);
1301 }
1302#endif
1303 switch(ctxt->doc->type) {
1304 case XML_DOCUMENT_NODE:
1305 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1306 xmlGenericError(xmlGenericErrorContext,
1307 "Failed to save to %s\n", filename);
1308 }
1309 break;
1310 case XML_HTML_DOCUMENT_NODE:
1311#ifdef LIBXML_HTML_ENABLED
1312 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1313 xmlGenericError(xmlGenericErrorContext,
1314 "Failed to save to %s\n", filename);
1315 }
1316#else
1317 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1318 xmlGenericError(xmlGenericErrorContext,
1319 "Failed to save to %s\n", filename);
1320 }
1321#endif /* LIBXML_HTML_ENABLED */
1322 break;
1323 default:
1324 xmlGenericError(xmlGenericErrorContext,
1325 "To save to subparts of a document use the 'write' command\n");
1326 return(-1);
1327
1328 }
1329 return(0);
1330}
1331
1332/**
1333 * xmlShellValidate:
1334 * @ctxt: the shell context
1335 * @dtd: the DTD URI (optionnal)
1336 * @node: unused
1337 * @node2: unused
1338 *
1339 * Implements the XML shell function "validate"
1340 * Validate the document, if a DTD path is provided, then the validation
1341 * is done against the given DTD.
1342 *
1343 * Returns 0 or -1 in case of error
1344 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001345static int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001346xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node ATTRIBUTE_UNUSED,
1347 xmlNodePtr node2 ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001348 xmlValidCtxt vctxt;
1349 int res = -1;
1350
1351 vctxt.userData = stderr;
1352 vctxt.error = (xmlValidityErrorFunc) fprintf;
1353 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1354
1355 if ((dtd == NULL) || (dtd[0] == 0)) {
1356 res = xmlValidateDocument(&vctxt, ctxt->doc);
1357 } else {
1358 xmlDtdPtr subset;
1359
1360 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1361 if (subset != NULL) {
1362 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1363
1364 xmlFreeDtd(subset);
1365 }
1366 }
1367 return(res);
1368}
1369
1370/**
1371 * xmlShellDu:
1372 * @ctxt: the shell context
1373 * @arg: unused
1374 * @tree: a node defining a subtree
1375 * @node2: unused
1376 *
1377 * Implements the XML shell function "du"
1378 * show the structure of the subtree under node @tree
1379 * If @tree is null, the command works on the current node.
1380 *
1381 * Returns 0 or -1 in case of error
1382 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001383static int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001384xmlShellDu(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1385 xmlNodePtr node2 ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001386 xmlNodePtr node;
1387 int indent = 0,i;
1388
1389 if (tree == NULL) return(-1);
1390 node = tree;
1391 while (node != NULL) {
1392 if ((node->type == XML_DOCUMENT_NODE) ||
1393 (node->type == XML_HTML_DOCUMENT_NODE)) {
1394 printf("/\n");
1395 } else if (node->type == XML_ELEMENT_NODE) {
1396 for (i = 0;i < indent;i++)
1397 printf(" ");
1398 printf("%s\n", node->name);
1399 } else {
1400 }
1401
1402 /*
1403 * Browse the full subtree, deep first
1404 */
1405
1406 if ((node->type == XML_DOCUMENT_NODE) ||
1407 (node->type == XML_HTML_DOCUMENT_NODE)) {
1408 node = ((xmlDocPtr) node)->children;
1409 } else if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1410 /* deep first */
1411 node = node->children;
1412 indent++;
1413 } else if ((node != tree) && (node->next != NULL)) {
1414 /* then siblings */
1415 node = node->next;
1416 } else if (node != tree) {
1417 /* go up to parents->next if needed */
1418 while (node != tree) {
1419 if (node->parent != NULL) {
1420 node = node->parent;
1421 indent--;
1422 }
1423 if ((node != tree) && (node->next != NULL)) {
1424 node = node->next;
1425 break;
1426 }
1427 if (node->parent == NULL) {
1428 node = NULL;
1429 break;
1430 }
1431 if (node == tree) {
1432 node = NULL;
1433 break;
1434 }
1435 }
1436 /* exit condition */
1437 if (node == tree)
1438 node = NULL;
1439 } else
1440 node = NULL;
1441 }
1442 return(0);
1443}
1444
1445/**
1446 * xmlShellPwd:
1447 * @ctxt: the shell context
1448 * @buffer: the output buffer
1449 * @tree: a node
1450 * @node2: unused
1451 *
1452 * Implements the XML shell function "pwd"
1453 * Show the full path from the root to the node, if needed building
1454 * thumblers when similar elements exists at a given ancestor level.
1455 * The output is compatible with XPath commands.
1456 *
1457 * Returns 0 or -1 in case of error
1458 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001459static int
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001460xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer, xmlNodePtr node,
1461 xmlNodePtr node2 ATTRIBUTE_UNUSED) {
Owen Taylor3473f882001-02-23 17:55:21 +00001462 xmlNodePtr cur, tmp, next;
1463 char buf[500];
1464 char sep;
1465 const char *name;
1466 int occur = 0;
1467
1468 buffer[0] = 0;
1469 if (node == NULL) return(-1);
1470 cur = node;
1471 do {
1472 name = "";
1473 sep= '?';
1474 occur = 0;
1475 if ((cur->type == XML_DOCUMENT_NODE) ||
1476 (cur->type == XML_HTML_DOCUMENT_NODE)) {
1477 sep = '/';
1478 next = NULL;
1479 } else if (cur->type == XML_ELEMENT_NODE) {
1480 sep = '/';
1481 name = (const char *)cur->name;
1482 next = cur->parent;
1483
1484 /*
1485 * Thumbler index computation
1486 */
1487 tmp = cur->prev;
1488 while (tmp != NULL) {
1489 if (xmlStrEqual(cur->name, tmp->name))
1490 occur++;
1491 tmp = tmp->prev;
1492 }
1493 if (occur == 0) {
1494 tmp = cur->next;
1495 while (tmp != NULL) {
1496 if (xmlStrEqual(cur->name, tmp->name))
1497 occur++;
1498 tmp = tmp->next;
1499 }
1500 if (occur != 0) occur = 1;
1501 } else
1502 occur++;
1503 } else if (cur->type == XML_ATTRIBUTE_NODE) {
1504 sep = '@';
1505 name = (const char *) (((xmlAttrPtr) cur)->name);
1506 next = ((xmlAttrPtr) cur)->parent;
1507 } else {
1508 next = cur->parent;
1509 }
1510 if (occur == 0)
Owen Taylor3473f882001-02-23 17:55:21 +00001511 snprintf(buf, sizeof(buf), "%c%s%s", sep, name, buffer);
Owen Taylor3473f882001-02-23 17:55:21 +00001512 else
Owen Taylor3473f882001-02-23 17:55:21 +00001513 snprintf(buf, sizeof(buf), "%c%s[%d]%s",
1514 sep, name, occur, buffer);
Owen Taylor3473f882001-02-23 17:55:21 +00001515 buf[sizeof(buf) - 1] = 0;
1516 /*
1517 * This test prevents buffer overflow, because this routine
1518 * is only called by xmlShell, in which the second argument is
1519 * 500 chars long.
1520 * It is a dirty hack before a cleaner solution is found.
1521 * Documentation should mention that the second argument must
1522 * be at least 500 chars long, and could be stripped if too long.
1523 */
1524 if (strlen(buffer) + strlen(buf) > 499)
1525 break;
1526 strcpy(buffer, buf);
1527 cur = next;
1528 } while (cur != NULL);
1529 return(0);
1530}
1531
1532/**
1533 * xmlShell
1534 * @doc: the initial document
1535 * @filename: the output buffer
1536 * @input: the line reading function
1537 * @output: the output FILE*
1538 *
1539 * Implements the XML shell
1540 * This allow to load, validate, view, modify and save a document
1541 * using a environment similar to a UNIX commandline.
1542 */
1543void
1544xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
1545 FILE *output) {
1546 char prompt[500] = "/ > ";
1547 char *cmdline = NULL, *cur;
1548 int nbargs;
1549 char command[100];
1550 char arg[400];
1551 int i;
1552 xmlShellCtxtPtr ctxt;
1553 xmlXPathObjectPtr list;
1554
1555 if (doc == NULL)
1556 return;
1557 if (filename == NULL)
1558 return;
1559 if (input == NULL)
1560 return;
1561 if (output == NULL)
1562 return;
1563 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
1564 if (ctxt == NULL)
1565 return;
1566 ctxt->loaded = 0;
1567 ctxt->doc = doc;
1568 ctxt->input = input;
1569 ctxt->output = output;
1570 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1571 ctxt->node = (xmlNodePtr) ctxt->doc;
1572
1573#ifdef LIBXML_XPATH_ENABLED
1574 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1575 if (ctxt->pctxt == NULL) {
1576 xmlFree(ctxt);
1577 return;
1578 }
1579#endif /* LIBXML_XPATH_ENABLED */
1580 while (1) {
1581 if (ctxt->node == (xmlNodePtr) ctxt->doc)
1582 sprintf(prompt, "%s > ", "/");
1583 else if (ctxt->node->name)
Owen Taylor3473f882001-02-23 17:55:21 +00001584 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001585 else
1586 sprintf(prompt, "? > ");
1587 prompt[sizeof(prompt) - 1] = 0;
1588
1589 /*
1590 * Get a new command line
1591 */
1592 cmdline = ctxt->input(prompt);
1593 if (cmdline == NULL) break;
1594
1595 /*
1596 * Parse the command itself
1597 */
1598 cur = cmdline;
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001599 nbargs = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00001600 while ((*cur == ' ') || (*cur == '\t')) cur++;
1601 i = 0;
1602 while ((*cur != ' ') && (*cur != '\t') &&
1603 (*cur != '\n') && (*cur != '\r')) {
1604 if (*cur == 0)
1605 break;
1606 command[i++] = *cur++;
1607 }
1608 command[i] = 0;
1609 if (i == 0) continue;
1610 nbargs++;
1611
1612 /*
1613 * Parse the argument
1614 */
1615 while ((*cur == ' ') || (*cur == '\t')) cur++;
1616 i = 0;
1617 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
1618 if (*cur == 0)
1619 break;
1620 arg[i++] = *cur++;
1621 }
1622 arg[i] = 0;
1623 if (i != 0)
1624 nbargs++;
1625
1626 /*
1627 * start interpreting the command
1628 */
1629 if (!strcmp(command, "exit"))
1630 break;
1631 if (!strcmp(command, "quit"))
1632 break;
1633 if (!strcmp(command, "bye"))
1634 break;
1635 if (!strcmp(command, "validate")) {
1636 xmlShellValidate(ctxt, arg, NULL, NULL);
1637 } else if (!strcmp(command, "load")) {
1638 xmlShellLoad(ctxt, arg, NULL, NULL);
1639 } else if (!strcmp(command, "save")) {
1640 xmlShellSave(ctxt, arg, NULL, NULL);
1641 } else if (!strcmp(command, "write")) {
1642 xmlShellWrite(ctxt, arg, NULL, NULL);
1643 } else if (!strcmp(command, "free")) {
1644 if (arg[0] == 0) {
1645 xmlMemShow(stdout, 0);
1646 } else {
1647 int len = 0;
1648 sscanf(arg, "%d", &len);
1649 xmlMemShow(stdout, len);
1650 }
1651 } else if (!strcmp(command, "pwd")) {
1652 char dir[500];
1653 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
1654 printf("%s\n", dir);
1655 } else if (!strcmp(command, "du")) {
1656 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
1657 } else if ((!strcmp(command, "ls")) ||
1658 (!strcmp(command, "dir"))) {
1659 int dir = (!strcmp(command, "dir"));
1660 if (arg[0] == 0) {
1661 if (dir)
1662 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
1663 else
1664 xmlShellList(ctxt, NULL, ctxt->node, NULL);
1665 } else {
1666 ctxt->pctxt->node = ctxt->node;
1667#ifdef LIBXML_XPATH_ENABLED
1668 ctxt->pctxt->node = ctxt->node;
1669 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1670#else
1671 list = NULL;
1672#endif /* LIBXML_XPATH_ENABLED */
1673 if (list != NULL) {
1674 switch (list->type) {
1675 case XPATH_UNDEFINED:
1676 xmlGenericError(xmlGenericErrorContext,
1677 "%s: no such node\n", arg);
1678 break;
1679 case XPATH_NODESET: {
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001680 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +00001681
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001682 for (indx = 0;indx < list->nodesetval->nodeNr;
1683 indx++) {
Owen Taylor3473f882001-02-23 17:55:21 +00001684 if (dir)
1685 xmlShellDir(ctxt, NULL,
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001686 list->nodesetval->nodeTab[indx], NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001687 else
1688 xmlShellList(ctxt, NULL,
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001689 list->nodesetval->nodeTab[indx], NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001690 }
1691 break;
1692 }
1693 case XPATH_BOOLEAN:
1694 xmlGenericError(xmlGenericErrorContext,
1695 "%s is a Boolean\n", arg);
1696 break;
1697 case XPATH_NUMBER:
1698 xmlGenericError(xmlGenericErrorContext,
1699 "%s is a number\n", arg);
1700 break;
1701 case XPATH_STRING:
1702 xmlGenericError(xmlGenericErrorContext,
1703 "%s is a string\n", arg);
1704 break;
1705 case XPATH_POINT:
1706 xmlGenericError(xmlGenericErrorContext,
1707 "%s is a point\n", arg);
1708 break;
1709 case XPATH_RANGE:
1710 xmlGenericError(xmlGenericErrorContext,
1711 "%s is a range\n", arg);
1712 break;
1713 case XPATH_LOCATIONSET:
1714 xmlGenericError(xmlGenericErrorContext,
1715 "%s is a range\n", arg);
1716 break;
1717 case XPATH_USERS:
1718 xmlGenericError(xmlGenericErrorContext,
1719 "%s is user-defined\n", arg);
1720 break;
1721 case XPATH_XSLT_TREE:
1722 xmlGenericError(xmlGenericErrorContext,
1723 "%s is an XSLT value tree\n", arg);
1724 break;
1725 }
Daniel Veillard61d80a22001-04-27 17:13:01 +00001726#ifdef LIBXML_XPATH_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001727 xmlXPathFreeNodeSetList(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00001728#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001729 } else {
1730 xmlGenericError(xmlGenericErrorContext,
1731 "%s: no such node\n", arg);
1732 }
1733 ctxt->pctxt->node = NULL;
1734 }
1735 } else if (!strcmp(command, "cd")) {
1736 if (arg[0] == 0) {
1737 ctxt->node = (xmlNodePtr) ctxt->doc;
1738 } else {
1739#ifdef LIBXML_XPATH_ENABLED
1740 ctxt->pctxt->node = ctxt->node;
1741 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1742#else
1743 list = NULL;
1744#endif /* LIBXML_XPATH_ENABLED */
1745 if (list != NULL) {
1746 switch (list->type) {
1747 case XPATH_UNDEFINED:
1748 xmlGenericError(xmlGenericErrorContext,
1749 "%s: no such node\n", arg);
1750 break;
1751 case XPATH_NODESET:
1752 if (list->nodesetval->nodeNr == 1) {
1753 ctxt->node = list->nodesetval->nodeTab[0];
1754 } else
1755 xmlGenericError(xmlGenericErrorContext,
1756 "%s is a %d Node Set\n",
1757 arg, list->nodesetval->nodeNr);
1758 break;
1759 case XPATH_BOOLEAN:
1760 xmlGenericError(xmlGenericErrorContext,
1761 "%s is a Boolean\n", arg);
1762 break;
1763 case XPATH_NUMBER:
1764 xmlGenericError(xmlGenericErrorContext,
1765 "%s is a number\n", arg);
1766 break;
1767 case XPATH_STRING:
1768 xmlGenericError(xmlGenericErrorContext,
1769 "%s is a string\n", arg);
1770 break;
1771 case XPATH_POINT:
1772 xmlGenericError(xmlGenericErrorContext,
1773 "%s is a point\n", arg);
1774 break;
1775 case XPATH_RANGE:
1776 xmlGenericError(xmlGenericErrorContext,
1777 "%s is a range\n", arg);
1778 break;
1779 case XPATH_LOCATIONSET:
1780 xmlGenericError(xmlGenericErrorContext,
1781 "%s is a range\n", arg);
1782 break;
1783 case XPATH_USERS:
1784 xmlGenericError(xmlGenericErrorContext,
1785 "%s is user-defined\n", arg);
1786 break;
1787 case XPATH_XSLT_TREE:
1788 xmlGenericError(xmlGenericErrorContext,
1789 "%s is an XSLT value tree\n", arg);
1790 break;
1791 }
Daniel Veillard61d80a22001-04-27 17:13:01 +00001792#ifdef LIBXML_XPATH_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001793 xmlXPathFreeNodeSetList(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00001794#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001795 } else {
1796 xmlGenericError(xmlGenericErrorContext,
1797 "%s: no such node\n", arg);
1798 }
1799 ctxt->pctxt->node = NULL;
1800 }
1801 } else if (!strcmp(command, "cat")) {
1802 if (arg[0] == 0) {
1803 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
1804 } else {
1805 ctxt->pctxt->node = ctxt->node;
1806#ifdef LIBXML_XPATH_ENABLED
1807 ctxt->pctxt->node = ctxt->node;
1808 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1809#else
1810 list = NULL;
1811#endif /* LIBXML_XPATH_ENABLED */
1812 if (list != NULL) {
1813 switch (list->type) {
1814 case XPATH_UNDEFINED:
1815 xmlGenericError(xmlGenericErrorContext,
1816 "%s: no such node\n", arg);
1817 break;
1818 case XPATH_NODESET: {
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001819 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +00001820
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001821 for (indx = 0;indx < list->nodesetval->nodeNr;
1822 indx++) {
Owen Taylor3473f882001-02-23 17:55:21 +00001823 if (i > 0) printf(" -------\n");
1824 xmlShellCat(ctxt, NULL,
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001825 list->nodesetval->nodeTab[indx], NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001826 }
1827 break;
1828 }
1829 case XPATH_BOOLEAN:
1830 xmlGenericError(xmlGenericErrorContext,
1831 "%s is a Boolean\n", arg);
1832 break;
1833 case XPATH_NUMBER:
1834 xmlGenericError(xmlGenericErrorContext,
1835 "%s is a number\n", arg);
1836 break;
1837 case XPATH_STRING:
1838 xmlGenericError(xmlGenericErrorContext,
1839 "%s is a string\n", arg);
1840 break;
1841 case XPATH_POINT:
1842 xmlGenericError(xmlGenericErrorContext,
1843 "%s is a point\n", arg);
1844 break;
1845 case XPATH_RANGE:
1846 xmlGenericError(xmlGenericErrorContext,
1847 "%s is a range\n", arg);
1848 break;
1849 case XPATH_LOCATIONSET:
1850 xmlGenericError(xmlGenericErrorContext,
1851 "%s is a range\n", arg);
1852 break;
1853 case XPATH_USERS:
1854 xmlGenericError(xmlGenericErrorContext,
1855 "%s is user-defined\n", arg);
1856 break;
1857 case XPATH_XSLT_TREE:
1858 xmlGenericError(xmlGenericErrorContext,
1859 "%s is an XSLT value tree\n", arg);
1860 break;
1861 }
Daniel Veillard61d80a22001-04-27 17:13:01 +00001862#ifdef LIBXML_XPATH_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001863 xmlXPathFreeNodeSetList(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00001864#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001865 } else {
1866 xmlGenericError(xmlGenericErrorContext,
1867 "%s: no such node\n", arg);
1868 }
1869 ctxt->pctxt->node = NULL;
1870 }
1871 } else {
1872 xmlGenericError(xmlGenericErrorContext,
1873 "Unknown command %s\n", command);
1874 }
1875 free(cmdline); /* not xmlFree here ! */
1876 }
1877#ifdef LIBXML_XPATH_ENABLED
1878 xmlXPathFreeContext(ctxt->pctxt);
1879#endif /* LIBXML_XPATH_ENABLED */
1880 if (ctxt->loaded) {
1881 xmlFreeDoc(ctxt->doc);
1882 }
1883 xmlFree(ctxt);
1884 if (cmdline != NULL)
1885 free(cmdline); /* not xmlFree here ! */
1886}
1887
1888#endif /* LIBXML_DEBUG_ENABLED */