blob: 7c00fb1802ae759104002509a4338a8b6139f02c [file] [log] [blame]
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001/*
2 * debugXML.c : This is a set of routines used for debugging the tree
3 * produced by the XML parser.
4 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005 * See Copyright for the status of this software.
6 *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00007 * Daniel Veillard <Daniel.Veillard@w3.org>
8 */
9
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#ifdef WIN32
11#include "win32config.h"
12#else
13#include "config.h"
14#endif
Daniel Veillard361d8452000-04-03 19:48:13 +000015
16#include "xmlversion.h"
17#ifdef LIBXML_DEBUG_ENABLED
18
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000019#include <stdio.h>
Daniel Veillard32bc74e2000-07-14 14:49:25 +000020#include <string.h>
Daniel Veillarddbfd6411999-12-28 16:35:14 +000021#ifdef HAVE_STDLIB_H
22#include <stdlib.h>
23#endif
Daniel Veillard5feb8492000-02-02 17:15:36 +000024#ifdef HAVE_STRING_H
25#include <string.h>
26#endif
Daniel Veillard361d8452000-04-03 19:48:13 +000027#include <libxml/xmlmemory.h>
28#include <libxml/tree.h>
29#include <libxml/parser.h>
30#include <libxml/valid.h>
31#include <libxml/debugXML.h>
32#include <libxml/HTMLtree.h>
33#include <libxml/HTMLparser.h>
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000034
35#define IS_BLANK(c) \
36 (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
37
Daniel Veillarddd6b3671999-09-23 22:19:22 +000038void xmlDebugDumpString(FILE *output, const xmlChar *str) {
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000039 int i;
40 for (i = 0;i < 40;i++)
41 if (str[i] == 0) return;
42 else if (IS_BLANK(str[i])) fputc(' ', output);
Daniel Veillard32bc74e2000-07-14 14:49:25 +000043 else if (str[i] >= 0x80)
44 fprintf(output, "#%X", str[i]);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000045 else fputc(str[i], output);
46 fprintf(output, "...");
47}
48
Daniel Veillardcf461992000-03-14 18:30:20 +000049void xmlDebugDumpDtd(FILE *output, xmlDtdPtr dtd, int depth) {
50 int i;
51 char shift[100];
52
53 for (i = 0;((i < depth) && (i < 25));i++)
54 shift[2 * i] = shift[2 * i + 1] = ' ';
55 shift[2 * i] = shift[2 * i + 1] = 0;
56
57 fprintf(output, shift);
58
59 if (dtd->type != XML_DTD_NODE) {
60 fprintf(output, "PBM: not a DTD\n");
61 return;
62 }
63 if (dtd->name != NULL)
64 fprintf(output, "DTD(%s)", dtd->name);
65 else
66 fprintf(output, "DTD");
67 if (dtd->ExternalID != NULL)
68 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
69 if (dtd->SystemID != NULL)
70 fprintf(output, ", SYSTEM %s", dtd->SystemID);
71 fprintf(output, "\n");
72 /*
73 * Do a bit of checking
74 */
75 if (dtd->parent == NULL)
76 fprintf(output, "PBM: Dtd has no parent\n");
77 if (dtd->doc == NULL)
78 fprintf(output, "PBM: Dtd has no doc\n");
79 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
80 fprintf(output, "PBM: Dtd doc differs from parent's one\n");
81 if (dtd->prev == NULL) {
82 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
83 fprintf(output, "PBM: Dtd has no prev and not first of list\n");
84 } else {
85 if (dtd->prev->next != (xmlNodePtr) dtd)
86 fprintf(output, "PBM: Dtd prev->next : back link wrong\n");
87 }
88 if (dtd->next == NULL) {
89 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
90 fprintf(output, "PBM: Dtd has no next and not last of list\n");
91 } else {
92 if (dtd->next->prev != (xmlNodePtr) dtd)
93 fprintf(output, "PBM: Dtd next->prev : forward link wrong\n");
94 }
95}
96
97void xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
98 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) {
152 int i;
153 xmlEnumerationPtr cur = attr->tree;
154
155 for (i = 0;i < 5; i++) {
156 if (i != 0)
157 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
213void xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
214 int i;
215 char shift[100];
216
217 for (i = 0;((i < depth) && (i < 25));i++)
218 shift[2 * i] = shift[2 * i + 1] = ' ';
219 shift[2 * i] = shift[2 * i + 1] = 0;
220
221 fprintf(output, shift);
222
223 if (elem->type != XML_ELEMENT_DECL) {
224 fprintf(output, "PBM: not a Elem\n");
225 return;
226 }
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000227 if (elem->name != NULL) {
228 fprintf(output, "ELEMDECL(");
229 xmlDebugDumpString(output, elem->name);
230 fprintf(output, ")");
231 } else
Daniel Veillardcf461992000-03-14 18:30:20 +0000232 fprintf(output, "PBM ELEMDECL noname!!!");
233 switch (elem->etype) {
234 case XML_ELEMENT_TYPE_EMPTY:
235 fprintf(output, ", EMPTY");
236 break;
237 case XML_ELEMENT_TYPE_ANY:
238 fprintf(output, ", ANY");
239 break;
240 case XML_ELEMENT_TYPE_MIXED:
241 fprintf(output, ", MIXED ");
242 break;
243 case XML_ELEMENT_TYPE_ELEMENT:
244 fprintf(output, ", MIXED ");
245 break;
246 }
247 if (elem->content != NULL) {
248 char buf[1001];
249
250 buf[0] = 0;
251 xmlSprintfElementContent(buf, elem->content, 1);
252 buf[1000] = 0;
253 fprintf(output, "%s", buf);
254 }
255 printf("\n");
256
257 /*
258 * Do a bit of checking
259 */
260 if (elem->parent == NULL)
261 fprintf(output, "PBM: Elem has no parent\n");
262 if (elem->doc == NULL)
263 fprintf(output, "PBM: Elem has no doc\n");
264 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
265 fprintf(output, "PBM: Elem doc differs from parent's one\n");
266 if (elem->prev == NULL) {
267 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
268 fprintf(output, "PBM: Elem has no prev and not first of list\n");
269 } else {
270 if (elem->prev->next != (xmlNodePtr) elem)
271 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
272 }
273 if (elem->next == NULL) {
274 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
275 fprintf(output, "PBM: Elem has no next and not last of list\n");
276 } else {
277 if (elem->next->prev != (xmlNodePtr) elem)
278 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
279 }
280}
281
282void xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
283 int i;
284 char shift[100];
285
286 for (i = 0;((i < depth) && (i < 25));i++)
287 shift[2 * i] = shift[2 * i + 1] = ' ';
288 shift[2 * i] = shift[2 * i + 1] = 0;
289
290 fprintf(output, shift);
291
292 if (ent->type != XML_ENTITY_DECL) {
293 fprintf(output, "PBM: not a Entity decl\n");
294 return;
295 }
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000296 if (ent->name != NULL) {
297 fprintf(output, "ENTITYDECL(");
298 xmlDebugDumpString(output, ent->name);
299 fprintf(output, ")");
300 } else
Daniel Veillardcf461992000-03-14 18:30:20 +0000301 fprintf(output, "PBM ENTITYDECL noname!!!");
302 switch (ent->etype) {
303 case XML_INTERNAL_GENERAL_ENTITY:
304 fprintf(output, ", internal\n");
305 break;
306 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
307 fprintf(output, ", external parsed\n");
308 break;
309 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
310 fprintf(output, ", unparsed\n");
311 break;
312 case XML_INTERNAL_PARAMETER_ENTITY:
313 fprintf(output, ", parameter\n");
314 break;
315 case XML_EXTERNAL_PARAMETER_ENTITY:
316 fprintf(output, ", external parameter\n");
317 break;
318 case XML_INTERNAL_PREDEFINED_ENTITY:
319 fprintf(output, ", predefined\n");
320 break;
321 }
322 if (ent->ExternalID) {
323 fprintf(output, shift);
324 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
325 }
326 if (ent->SystemID) {
327 fprintf(output, shift);
328 fprintf(output, "SystemID=%s\n", ent->SystemID);
329 }
330 if (ent->content) {
331 fprintf(output, shift);
332 fprintf(output, "content=");
333 xmlDebugDumpString(output, ent->content);
334 fprintf(output, "\n");
335 }
336
337 /*
338 * Do a bit of checking
339 */
340 if (ent->parent == NULL)
341 fprintf(output, "PBM: Ent has no parent\n");
342 if (ent->doc == NULL)
343 fprintf(output, "PBM: Ent has no doc\n");
344 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
345 fprintf(output, "PBM: Ent doc differs from parent's one\n");
346 if (ent->prev == NULL) {
347 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
348 fprintf(output, "PBM: Ent has no prev and not first of list\n");
349 } else {
350 if (ent->prev->next != (xmlNodePtr) ent)
351 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
352 }
353 if (ent->next == NULL) {
354 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
355 fprintf(output, "PBM: Ent has no next and not last of list\n");
356 } else {
357 if (ent->next->prev != (xmlNodePtr) ent)
358 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
359 }
360}
361
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000362void xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
363 int i;
364 char shift[100];
365
366 for (i = 0;((i < depth) && (i < 25));i++)
367 shift[2 * i] = shift[2 * i + 1] = ' ';
368 shift[2 * i] = shift[2 * i + 1] = 0;
369
370 fprintf(output, shift);
371 if (ns->type == XML_GLOBAL_NAMESPACE)
372 fprintf(output, "old ");
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000373 if (ns->prefix != NULL)
374 fprintf(output, "namespace %s href=", ns->prefix);
375 else
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000376 fprintf(output, "default namespace href=");
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000377
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000378 xmlDebugDumpString(output, ns->href);
379 fprintf(output, "\n");
380}
381
382void xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
383 while (ns != NULL) {
384 xmlDebugDumpNamespace(output, ns, depth);
385 ns = ns->next;
386 }
387}
388
389void xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
390 int i;
391 char shift[100];
392
393 for (i = 0;((i < depth) && (i < 25));i++)
394 shift[2 * i] = shift[2 * i + 1] = ' ';
395 shift[2 * i] = shift[2 * i + 1] = 0;
396
397 fprintf(output, shift);
Daniel Veillardcf461992000-03-14 18:30:20 +0000398 switch (ent->etype) {
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000399 case XML_INTERNAL_GENERAL_ENTITY:
400 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
401 break;
402 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
403 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
404 break;
405 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
406 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
407 break;
408 case XML_INTERNAL_PARAMETER_ENTITY:
409 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
410 break;
411 case XML_EXTERNAL_PARAMETER_ENTITY:
412 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
413 break;
414 default:
Daniel Veillardcf461992000-03-14 18:30:20 +0000415 fprintf(output, "ENTITY_%d ! ", ent->etype);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000416 }
417 fprintf(output, "%s\n", ent->name);
418 if (ent->ExternalID) {
419 fprintf(output, shift);
420 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
421 }
422 if (ent->SystemID) {
423 fprintf(output, shift);
424 fprintf(output, "SystemID=%s\n", ent->SystemID);
425 }
426 if (ent->content) {
427 fprintf(output, shift);
428 fprintf(output, "content=");
429 xmlDebugDumpString(output, ent->content);
430 fprintf(output, "\n");
431 }
432}
433
434void xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
435 int i;
436 char shift[100];
437
438 for (i = 0;((i < depth) && (i < 25));i++)
439 shift[2 * i] = shift[2 * i + 1] = ' ';
440 shift[2 * i] = shift[2 * i + 1] = 0;
441
442 fprintf(output, shift);
Daniel Veillardcf461992000-03-14 18:30:20 +0000443
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000444 fprintf(output, "ATTRIBUTE ");
445 xmlDebugDumpString(output, attr->name);
446 fprintf(output, "\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000447 if (attr->children != NULL)
448 xmlDebugDumpNodeList(output, attr->children, depth + 1);
449
450 /*
451 * Do a bit of checking
452 */
453 if (attr->parent == NULL)
454 fprintf(output, "PBM: Attr has no parent\n");
455 if (attr->doc == NULL)
456 fprintf(output, "PBM: Attr has no doc\n");
457 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
458 fprintf(output, "PBM: Attr doc differs from parent's one\n");
459 if (attr->prev == NULL) {
460 if ((attr->parent != NULL) && (attr->parent->properties != attr))
461 fprintf(output, "PBM: Attr has no prev and not first of list\n");
462 } else {
463 if (attr->prev->next != attr)
464 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
465 }
466 if (attr->next != NULL) {
467 if (attr->next->prev != attr)
468 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
469 }
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000470}
471
472void xmlDebugDumpAttrList(FILE *output, xmlAttrPtr attr, int depth) {
473 while (attr != NULL) {
474 xmlDebugDumpAttr(output, attr, depth);
475 attr = attr->next;
476 }
477}
478
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000479void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) {
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000480 int i;
481 char shift[100];
482
483 for (i = 0;((i < depth) && (i < 25));i++)
484 shift[2 * i] = shift[2 * i + 1] = ' ';
485 shift[2 * i] = shift[2 * i + 1] = 0;
486
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000487 switch (node->type) {
488 case XML_ELEMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000489 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000490 fprintf(output, "ELEMENT ");
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000491 if (node->ns != NULL) {
492 xmlDebugDumpString(output, node->ns->prefix);
493 fprintf(output, ":");
494 }
495 xmlDebugDumpString(output, node->name);
496 fprintf(output, "\n");
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000497 break;
498 case XML_ATTRIBUTE_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000499 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000500 fprintf(output, "Error, ATTRIBUTE found here\n");
501 break;
502 case XML_TEXT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000503 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000504 fprintf(output, "TEXT\n");
505 break;
506 case XML_CDATA_SECTION_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000507 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000508 fprintf(output, "CDATA_SECTION\n");
509 break;
510 case XML_ENTITY_REF_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000511 fprintf(output, shift);
512 fprintf(output, "ENTITY_REF(%s)\n", node->name);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000513 break;
514 case XML_ENTITY_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000515 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000516 fprintf(output, "ENTITY\n");
517 break;
518 case XML_PI_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000519 fprintf(output, shift);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000520 fprintf(output, "PI %s\n", node->name);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000521 break;
522 case XML_COMMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000523 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000524 fprintf(output, "COMMENT\n");
525 break;
526 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000527 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000528 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000529 fprintf(output, "Error, DOCUMENT found here\n");
530 break;
531 case XML_DOCUMENT_TYPE_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000532 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000533 fprintf(output, "DOCUMENT_TYPE\n");
534 break;
535 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000536 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000537 fprintf(output, "DOCUMENT_FRAG\n");
538 break;
539 case XML_NOTATION_NODE:
540 fprintf(output, "NOTATION\n");
541 break;
Daniel Veillardcf461992000-03-14 18:30:20 +0000542 case XML_DTD_NODE:
543 xmlDebugDumpDtd(output, (xmlDtdPtr) node, depth);
544 return;
545 case XML_ELEMENT_DECL:
546 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
547 return;
548 case XML_ATTRIBUTE_DECL:
549 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
550 return;
551 case XML_ENTITY_DECL:
552 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
553 return;
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000554 default:
Daniel Veillardcf461992000-03-14 18:30:20 +0000555 fprintf(output, shift);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000556 fprintf(output, "NODE_%d\n", node->type);
557 }
558 if (node->doc == NULL) {
559 fprintf(output, shift);
560 fprintf(output, "doc == NULL !!!\n");
561 }
562 if (node->nsDef != NULL)
563 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
564 if (node->properties != NULL)
565 xmlDebugDumpAttrList(output, node->properties, depth + 1);
566 if (node->type != XML_ENTITY_REF_NODE) {
567 if (node->content != NULL) {
568 fprintf(output, shift);
569 fprintf(output, "content=");
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000570#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000571 xmlDebugDumpString(output, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000572#else
573 xmlDebugDumpString(output, xmlBufferContent(node->content));
574#endif
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000575 fprintf(output, "\n");
576 }
577 } else {
578 xmlEntityPtr ent;
579 ent = xmlGetDocEntity(node->doc, node->name);
580 if (ent != NULL)
581 xmlDebugDumpEntity(output, ent, depth + 1);
582 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000583 /*
584 * Do a bit of checking
585 */
586 if (node->parent == NULL)
587 fprintf(output, "PBM: Node has no parent\n");
588 if (node->doc == NULL)
589 fprintf(output, "PBM: Node has no doc\n");
590 if ((node->parent != NULL) && (node->doc != node->parent->doc))
591 fprintf(output, "PBM: Node doc differs from parent's one\n");
592 if (node->prev == NULL) {
593 if ((node->parent != NULL) && (node->parent->children != node))
594 fprintf(output, "PBM: Node has no prev and not first of list\n");
595 } else {
596 if (node->prev->next != node)
597 fprintf(output, "PBM: Node prev->next : back link wrong\n");
598 }
599 if (node->next == NULL) {
600 if ((node->parent != NULL) && (node->parent->last != node))
601 fprintf(output, "PBM: Node has no next and not last of list\n");
602 } else {
603 if (node->next->prev != node)
604 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
605 }
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000606}
607
608void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth) {
609 xmlDebugDumpOneNode(output, node, depth);
Daniel Veillardcf461992000-03-14 18:30:20 +0000610 if (node->children != NULL)
611 xmlDebugDumpNodeList(output, node->children, depth + 1);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000612}
613
614void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth) {
615 while (node != NULL) {
616 xmlDebugDumpNode(output, node, depth);
617 node = node->next;
618 }
619}
620
621
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000622void xmlDebugDumpDocumentHead(FILE *output, xmlDocPtr doc) {
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000623 if (output == NULL) output = stdout;
624 if (doc == NULL) {
625 fprintf(output, "DOCUMENT == NULL !\n");
626 return;
627 }
628
629 switch (doc->type) {
630 case XML_ELEMENT_NODE:
631 fprintf(output, "Error, ELEMENT found here ");
632 break;
633 case XML_ATTRIBUTE_NODE:
634 fprintf(output, "Error, ATTRIBUTE found here\n");
635 break;
636 case XML_TEXT_NODE:
637 fprintf(output, "Error, TEXT\n");
638 break;
639 case XML_CDATA_SECTION_NODE:
640 fprintf(output, "Error, CDATA_SECTION\n");
641 break;
642 case XML_ENTITY_REF_NODE:
643 fprintf(output, "Error, ENTITY_REF\n");
644 break;
645 case XML_ENTITY_NODE:
646 fprintf(output, "Error, ENTITY\n");
647 break;
648 case XML_PI_NODE:
649 fprintf(output, "Error, PI\n");
650 break;
651 case XML_COMMENT_NODE:
652 fprintf(output, "Error, COMMENT\n");
653 break;
654 case XML_DOCUMENT_NODE:
655 fprintf(output, "DOCUMENT\n");
656 break;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000657 case XML_HTML_DOCUMENT_NODE:
658 fprintf(output, "HTML DOCUMENT\n");
659 break;
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000660 case XML_DOCUMENT_TYPE_NODE:
661 fprintf(output, "Error, DOCUMENT_TYPE\n");
662 break;
663 case XML_DOCUMENT_FRAG_NODE:
664 fprintf(output, "Error, DOCUMENT_FRAG\n");
665 break;
666 case XML_NOTATION_NODE:
667 fprintf(output, "Error, NOTATION\n");
668 break;
669 default:
670 fprintf(output, "NODE_%d\n", doc->type);
671 }
672 if (doc->name != NULL) {
673 fprintf(output, "name=");
Daniel Veillardb96e6431999-08-29 21:02:19 +0000674 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000675 fprintf(output, "\n");
676 }
677 if (doc->version != NULL) {
678 fprintf(output, "version=");
679 xmlDebugDumpString(output, doc->version);
680 fprintf(output, "\n");
681 }
682 if (doc->encoding != NULL) {
683 fprintf(output, "encoding=");
684 xmlDebugDumpString(output, doc->encoding);
685 fprintf(output, "\n");
686 }
687 if (doc->standalone)
688 fprintf(output, "standalone=true\n");
689 if (doc->oldNs != NULL)
690 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000691}
Daniel Veillard10a2c651999-12-12 13:03:50 +0000692
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000693void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
694 if (output == NULL) output = stdout;
695 if (doc == NULL) {
696 fprintf(output, "DOCUMENT == NULL !\n");
697 return;
698 }
699 xmlDebugDumpDocumentHead(output, doc);
700 if (((doc->type == XML_DOCUMENT_NODE) ||
701 (doc->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000702 (doc->children != NULL))
703 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000704}
705
Daniel Veillard10a2c651999-12-12 13:03:50 +0000706void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
707 int i;
708 xmlEntityPtr cur;
709
710 if (output == NULL) output = stdout;
711 if (doc == NULL) {
712 fprintf(output, "DOCUMENT == NULL !\n");
713 return;
714 }
715
716 switch (doc->type) {
717 case XML_ELEMENT_NODE:
718 fprintf(output, "Error, ELEMENT found here ");
719 break;
720 case XML_ATTRIBUTE_NODE:
721 fprintf(output, "Error, ATTRIBUTE found here\n");
722 break;
723 case XML_TEXT_NODE:
724 fprintf(output, "Error, TEXT\n");
725 break;
726 case XML_CDATA_SECTION_NODE:
727 fprintf(output, "Error, CDATA_SECTION\n");
728 break;
729 case XML_ENTITY_REF_NODE:
730 fprintf(output, "Error, ENTITY_REF\n");
731 break;
732 case XML_ENTITY_NODE:
733 fprintf(output, "Error, ENTITY\n");
734 break;
735 case XML_PI_NODE:
736 fprintf(output, "Error, PI\n");
737 break;
738 case XML_COMMENT_NODE:
739 fprintf(output, "Error, COMMENT\n");
740 break;
741 case XML_DOCUMENT_NODE:
742 fprintf(output, "DOCUMENT\n");
743 break;
744 case XML_HTML_DOCUMENT_NODE:
745 fprintf(output, "HTML DOCUMENT\n");
746 break;
747 case XML_DOCUMENT_TYPE_NODE:
748 fprintf(output, "Error, DOCUMENT_TYPE\n");
749 break;
750 case XML_DOCUMENT_FRAG_NODE:
751 fprintf(output, "Error, DOCUMENT_FRAG\n");
752 break;
753 case XML_NOTATION_NODE:
754 fprintf(output, "Error, NOTATION\n");
755 break;
756 default:
757 fprintf(output, "NODE_%d\n", doc->type);
758 }
759 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
760 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
761 doc->intSubset->entities;
762 fprintf(output, "Entities in internal subset\n");
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000763 for (i = 0;i < table->max_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000764 cur = table->table[i];
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000765 while (cur != NULL) {
766 fprintf(output, "%d : %s : ", i, cur->name);
767 switch (cur->etype) {
768 case XML_INTERNAL_GENERAL_ENTITY:
769 fprintf(output, "INTERNAL GENERAL, ");
770 break;
771 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
772 fprintf(output, "EXTERNAL PARSED, ");
773 break;
774 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
775 fprintf(output, "EXTERNAL UNPARSED, ");
776 break;
777 case XML_INTERNAL_PARAMETER_ENTITY:
778 fprintf(output, "INTERNAL PARAMETER, ");
779 break;
780 case XML_EXTERNAL_PARAMETER_ENTITY:
781 fprintf(output, "EXTERNAL PARAMETER, ");
782 break;
783 default:
784 fprintf(output, "UNKNOWN TYPE %d",
785 cur->etype);
786 }
787 if (cur->ExternalID != NULL)
788 fprintf(output, "ID \"%s\"", cur->ExternalID);
789 if (cur->SystemID != NULL)
790 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
791 if (cur->orig != NULL)
792 fprintf(output, "\n orig \"%s\"", cur->orig);
793 if (cur->content != NULL)
794 fprintf(output, "\n content \"%s\"", cur->content);
795 fprintf(output, "\n");
796 cur = cur->nexte;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000797 }
Daniel Veillard10a2c651999-12-12 13:03:50 +0000798 }
799 } else
800 fprintf(output, "No entities in internal subset\n");
801 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
802 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
803 doc->extSubset->entities;
804 fprintf(output, "Entities in external subset\n");
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000805 for (i = 0;i < table->max_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000806 cur = table->table[i];
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000807 while (cur != NULL) {
808 fprintf(output, "%d : %s : ", i, cur->name);
809 switch (cur->etype) {
810 case XML_INTERNAL_GENERAL_ENTITY:
811 fprintf(output, "INTERNAL GENERAL, ");
812 break;
813 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
814 fprintf(output, "EXTERNAL PARSED, ");
815 break;
816 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
817 fprintf(output, "EXTERNAL UNPARSED, ");
818 break;
819 case XML_INTERNAL_PARAMETER_ENTITY:
820 fprintf(output, "INTERNAL PARAMETER, ");
821 break;
822 case XML_EXTERNAL_PARAMETER_ENTITY:
823 fprintf(output, "EXTERNAL PARAMETER, ");
824 break;
825 default:
826 fprintf(output, "UNKNOWN TYPE %d",
827 cur->etype);
828 }
829 if (cur->ExternalID != NULL)
830 fprintf(output, "ID \"%s\"", cur->ExternalID);
831 if (cur->SystemID != NULL)
832 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
833 if (cur->orig != NULL)
834 fprintf(output, "\n orig \"%s\"", cur->orig);
835 if (cur->content != NULL)
836 fprintf(output, "\n content \"%s\"", cur->content);
837 fprintf(output, "\n");
838 cur = cur->nexte;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000839 }
Daniel Veillard10a2c651999-12-12 13:03:50 +0000840 }
841 } else
842 fprintf(output, "No entities in external subset\n");
843}
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000844
845static int xmlLsCountNode(xmlNodePtr node) {
846 int ret = 0;
847 xmlNodePtr list = NULL;
848
849 switch (node->type) {
850 case XML_ELEMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000851 list = node->children;
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000852 break;
853 case XML_DOCUMENT_NODE:
854 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000855 list = ((xmlDocPtr) node)->children;
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000856 break;
857 case XML_ATTRIBUTE_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000858 list = ((xmlAttrPtr) node)->children;
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000859 break;
860 case XML_TEXT_NODE:
861 case XML_CDATA_SECTION_NODE:
862 case XML_PI_NODE:
863 case XML_COMMENT_NODE:
864 if (node->content != NULL) {
865#ifndef XML_USE_BUFFER_CONTENT
866 ret = xmlStrlen(node->content);
867#else
868 ret = xmlBufferLength(node->content);
869#endif
870 }
871 break;
872 case XML_ENTITY_REF_NODE:
873 case XML_DOCUMENT_TYPE_NODE:
874 case XML_ENTITY_NODE:
875 case XML_DOCUMENT_FRAG_NODE:
876 case XML_NOTATION_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +0000877 case XML_DTD_NODE:
878 case XML_ELEMENT_DECL:
879 case XML_ATTRIBUTE_DECL:
880 case XML_ENTITY_DECL:
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000881 ret = 1;
882 break;
883 }
884 for (;list != NULL;ret++)
885 list = list->next;
886 return(ret);
887}
888
889void xmlLsOneNode(FILE *output, xmlNodePtr node) {
890 switch (node->type) {
891 case XML_ELEMENT_NODE:
892 fprintf(output, "-");
893 break;
894 case XML_ATTRIBUTE_NODE:
895 fprintf(output, "a");
896 break;
897 case XML_TEXT_NODE:
898 fprintf(output, "t");
899 break;
900 case XML_CDATA_SECTION_NODE:
901 fprintf(output, "c");
902 break;
903 case XML_ENTITY_REF_NODE:
904 fprintf(output, "e");
905 break;
906 case XML_ENTITY_NODE:
907 fprintf(output, "E");
908 break;
909 case XML_PI_NODE:
910 fprintf(output, "p");
911 break;
912 case XML_COMMENT_NODE:
913 fprintf(output, "c");
914 break;
915 case XML_DOCUMENT_NODE:
916 fprintf(output, "d");
917 break;
918 case XML_HTML_DOCUMENT_NODE:
919 fprintf(output, "h");
920 break;
921 case XML_DOCUMENT_TYPE_NODE:
922 fprintf(output, "T");
923 break;
924 case XML_DOCUMENT_FRAG_NODE:
925 fprintf(output, "F");
926 break;
927 case XML_NOTATION_NODE:
928 fprintf(output, "N");
929 break;
930 default:
931 fprintf(output, "?");
932 }
933 if (node->properties != NULL)
934 fprintf(output, "a");
935 else
936 fprintf(output, "-");
937 if (node->nsDef != NULL)
938 fprintf(output, "n");
939 else
940 fprintf(output, "-");
941
942 fprintf(output, " %8d ", xmlLsCountNode(node));
943
944 switch (node->type) {
945 case XML_ELEMENT_NODE:
946 if (node->name != NULL)
947 fprintf(output, "%s", node->name);
948 break;
949 case XML_ATTRIBUTE_NODE:
950 if (node->name != NULL)
951 fprintf(output, "%s", node->name);
952 break;
953 case XML_TEXT_NODE:
954 if (node->content != NULL) {
955#ifndef XML_USE_BUFFER_CONTENT
956 xmlDebugDumpString(output, node->content);
957#else
958 xmlDebugDumpString(output, xmlBufferContent(node->content));
959#endif
960 }
961 break;
962 case XML_CDATA_SECTION_NODE:
963 break;
964 case XML_ENTITY_REF_NODE:
965 if (node->name != NULL)
966 fprintf(output, "%s", node->name);
967 break;
968 case XML_ENTITY_NODE:
969 if (node->name != NULL)
970 fprintf(output, "%s", node->name);
971 break;
972 case XML_PI_NODE:
973 if (node->name != NULL)
974 fprintf(output, "%s", node->name);
975 break;
976 case XML_COMMENT_NODE:
977 break;
978 case XML_DOCUMENT_NODE:
979 break;
980 case XML_HTML_DOCUMENT_NODE:
981 break;
982 case XML_DOCUMENT_TYPE_NODE:
983 break;
984 case XML_DOCUMENT_FRAG_NODE:
985 break;
986 case XML_NOTATION_NODE:
987 break;
988 default:
989 if (node->name != NULL)
990 fprintf(output, "%s", node->name);
991 }
992 fprintf(output, "\n");
993}
994
995/****************************************************************
996 * *
997 * The XML shell related functions *
998 * *
999 ****************************************************************/
1000
1001/*
1002 * TODO: Improvement/cleanups for the XML shell
1003 * - allow to shell out an editor on a subpart
1004 * - cleanup function registrations (with help) and calling
1005 * - provide registration routines
1006 */
1007
1008/**
1009 * xmlShellList:
1010 * @ctxt: the shell context
1011 * @arg: unused
1012 * @node: a node
1013 * @node2: unused
1014 *
1015 * Implements the XML shell function "ls"
1016 * Does an Unix like listing of the given node (like a directory)
1017 *
1018 * Returns 0
1019 */
1020int
1021xmlShellList(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
1022 xmlNodePtr node2) {
1023 xmlNodePtr cur;
1024
1025 if ((node->type == XML_DOCUMENT_NODE) ||
1026 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001027 cur = ((xmlDocPtr) node)->children;
1028 } else if (node->children != NULL) {
1029 cur = node->children;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001030 } else {
1031 xmlLsOneNode(stdout, node);
1032 return(0);
1033 }
1034 while (cur != NULL) {
1035 xmlLsOneNode(stdout, cur);
1036 cur = cur->next;
1037 }
1038 return(0);
1039}
1040
1041/**
1042 * xmlShellDir:
1043 * @ctxt: the shell context
1044 * @arg: unused
1045 * @node: a node
1046 * @node2: unused
1047 *
1048 * Implements the XML shell function "dir"
1049 * dumps informations about the node (namespace, attributes, content).
1050 *
1051 * Returns 0
1052 */
1053int
1054xmlShellDir(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
1055 xmlNodePtr node2) {
1056 if ((node->type == XML_DOCUMENT_NODE) ||
1057 (node->type == XML_HTML_DOCUMENT_NODE)) {
1058 xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
1059 } else if (node->type == XML_ATTRIBUTE_NODE) {
1060 xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
1061 } else {
1062 xmlDebugDumpOneNode(stdout, node, 0);
1063 }
1064 return(0);
1065}
1066
1067/**
1068 * xmlShellCat:
1069 * @ctxt: the shell context
1070 * @arg: unused
1071 * @node: a node
1072 * @node2: unused
1073 *
1074 * Implements the XML shell function "cat"
1075 * dumps the serialization node content (XML or HTML).
1076 *
1077 * Returns 0
1078 */
1079int
1080xmlShellCat(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
1081 xmlNodePtr node2) {
Daniel Veillardaeea04f2000-01-25 19:27:27 +00001082 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
Daniel Veillard361d8452000-04-03 19:48:13 +00001083#ifdef LIBXML_HTML_ENABLED
Daniel Veillardaeea04f2000-01-25 19:27:27 +00001084 if (node->type == XML_HTML_DOCUMENT_NODE)
1085 htmlDocDump(stdout, (htmlDocPtr) node);
1086 else
Daniel Veillard5feb8492000-02-02 17:15:36 +00001087 htmlNodeDumpFile(stdout, ctxt->doc, node);
Daniel Veillard361d8452000-04-03 19:48:13 +00001088#else
1089 if (node->type == XML_DOCUMENT_NODE)
1090 xmlDocDump(stdout, (xmlDocPtr) node);
1091 else
1092 xmlElemDump(stdout, ctxt->doc, node);
1093#endif /* LIBXML_HTML_ENABLED */
Daniel Veillardaeea04f2000-01-25 19:27:27 +00001094 } else {
1095 if (node->type == XML_DOCUMENT_NODE)
1096 xmlDocDump(stdout, (xmlDocPtr) node);
1097 else
1098 xmlElemDump(stdout, ctxt->doc, node);
1099 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001100 printf("\n");
1101 return(0);
1102}
1103
1104/**
1105 * xmlShellLoad:
1106 * @ctxt: the shell context
1107 * @filename: the file name
1108 * @node: unused
1109 * @node2: unused
1110 *
1111 * Implements the XML shell function "load"
1112 * loads a new document specified by the filename
1113 *
1114 * Returns 0 or -1 if loading failed
1115 */
1116int
1117xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1118 xmlNodePtr node2) {
1119 xmlDocPtr doc;
1120 int html = 0;
1121
1122 if (ctxt->doc != NULL)
1123 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
1124
1125 if (html) {
Daniel Veillard361d8452000-04-03 19:48:13 +00001126#ifdef LIBXML_HTML_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001127 doc = htmlParseFile(filename, NULL);
Daniel Veillard361d8452000-04-03 19:48:13 +00001128#else
1129 printf("HTML support not compiled in\n");
1130 doc = NULL;
1131#endif /* LIBXML_HTML_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001132 } else {
1133 doc = xmlParseFile(filename);
1134 }
1135 if (doc != NULL) {
1136 if (ctxt->loaded == 1) {
1137 xmlFreeDoc(ctxt->doc);
1138 }
1139 ctxt->loaded = 1;
Daniel Veillard361d8452000-04-03 19:48:13 +00001140#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001141 xmlXPathFreeContext(ctxt->pctxt);
Daniel Veillard361d8452000-04-03 19:48:13 +00001142#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001143 xmlFree(ctxt->filename);
1144 ctxt->doc = doc;
1145 ctxt->node = (xmlNodePtr) doc;
Daniel Veillard361d8452000-04-03 19:48:13 +00001146#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001147 ctxt->pctxt = xmlXPathNewContext(doc);
Daniel Veillard361d8452000-04-03 19:48:13 +00001148#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001149 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1150 } else
1151 return(-1);
1152 return(0);
1153}
1154
1155/**
1156 * xmlShellWrite:
1157 * @ctxt: the shell context
1158 * @filename: the file name
1159 * @node: a node in the tree
1160 * @node2: unused
1161 *
1162 * Implements the XML shell function "write"
1163 * Write the current node to the filename, it saves the serailization
1164 * of the subtree under the @node specified
1165 *
1166 * Returns 0 or -1 in case of error
1167 */
1168int
1169xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1170 xmlNodePtr node2) {
1171 if (node == NULL)
1172 return(-1);
1173 if ((filename == NULL) || (filename[0] == 0)) {
1174 fprintf(stderr, "Write command requires a filename argument\n");
1175 return(-1);
1176 }
1177#ifdef W_OK
1178 if (access((char *) filename, W_OK)) {
1179 fprintf(stderr, "Cannot write to %s\n", filename);
1180 return(-1);
1181 }
1182#endif
1183 switch(node->type) {
1184 case XML_DOCUMENT_NODE:
1185 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1186 fprintf(stderr, "Failed to write to %s\n", filename);
1187 return(-1);
1188 }
1189 break;
1190 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard361d8452000-04-03 19:48:13 +00001191#ifdef LIBXML_HTML_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001192 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1193 fprintf(stderr, "Failed to write to %s\n", filename);
1194 return(-1);
1195 }
Daniel Veillard361d8452000-04-03 19:48:13 +00001196#else
1197 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1198 fprintf(stderr, "Failed to write to %s\n", filename);
1199 return(-1);
1200 }
1201#endif /* LIBXML_HTML_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001202 break;
1203 default: {
1204 FILE *f;
1205
1206 f = fopen((char *) filename, "w");
1207 if (f == NULL) {
1208 fprintf(stderr, "Failed to write to %s\n", filename);
1209 return(-1);
1210 }
1211 xmlElemDump(f, ctxt->doc, node);
1212 fclose(f);
1213 }
1214 }
1215 return(0);
1216}
1217
1218/**
1219 * xmlShellSave:
1220 * @ctxt: the shell context
1221 * @filename: the file name (optionnal)
1222 * @node: unused
1223 * @node2: unused
1224 *
1225 * Implements the XML shell function "save"
1226 * Write the current document to the filename, or it's original name
1227 *
1228 * Returns 0 or -1 in case of error
1229 */
1230int
1231xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1232 xmlNodePtr node2) {
1233 if (ctxt->doc == NULL)
1234 return(-1);
1235 if ((filename == NULL) || (filename[0] == 0))
1236 filename = ctxt->filename;
1237#ifdef W_OK
1238 if (access((char *) filename, W_OK)) {
1239 fprintf(stderr, "Cannot save to %s\n", filename);
1240 return(-1);
1241 }
1242#endif
1243 switch(ctxt->doc->type) {
1244 case XML_DOCUMENT_NODE:
1245 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1246 fprintf(stderr, "Failed to save to %s\n", filename);
1247 }
1248 break;
1249 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard361d8452000-04-03 19:48:13 +00001250#ifdef LIBXML_HTML_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001251 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1252 fprintf(stderr, "Failed to save to %s\n", filename);
1253 }
Daniel Veillard361d8452000-04-03 19:48:13 +00001254#else
1255 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1256 fprintf(stderr, "Failed to save to %s\n", filename);
1257 }
1258#endif /* LIBXML_HTML_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001259 break;
1260 default:
1261 fprintf(stderr,
1262 "To save to subparts of a document use the 'write' command\n");
1263 return(-1);
1264
1265 }
1266 return(0);
1267}
1268
1269/**
1270 * xmlShellValidate:
1271 * @ctxt: the shell context
1272 * @dtd: the DTD URI (optionnal)
1273 * @node: unused
1274 * @node2: unused
1275 *
1276 * Implements the XML shell function "validate"
1277 * Validate the document, if a DTD path is provided, then the validation
1278 * is done against the given DTD.
1279 *
1280 * Returns 0 or -1 in case of error
1281 */
1282int
1283xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node,
1284 xmlNodePtr node2) {
1285 xmlValidCtxt vctxt;
1286 int res = -1;
1287
1288 vctxt.userData = stderr;
1289 vctxt.error = (xmlValidityErrorFunc) fprintf;
1290 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1291
1292 if ((dtd == NULL) || (dtd[0] == 0)) {
1293 res = xmlValidateDocument(&vctxt, ctxt->doc);
1294 } else {
1295 xmlDtdPtr subset;
1296
1297 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1298 if (subset != NULL) {
1299 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1300
1301 xmlFreeDtd(subset);
1302 }
1303 }
1304 return(res);
1305}
1306
1307/**
1308 * xmlShellDu:
1309 * @ctxt: the shell context
1310 * @arg: unused
1311 * @tree: a node defining a subtree
1312 * @node2: unused
1313 *
1314 * Implements the XML shell function "du"
1315 * show the structure of the subtree under node @tree
1316 * If @tree is null, the command works on the current node.
1317 *
1318 * Returns 0 or -1 in case of error
1319 */
1320int
1321xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
1322 xmlNodePtr node2) {
1323 xmlNodePtr node;
1324 int indent = 0,i;
1325
1326 if (tree == NULL) return(-1);
1327 node = tree;
1328 while (node != NULL) {
1329 if ((node->type == XML_DOCUMENT_NODE) ||
1330 (node->type == XML_HTML_DOCUMENT_NODE)) {
1331 printf("/\n");
1332 } else if (node->type == XML_ELEMENT_NODE) {
1333 for (i = 0;i < indent;i++)
1334 printf(" ");
1335 printf("%s\n", node->name);
1336 } else {
1337 }
1338
1339 /*
1340 * Browse the full subtree, deep first
1341 */
1342
1343 if ((node->type == XML_DOCUMENT_NODE) ||
1344 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001345 node = ((xmlDocPtr) node)->children;
Daniel Veillardbe803962000-06-28 23:40:59 +00001346 } else if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001347 /* deep first */
Daniel Veillardcf461992000-03-14 18:30:20 +00001348 node = node->children;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001349 indent++;
1350 } else if ((node != tree) && (node->next != NULL)) {
1351 /* then siblings */
1352 node = node->next;
1353 } else if (node != tree) {
1354 /* go up to parents->next if needed */
1355 while (node != tree) {
1356 if (node->parent != NULL) {
1357 node = node->parent;
1358 indent--;
1359 }
1360 if ((node != tree) && (node->next != NULL)) {
1361 node = node->next;
1362 break;
1363 }
1364 if (node->parent == NULL) {
1365 node = NULL;
1366 break;
1367 }
1368 if (node == tree) {
1369 node = NULL;
1370 break;
1371 }
1372 }
1373 /* exit condition */
1374 if (node == tree)
1375 node = NULL;
1376 } else
1377 node = NULL;
1378 }
1379 return(0);
1380}
1381
1382/**
1383 * xmlShellPwd:
1384 * @ctxt: the shell context
1385 * @buffer: the output buffer
1386 * @tree: a node
1387 * @node2: unused
1388 *
1389 * Implements the XML shell function "pwd"
1390 * Show the full path from the root to the node, if needed building
1391 * thumblers when similar elements exists at a given ancestor level.
1392 * The output is compatible with XPath commands.
1393 *
1394 * Returns 0 or -1 in case of error
1395 */
1396int
1397xmlShellPwd(xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node,
1398 xmlNodePtr node2) {
1399 xmlNodePtr cur, tmp, next;
1400 char buf[500];
1401 char sep;
1402 const char *name;
1403 int occur = 0;
1404
1405 buffer[0] = 0;
1406 if (node == NULL) return(-1);
1407 cur = node;
1408 do {
1409 name = "";
1410 sep= '?';
1411 occur = 0;
1412 if ((cur->type == XML_DOCUMENT_NODE) ||
1413 (cur->type == XML_HTML_DOCUMENT_NODE)) {
1414 sep = '/';
1415 next = NULL;
1416 } else if (cur->type == XML_ELEMENT_NODE) {
1417 sep = '/';
1418 name = (const char *)cur->name;
1419 next = cur->parent;
1420
1421 /*
1422 * Thumbler index computation
1423 */
1424 tmp = cur->prev;
1425 while (tmp != NULL) {
1426 if (!xmlStrcmp(cur->name, tmp->name))
1427 occur++;
1428 tmp = tmp->prev;
1429 }
1430 if (occur == 0) {
1431 tmp = cur->next;
1432 while (tmp != NULL) {
1433 if (!xmlStrcmp(cur->name, tmp->name))
1434 occur++;
1435 tmp = tmp->next;
1436 }
1437 if (occur != 0) occur = 1;
1438 } else
1439 occur++;
1440 } else if (cur->type == XML_ATTRIBUTE_NODE) {
1441 sep = '@';
1442 name = (const char *) (((xmlAttrPtr) cur)->name);
Daniel Veillardcf461992000-03-14 18:30:20 +00001443 next = ((xmlAttrPtr) cur)->parent;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001444 } else {
1445 next = cur->parent;
1446 }
1447 if (occur == 0)
1448 sprintf(buf, "%c%s%s", sep, name, buffer);
1449 else
1450 sprintf(buf, "%c%s[%d]%s", sep, name, occur, buffer);
1451 strcpy(buffer, buf);
1452 cur = next;
1453 } while (cur != NULL);
1454 return(0);
1455}
1456
1457/**
1458 * xmlShell
1459 * @doc: the initial document
1460 * @filename: the output buffer
1461 * @input: the line reading function
1462 * @output: the output FILE*
1463 *
1464 * Implements the XML shell
1465 * This allow to load, validate, view, modify and save a document
1466 * using a environment similar to a UNIX commandline.
1467 */
1468void
1469xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
1470 FILE *output) {
1471 char prompt[500] = "/ > ";
1472 char *cmdline = NULL;
1473 int nbargs;
1474 char command[100];
1475 char arg[400];
1476 xmlShellCtxtPtr ctxt;
1477 xmlXPathObjectPtr list;
1478
1479 if (doc == NULL)
1480 return;
1481 if (filename == NULL)
1482 return;
1483 if (input == NULL)
1484 return;
1485 if (output == NULL)
1486 return;
1487 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
1488 if (ctxt == NULL)
1489 return;
1490 ctxt->loaded = 0;
1491 ctxt->doc = doc;
1492 ctxt->input = input;
1493 ctxt->output = output;
1494 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1495 ctxt->node = (xmlNodePtr) ctxt->doc;
1496
Daniel Veillard361d8452000-04-03 19:48:13 +00001497#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001498 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1499 if (ctxt->pctxt == NULL) {
1500 xmlFree(ctxt);
1501 return;
1502 }
Daniel Veillard361d8452000-04-03 19:48:13 +00001503#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001504 while (1) {
1505 if (ctxt->node == (xmlNodePtr) ctxt->doc)
1506 sprintf(prompt, "%s > ", "/");
1507 else if (ctxt->node->name)
1508 sprintf(prompt, "%s > ", ctxt->node->name);
1509 else
1510 sprintf(prompt, "? > ");
1511
1512 cmdline = ctxt->input(prompt);
1513 if (cmdline == NULL) break;
1514
1515 command[0] = 0;
1516 arg[0] = 0;
1517 nbargs = sscanf(cmdline, "%s %s", command, arg);
1518
1519 if (command[0] == 0) continue;
1520 if (!strcmp(command, "exit"))
1521 break;
1522 if (!strcmp(command, "quit"))
1523 break;
1524 if (!strcmp(command, "bye"))
1525 break;
1526 if (!strcmp(command, "validate")) {
1527 xmlShellValidate(ctxt, arg, NULL, NULL);
1528 } else if (!strcmp(command, "load")) {
1529 xmlShellLoad(ctxt, arg, NULL, NULL);
1530 } else if (!strcmp(command, "save")) {
1531 xmlShellSave(ctxt, arg, NULL, NULL);
1532 } else if (!strcmp(command, "write")) {
1533 xmlShellWrite(ctxt, arg, NULL, NULL);
1534 } else if (!strcmp(command, "free")) {
1535 if (arg[0] == 0) {
1536 xmlMemShow(stdout, 0);
1537 } else {
1538 int len = 0;
1539 sscanf(arg, "%d", &len);
1540 xmlMemShow(stdout, len);
1541 }
1542 } else if (!strcmp(command, "pwd")) {
1543 char dir[500];
1544 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
1545 printf("%s\n", dir);
1546 } else if (!strcmp(command, "du")) {
1547 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
1548 } else if ((!strcmp(command, "ls")) ||
1549 (!strcmp(command, "dir"))) {
1550 int dir = (!strcmp(command, "dir"));
1551 if (arg[0] == 0) {
1552 if (dir)
1553 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
1554 else
1555 xmlShellList(ctxt, NULL, ctxt->node, NULL);
1556 } else {
1557 ctxt->pctxt->node = ctxt->node;
Daniel Veillard361d8452000-04-03 19:48:13 +00001558#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001559 if (ctxt->pctxt->nodelist != NULL)
1560 xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1561 ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
1562 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard361d8452000-04-03 19:48:13 +00001563#else
1564 list = NULL;
1565#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001566 if (list != NULL) {
1567 switch (list->type) {
1568 case XPATH_UNDEFINED:
1569 fprintf(stderr, "%s: no such node\n", arg);
1570 break;
1571 case XPATH_NODESET: {
1572 int i;
1573
1574 for (i = 0;i < list->nodesetval->nodeNr;i++) {
1575 if (dir)
1576 xmlShellDir(ctxt, NULL,
1577 list->nodesetval->nodeTab[i], NULL);
1578 else
1579 xmlShellList(ctxt, NULL,
1580 list->nodesetval->nodeTab[i], NULL);
1581 }
1582 break;
1583 }
1584 case XPATH_BOOLEAN:
1585 fprintf(stderr, "%s is a Boolean\n", arg);
1586 break;
1587 case XPATH_NUMBER:
1588 fprintf(stderr, "%s is a number\n", arg);
1589 break;
1590 case XPATH_STRING:
1591 fprintf(stderr, "%s is a string\n", arg);
1592 break;
1593 }
1594 xmlXPathFreeNodeSetList(list);
1595 } else {
1596 fprintf(stderr, "%s: no such node\n", arg);
1597 }
Daniel Veillard361d8452000-04-03 19:48:13 +00001598#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001599 if (ctxt->pctxt->nodelist != NULL)
1600 xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
Daniel Veillard361d8452000-04-03 19:48:13 +00001601#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001602 ctxt->pctxt->nodelist = NULL;
1603 }
1604 } else if (!strcmp(command, "cd")) {
1605 if (arg[0] == 0) {
1606 ctxt->node = (xmlNodePtr) ctxt->doc;
1607 } else {
1608 ctxt->pctxt->node = ctxt->node;
Daniel Veillard361d8452000-04-03 19:48:13 +00001609#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001610 if (ctxt->pctxt->nodelist != NULL)
1611 xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1612 ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
1613 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard361d8452000-04-03 19:48:13 +00001614#else
1615 list = NULL;
1616#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001617 if (list != NULL) {
1618 switch (list->type) {
1619 case XPATH_UNDEFINED:
1620 fprintf(stderr, "%s: no such node\n", arg);
1621 break;
1622 case XPATH_NODESET:
1623 if (list->nodesetval->nodeNr == 1) {
1624 ctxt->node = list->nodesetval->nodeTab[0];
1625 } else
1626 fprintf(stderr, "%s is a %d Node Set\n",
1627 arg, list->nodesetval->nodeNr);
1628 break;
1629 case XPATH_BOOLEAN:
1630 fprintf(stderr, "%s is a Boolean\n", arg);
1631 break;
1632 case XPATH_NUMBER:
1633 fprintf(stderr, "%s is a number\n", arg);
1634 break;
1635 case XPATH_STRING:
1636 fprintf(stderr, "%s is a string\n", arg);
1637 break;
1638 }
1639 xmlXPathFreeNodeSetList(list);
1640 } else {
1641 fprintf(stderr, "%s: no such node\n", arg);
1642 }
Daniel Veillard361d8452000-04-03 19:48:13 +00001643#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001644 if (ctxt->pctxt->nodelist != NULL)
1645 xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
Daniel Veillard361d8452000-04-03 19:48:13 +00001646#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001647 ctxt->pctxt->nodelist = NULL;
1648 }
1649 } else if (!strcmp(command, "cat")) {
1650 if (arg[0] == 0) {
1651 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
1652 } else {
1653 ctxt->pctxt->node = ctxt->node;
Daniel Veillard361d8452000-04-03 19:48:13 +00001654#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001655 if (ctxt->pctxt->nodelist != NULL)
1656 xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1657 ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
1658 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard361d8452000-04-03 19:48:13 +00001659#else
1660 list = NULL;
1661#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001662 if (list != NULL) {
1663 switch (list->type) {
1664 case XPATH_UNDEFINED:
1665 fprintf(stderr, "%s: no such node\n", arg);
1666 break;
1667 case XPATH_NODESET: {
1668 int i;
1669
1670 for (i = 0;i < list->nodesetval->nodeNr;i++) {
1671 if (i > 0) printf(" -------\n");
1672 xmlShellCat(ctxt, NULL,
1673 list->nodesetval->nodeTab[i], NULL);
1674 }
1675 break;
1676 }
1677 case XPATH_BOOLEAN:
1678 fprintf(stderr, "%s is a Boolean\n", arg);
1679 break;
1680 case XPATH_NUMBER:
1681 fprintf(stderr, "%s is a number\n", arg);
1682 break;
1683 case XPATH_STRING:
1684 fprintf(stderr, "%s is a string\n", arg);
1685 break;
1686 }
1687 xmlXPathFreeNodeSetList(list);
1688 } else {
1689 fprintf(stderr, "%s: no such node\n", arg);
1690 }
Daniel Veillard361d8452000-04-03 19:48:13 +00001691#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001692 if (ctxt->pctxt->nodelist != NULL)
1693 xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
Daniel Veillard361d8452000-04-03 19:48:13 +00001694#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001695 ctxt->pctxt->nodelist = NULL;
1696 }
1697 } else {
1698 fprintf(stderr, "Unknown command %s\n", command);
1699 }
1700 free(cmdline); /* not xmlFree here ! */
1701 }
Daniel Veillard361d8452000-04-03 19:48:13 +00001702#ifdef LIBXML_XPATH_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001703 xmlXPathFreeContext(ctxt->pctxt);
Daniel Veillard361d8452000-04-03 19:48:13 +00001704#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001705 if (ctxt->loaded) {
1706 xmlFreeDoc(ctxt->doc);
1707 }
1708 xmlFree(ctxt);
1709 if (cmdline != NULL)
1710 free(cmdline); /* not xmlFree here ! */
1711}
1712
Daniel Veillard361d8452000-04-03 19:48:13 +00001713#endif /* LIBXML_DEBUG_ENABLED */