blob: 57a09fe8f22c3f63bad1b658cd89b2581d791c1f [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
Daniel Veillard34ce8be2002-03-18 19:37:11 +000010#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +000011#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000012#ifdef LIBXML_DEBUG_ENABLED
13
Owen Taylor3473f882001-02-23 17:55:21 +000014#include <string.h>
15#ifdef HAVE_STDLIB_H
16#include <stdlib.h>
17#endif
18#ifdef HAVE_STRING_H
19#include <string.h>
20#endif
21#include <libxml/xmlmemory.h>
22#include <libxml/tree.h>
23#include <libxml/parser.h>
Daniel Veillard567e1b42001-08-01 15:53:47 +000024#include <libxml/parserInternals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000025#include <libxml/valid.h>
26#include <libxml/debugXML.h>
27#include <libxml/HTMLtree.h>
28#include <libxml/HTMLparser.h>
29#include <libxml/xmlerror.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000030#include <libxml/globals.h>
Daniel Veillard0ba59232002-02-10 13:20:39 +000031#include <libxml/xpathInternals.h>
Igor Zlatkovicc06bb622003-04-27 15:59:00 +000032#include <libxml/uri.h>
Owen Taylor3473f882001-02-23 17:55:21 +000033
Daniel Veillard5e2dace2001-07-18 19:30:27 +000034/**
35 * xmlDebugDumpString:
36 * @output: the FILE * for the output
37 * @str: the string
38 *
39 * Dumps informations about the string, shorten it if necessary
40 */
41void
42xmlDebugDumpString(FILE * output, const xmlChar * str)
43{
Owen Taylor3473f882001-02-23 17:55:21 +000044 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000045
Daniel Veillard7db38712002-02-07 16:39:11 +000046 if (output == NULL)
47 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +000048 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000049 fprintf(output, "(NULL)");
50 return;
Owen Taylor3473f882001-02-23 17:55:21 +000051 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000052 for (i = 0; i < 40; i++)
53 if (str[i] == 0)
54 return;
55 else if (IS_BLANK(str[i]))
56 fputc(' ', output);
57 else if (str[i] >= 0x80)
58 fprintf(output, "#%X", str[i]);
59 else
60 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000061 fprintf(output, "...");
62}
63
Daniel Veillard56a4cb82001-03-24 17:00:36 +000064static void
65xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000066 int i;
67 char shift[100];
68
69 for (i = 0;((i < depth) && (i < 25));i++)
70 shift[2 * i] = shift[2 * i + 1] = ' ';
71 shift[2 * i] = shift[2 * i + 1] = 0;
72
73 fprintf(output, shift);
74
Daniel Veillard5e926fa2002-01-22 21:44:25 +000075 if (dtd == NULL) {
76 fprintf(output, "DTD node is NULL\n");
77 return;
78 }
79
Owen Taylor3473f882001-02-23 17:55:21 +000080 if (dtd->type != XML_DTD_NODE) {
81 fprintf(output, "PBM: not a DTD\n");
82 return;
83 }
84 if (dtd->name != NULL)
85 fprintf(output, "DTD(%s)", dtd->name);
86 else
87 fprintf(output, "DTD");
88 if (dtd->ExternalID != NULL)
89 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
90 if (dtd->SystemID != NULL)
91 fprintf(output, ", SYSTEM %s", dtd->SystemID);
92 fprintf(output, "\n");
93 /*
94 * Do a bit of checking
95 */
96 if (dtd->parent == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000097 fprintf(output, "PBM: DTD has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +000098 if (dtd->doc == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +000099 fprintf(output, "PBM: DTD has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000100 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000101 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000102 if (dtd->prev == NULL) {
103 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000104 fprintf(output, "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000105 } else {
106 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000107 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000108 }
109 if (dtd->next == NULL) {
110 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000111 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000112 } else {
113 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000114 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000115 }
116}
117
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000118static void
119xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000120 int i;
121 char shift[100];
122
123 for (i = 0;((i < depth) && (i < 25));i++)
124 shift[2 * i] = shift[2 * i + 1] = ' ';
125 shift[2 * i] = shift[2 * i + 1] = 0;
126
127 fprintf(output, shift);
128
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000129 if (attr == NULL) {
130 fprintf(output, "Attribute declaration is NULL\n");
131 return;
132 }
Owen Taylor3473f882001-02-23 17:55:21 +0000133 if (attr->type != XML_ATTRIBUTE_DECL) {
134 fprintf(output, "PBM: not a Attr\n");
135 return;
136 }
137 if (attr->name != NULL)
138 fprintf(output, "ATTRDECL(%s)", attr->name);
139 else
140 fprintf(output, "PBM ATTRDECL noname!!!");
141 if (attr->elem != NULL)
142 fprintf(output, " for %s", attr->elem);
143 else
144 fprintf(output, " PBM noelem!!!");
145 switch (attr->atype) {
146 case XML_ATTRIBUTE_CDATA:
147 fprintf(output, " CDATA");
148 break;
149 case XML_ATTRIBUTE_ID:
150 fprintf(output, " ID");
151 break;
152 case XML_ATTRIBUTE_IDREF:
153 fprintf(output, " IDREF");
154 break;
155 case XML_ATTRIBUTE_IDREFS:
156 fprintf(output, " IDREFS");
157 break;
158 case XML_ATTRIBUTE_ENTITY:
159 fprintf(output, " ENTITY");
160 break;
161 case XML_ATTRIBUTE_ENTITIES:
162 fprintf(output, " ENTITIES");
163 break;
164 case XML_ATTRIBUTE_NMTOKEN:
165 fprintf(output, " NMTOKEN");
166 break;
167 case XML_ATTRIBUTE_NMTOKENS:
168 fprintf(output, " NMTOKENS");
169 break;
170 case XML_ATTRIBUTE_ENUMERATION:
171 fprintf(output, " ENUMERATION");
172 break;
173 case XML_ATTRIBUTE_NOTATION:
174 fprintf(output, " NOTATION ");
175 break;
176 }
177 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000178 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000179 xmlEnumerationPtr cur = attr->tree;
180
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000181 for (indx = 0;indx < 5; indx++) {
182 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000183 fprintf(output, "|%s", cur->name);
184 else
185 fprintf(output, " (%s", cur->name);
186 cur = cur->next;
187 if (cur == NULL) break;
188 }
189 if (cur == NULL)
190 fprintf(output, ")");
191 else
192 fprintf(output, "...)");
193 }
194 switch (attr->def) {
195 case XML_ATTRIBUTE_NONE:
196 break;
197 case XML_ATTRIBUTE_REQUIRED:
198 fprintf(output, " REQUIRED");
199 break;
200 case XML_ATTRIBUTE_IMPLIED:
201 fprintf(output, " IMPLIED");
202 break;
203 case XML_ATTRIBUTE_FIXED:
204 fprintf(output, " FIXED");
205 break;
206 }
207 if (attr->defaultValue != NULL) {
208 fprintf(output, "\"");
209 xmlDebugDumpString(output, attr->defaultValue);
210 fprintf(output, "\"");
211 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000212 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000213
214 /*
215 * Do a bit of checking
216 */
217 if (attr->parent == NULL)
218 fprintf(output, "PBM: Attr has no parent\n");
219 if (attr->doc == NULL)
220 fprintf(output, "PBM: Attr has no doc\n");
221 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
222 fprintf(output, "PBM: Attr doc differs from parent's one\n");
223 if (attr->prev == NULL) {
224 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
225 fprintf(output, "PBM: Attr has no prev and not first of list\n");
226 } else {
227 if (attr->prev->next != (xmlNodePtr) attr)
228 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
229 }
230 if (attr->next == NULL) {
231 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
232 fprintf(output, "PBM: Attr has no next and not last of list\n");
233 } else {
234 if (attr->next->prev != (xmlNodePtr) attr)
235 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
236 }
237}
238
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000239static void
240xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000241 int i;
242 char shift[100];
243
244 for (i = 0;((i < depth) && (i < 25));i++)
245 shift[2 * i] = shift[2 * i + 1] = ' ';
246 shift[2 * i] = shift[2 * i + 1] = 0;
247
248 fprintf(output, shift);
249
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000250 if (elem == NULL) {
251 fprintf(output, "Element declaration is NULL\n");
252 return;
253 }
Owen Taylor3473f882001-02-23 17:55:21 +0000254 if (elem->type != XML_ELEMENT_DECL) {
255 fprintf(output, "PBM: not a Elem\n");
256 return;
257 }
258 if (elem->name != NULL) {
259 fprintf(output, "ELEMDECL(");
260 xmlDebugDumpString(output, elem->name);
261 fprintf(output, ")");
262 } else
263 fprintf(output, "PBM ELEMDECL noname!!!");
264 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000265 case XML_ELEMENT_TYPE_UNDEFINED:
266 fprintf(output, ", UNDEFINED");
267 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000268 case XML_ELEMENT_TYPE_EMPTY:
269 fprintf(output, ", EMPTY");
270 break;
271 case XML_ELEMENT_TYPE_ANY:
272 fprintf(output, ", ANY");
273 break;
274 case XML_ELEMENT_TYPE_MIXED:
275 fprintf(output, ", MIXED ");
276 break;
277 case XML_ELEMENT_TYPE_ELEMENT:
278 fprintf(output, ", MIXED ");
279 break;
280 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000281 if ((elem->type != XML_ELEMENT_NODE) &&
282 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000283 char buf[5001];
284
285 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000286 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000287 buf[5000] = 0;
288 fprintf(output, "%s", buf);
289 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000290 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000291
292 /*
293 * Do a bit of checking
294 */
295 if (elem->parent == NULL)
296 fprintf(output, "PBM: Elem has no parent\n");
297 if (elem->doc == NULL)
298 fprintf(output, "PBM: Elem has no doc\n");
299 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
300 fprintf(output, "PBM: Elem doc differs from parent's one\n");
301 if (elem->prev == NULL) {
302 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
303 fprintf(output, "PBM: Elem has no prev and not first of list\n");
304 } else {
305 if (elem->prev->next != (xmlNodePtr) elem)
306 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
307 }
308 if (elem->next == NULL) {
309 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
310 fprintf(output, "PBM: Elem has no next and not last of list\n");
311 } else {
312 if (elem->next->prev != (xmlNodePtr) elem)
313 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
314 }
315}
316
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000317static void
318xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000319 int i;
320 char shift[100];
321
322 for (i = 0;((i < depth) && (i < 25));i++)
323 shift[2 * i] = shift[2 * i + 1] = ' ';
324 shift[2 * i] = shift[2 * i + 1] = 0;
325
326 fprintf(output, shift);
327
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000328 if (ent == NULL) {
329 fprintf(output, "Entity declaration is NULL\n");
330 return;
331 }
Owen Taylor3473f882001-02-23 17:55:21 +0000332 if (ent->type != XML_ENTITY_DECL) {
333 fprintf(output, "PBM: not a Entity decl\n");
334 return;
335 }
336 if (ent->name != NULL) {
337 fprintf(output, "ENTITYDECL(");
338 xmlDebugDumpString(output, ent->name);
339 fprintf(output, ")");
340 } else
341 fprintf(output, "PBM ENTITYDECL noname!!!");
342 switch (ent->etype) {
343 case XML_INTERNAL_GENERAL_ENTITY:
344 fprintf(output, ", internal\n");
345 break;
346 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
347 fprintf(output, ", external parsed\n");
348 break;
349 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
350 fprintf(output, ", unparsed\n");
351 break;
352 case XML_INTERNAL_PARAMETER_ENTITY:
353 fprintf(output, ", parameter\n");
354 break;
355 case XML_EXTERNAL_PARAMETER_ENTITY:
356 fprintf(output, ", external parameter\n");
357 break;
358 case XML_INTERNAL_PREDEFINED_ENTITY:
359 fprintf(output, ", predefined\n");
360 break;
361 }
362 if (ent->ExternalID) {
363 fprintf(output, shift);
364 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
365 }
366 if (ent->SystemID) {
367 fprintf(output, shift);
368 fprintf(output, " SystemID=%s\n", ent->SystemID);
369 }
370 if (ent->URI != NULL) {
371 fprintf(output, shift);
372 fprintf(output, " URI=%s\n", ent->URI);
373 }
374 if (ent->content) {
375 fprintf(output, shift);
376 fprintf(output, " content=");
377 xmlDebugDumpString(output, ent->content);
378 fprintf(output, "\n");
379 }
380
381 /*
382 * Do a bit of checking
383 */
384 if (ent->parent == NULL)
385 fprintf(output, "PBM: Ent has no parent\n");
386 if (ent->doc == NULL)
387 fprintf(output, "PBM: Ent has no doc\n");
388 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
389 fprintf(output, "PBM: Ent doc differs from parent's one\n");
390 if (ent->prev == NULL) {
391 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
392 fprintf(output, "PBM: Ent has no prev and not first of list\n");
393 } else {
394 if (ent->prev->next != (xmlNodePtr) ent)
395 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
396 }
397 if (ent->next == NULL) {
398 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
399 fprintf(output, "PBM: Ent has no next and not last of list\n");
400 } else {
401 if (ent->next->prev != (xmlNodePtr) ent)
402 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
403 }
404}
405
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000406static void
407xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000408 int i;
409 char shift[100];
410
411 for (i = 0;((i < depth) && (i < 25));i++)
412 shift[2 * i] = shift[2 * i + 1] = ' ';
413 shift[2 * i] = shift[2 * i + 1] = 0;
414
415 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000416
417 if (ns == NULL) {
418 fprintf(output, "namespace node is NULL\n");
419 return;
420 }
Owen Taylor3473f882001-02-23 17:55:21 +0000421 if (ns->type != XML_NAMESPACE_DECL) {
422 fprintf(output, "invalid namespace node %d\n", ns->type);
423 return;
424 }
425 if (ns->href == NULL) {
426 if (ns->prefix != NULL)
427 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
428 else
429 fprintf(output, "incomplete default namespace href=NULL\n");
430 } else {
431 if (ns->prefix != NULL)
432 fprintf(output, "namespace %s href=", ns->prefix);
433 else
434 fprintf(output, "default namespace href=");
435
436 xmlDebugDumpString(output, ns->href);
437 fprintf(output, "\n");
438 }
439}
440
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000441static void
442xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000443 while (ns != NULL) {
444 xmlDebugDumpNamespace(output, ns, depth);
445 ns = ns->next;
446 }
447}
448
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000449static void
450xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000451 int i;
452 char shift[100];
453
454 for (i = 0;((i < depth) && (i < 25));i++)
455 shift[2 * i] = shift[2 * i + 1] = ' ';
456 shift[2 * i] = shift[2 * i + 1] = 0;
457
458 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000459
460 if (ent == NULL) {
461 fprintf(output, "Entity is NULL\n");
462 return;
463 }
Owen Taylor3473f882001-02-23 17:55:21 +0000464 switch (ent->etype) {
465 case XML_INTERNAL_GENERAL_ENTITY:
466 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
467 break;
468 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
469 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
470 break;
471 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
472 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
473 break;
474 case XML_INTERNAL_PARAMETER_ENTITY:
475 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
476 break;
477 case XML_EXTERNAL_PARAMETER_ENTITY:
478 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
479 break;
480 default:
481 fprintf(output, "ENTITY_%d ! ", ent->etype);
482 }
483 fprintf(output, "%s\n", ent->name);
484 if (ent->ExternalID) {
485 fprintf(output, shift);
486 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
487 }
488 if (ent->SystemID) {
489 fprintf(output, shift);
490 fprintf(output, "SystemID=%s\n", ent->SystemID);
491 }
492 if (ent->URI) {
493 fprintf(output, shift);
494 fprintf(output, "URI=%s\n", ent->URI);
495 }
496 if (ent->content) {
497 fprintf(output, shift);
498 fprintf(output, "content=");
499 xmlDebugDumpString(output, ent->content);
500 fprintf(output, "\n");
501 }
502}
503
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000504/**
505 * xmlDebugDumpAttr:
506 * @output: the FILE * for the output
507 * @attr: the attribute
508 * @depth: the indentation level.
509 *
510 * Dumps debug information for the attribute
511 */
512void
513xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000514 int i;
515 char shift[100];
516
517 for (i = 0;((i < depth) && (i < 25));i++)
518 shift[2 * i] = shift[2 * i + 1] = ' ';
519 shift[2 * i] = shift[2 * i + 1] = 0;
520
521 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000522
523 if (attr == NULL) {
524 fprintf(output, "Attr is NULL");
525 return;
526 }
Owen Taylor3473f882001-02-23 17:55:21 +0000527 fprintf(output, "ATTRIBUTE ");
528 xmlDebugDumpString(output, attr->name);
529 fprintf(output, "\n");
530 if (attr->children != NULL)
531 xmlDebugDumpNodeList(output, attr->children, depth + 1);
532
533 /*
534 * Do a bit of checking
535 */
536 if (attr->parent == NULL)
537 fprintf(output, "PBM: Attr has no parent\n");
538 if (attr->doc == NULL)
539 fprintf(output, "PBM: Attr has no doc\n");
540 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
541 fprintf(output, "PBM: Attr doc differs from parent's one\n");
542 if (attr->prev == NULL) {
543 if ((attr->parent != NULL) && (attr->parent->properties != attr))
544 fprintf(output, "PBM: Attr has no prev and not first of list\n");
545 } else {
546 if (attr->prev->next != attr)
547 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
548 }
549 if (attr->next != NULL) {
550 if (attr->next->prev != attr)
551 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
552 }
553}
554
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000555/**
556 * xmlDebugDumpAttrList:
557 * @output: the FILE * for the output
558 * @attr: the attribute list
559 * @depth: the indentation level.
560 *
561 * Dumps debug information for the attribute list
562 */
563void
564xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
565{
Daniel Veillard7db38712002-02-07 16:39:11 +0000566 if (output == NULL)
567 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000568 while (attr != NULL) {
569 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000570 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000571 }
572}
573
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000574/**
575 * xmlDebugDumpOneNode:
576 * @output: the FILE * for the output
577 * @node: the node
578 * @depth: the indentation level.
579 *
580 * Dumps debug information for the element node, it is not recursive
581 */
582void
583xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
584{
Owen Taylor3473f882001-02-23 17:55:21 +0000585 int i;
586 char shift[100];
587
Daniel Veillard7db38712002-02-07 16:39:11 +0000588 if (output == NULL)
589 output = stdout;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000590 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000591 shift[2 * i] = shift[2 * i + 1] = ' ';
592 shift[2 * i] = shift[2 * i + 1] = 0;
593
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000594 if (node == NULL) {
595 fprintf(output, shift);
596 fprintf(output, "node is NULL\n");
597 return;
598 }
Owen Taylor3473f882001-02-23 17:55:21 +0000599 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000600 case XML_ELEMENT_NODE:
601 fprintf(output, shift);
602 fprintf(output, "ELEMENT ");
603 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
604 xmlDebugDumpString(output, node->ns->prefix);
605 fprintf(output, ":");
606 }
607 xmlDebugDumpString(output, node->name);
608 fprintf(output, "\n");
609 break;
610 case XML_ATTRIBUTE_NODE:
611 fprintf(output, shift);
612 fprintf(output, "Error, ATTRIBUTE found here\n");
613 break;
614 case XML_TEXT_NODE:
615 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000616 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000617 fprintf(output, "TEXT no enc\n");
618 else
619 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000620 break;
621 case XML_CDATA_SECTION_NODE:
622 fprintf(output, shift);
623 fprintf(output, "CDATA_SECTION\n");
624 break;
625 case XML_ENTITY_REF_NODE:
626 fprintf(output, shift);
627 fprintf(output, "ENTITY_REF(%s)\n", node->name);
628 break;
629 case XML_ENTITY_NODE:
630 fprintf(output, shift);
631 fprintf(output, "ENTITY\n");
632 break;
633 case XML_PI_NODE:
634 fprintf(output, shift);
635 fprintf(output, "PI %s\n", node->name);
636 break;
637 case XML_COMMENT_NODE:
638 fprintf(output, shift);
639 fprintf(output, "COMMENT\n");
640 break;
641 case XML_DOCUMENT_NODE:
642 case XML_HTML_DOCUMENT_NODE:
643 fprintf(output, shift);
644 fprintf(output, "Error, DOCUMENT found here\n");
645 break;
646 case XML_DOCUMENT_TYPE_NODE:
647 fprintf(output, shift);
648 fprintf(output, "DOCUMENT_TYPE\n");
649 break;
650 case XML_DOCUMENT_FRAG_NODE:
651 fprintf(output, shift);
652 fprintf(output, "DOCUMENT_FRAG\n");
653 break;
654 case XML_NOTATION_NODE:
655 fprintf(output, shift);
656 fprintf(output, "NOTATION\n");
657 break;
658 case XML_DTD_NODE:
659 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
660 return;
661 case XML_ELEMENT_DECL:
662 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
663 return;
664 case XML_ATTRIBUTE_DECL:
665 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
666 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000667 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000668 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
669 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000670 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000671 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
672 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000673 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000674 fprintf(output, shift);
675 fprintf(output, "INCLUDE START\n");
676 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000677 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000678 fprintf(output, shift);
679 fprintf(output, "INCLUDE END\n");
680 return;
681 default:
682 fprintf(output, shift);
683 fprintf(output, "NODE_%d !!!\n", node->type);
684 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000685 }
686 if (node->doc == NULL) {
687 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000688 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000689 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000690 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000691 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
692 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000693 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000694 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000695 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
696 shift[2 * i] = shift[2 * i + 1] = ' ';
697 shift[2 * i + 2] = shift[2 * i + 3] = 0;
698 fprintf(output, shift);
699 fprintf(output, "content=");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000700 xmlDebugDumpString(output, node->content);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000701 fprintf(output, "\n");
702 }
Owen Taylor3473f882001-02-23 17:55:21 +0000703 } else {
704 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000705
706 ent = xmlGetDocEntity(node->doc, node->name);
707 if (ent != NULL)
708 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000709 }
710 /*
711 * Do a bit of checking
712 */
713 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000714 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000715 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000716 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000717 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000718 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000719 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000720 if ((node->parent != NULL) && (node->parent->children != node))
721 fprintf(output,
722 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000723 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000724 if (node->prev->next != node)
725 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000726 }
727 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000728 if ((node->parent != NULL) && (node->parent->last != node))
729 fprintf(output,
730 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000731 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000732 if (node->next->prev != node)
733 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000734 }
735}
736
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000737/**
738 * xmlDebugDumpNode:
739 * @output: the FILE * for the output
740 * @node: the node
741 * @depth: the indentation level.
742 *
743 * Dumps debug information for the element node, it is recursive
744 */
745void
746xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
747{
Daniel Veillard7db38712002-02-07 16:39:11 +0000748 if (output == NULL)
749 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000750 if (node == NULL) {
751 int i;
752 char shift[100];
753
754 for (i = 0; ((i < depth) && (i < 25)); i++)
755 shift[2 * i] = shift[2 * i + 1] = ' ';
756 shift[2 * i] = shift[2 * i + 1] = 0;
757
758 fprintf(output, shift);
759 fprintf(output, "node is NULL\n");
760 return;
761 }
Owen Taylor3473f882001-02-23 17:55:21 +0000762 xmlDebugDumpOneNode(output, node, depth);
763 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000764 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000765}
766
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000767/**
768 * xmlDebugDumpNodeList:
769 * @output: the FILE * for the output
770 * @node: the node list
771 * @depth: the indentation level.
772 *
773 * Dumps debug information for the list of element node, it is recursive
774 */
775void
776xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
777{
Daniel Veillard7db38712002-02-07 16:39:11 +0000778 if (output == NULL)
779 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000780 while (node != NULL) {
781 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000782 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000783 }
784}
785
786
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000787/**
788 * xmlDebugDumpDocumentHead:
789 * @output: the FILE * for the output
790 * @doc: the document
791 *
792 * Dumps debug information cncerning the document, not recursive
793 */
794void
795xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
796{
797 if (output == NULL)
798 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000799 if (doc == NULL) {
800 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000801 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000802 }
803
804 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000805 case XML_ELEMENT_NODE:
806 fprintf(output, "Error, ELEMENT found here ");
807 break;
808 case XML_ATTRIBUTE_NODE:
809 fprintf(output, "Error, ATTRIBUTE found here\n");
810 break;
811 case XML_TEXT_NODE:
812 fprintf(output, "Error, TEXT\n");
813 break;
814 case XML_CDATA_SECTION_NODE:
815 fprintf(output, "Error, CDATA_SECTION\n");
816 break;
817 case XML_ENTITY_REF_NODE:
818 fprintf(output, "Error, ENTITY_REF\n");
819 break;
820 case XML_ENTITY_NODE:
821 fprintf(output, "Error, ENTITY\n");
822 break;
823 case XML_PI_NODE:
824 fprintf(output, "Error, PI\n");
825 break;
826 case XML_COMMENT_NODE:
827 fprintf(output, "Error, COMMENT\n");
828 break;
829 case XML_DOCUMENT_NODE:
830 fprintf(output, "DOCUMENT\n");
831 break;
832 case XML_HTML_DOCUMENT_NODE:
833 fprintf(output, "HTML DOCUMENT\n");
834 break;
835 case XML_DOCUMENT_TYPE_NODE:
836 fprintf(output, "Error, DOCUMENT_TYPE\n");
837 break;
838 case XML_DOCUMENT_FRAG_NODE:
839 fprintf(output, "Error, DOCUMENT_FRAG\n");
840 break;
841 case XML_NOTATION_NODE:
842 fprintf(output, "Error, NOTATION\n");
843 break;
844 default:
845 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000846 }
847 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000848 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000849 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000850 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000851 }
852 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000853 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000854 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000855 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000856 }
857 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000858 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000859 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000860 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000861 }
862 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000863 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000864 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000865 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000866 }
867 if (doc->standalone)
868 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000869 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000870 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
871}
872
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000873/**
874 * xmlDebugDumpDocument:
875 * @output: the FILE * for the output
876 * @doc: the document
877 *
878 * Dumps debug information for the document, it's recursive
879 */
880void
881xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
882{
883 if (output == NULL)
884 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000885 if (doc == NULL) {
886 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000887 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000888 }
889 xmlDebugDumpDocumentHead(output, doc);
890 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000891 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000892 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000893}
Owen Taylor3473f882001-02-23 17:55:21 +0000894
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000895/**
896 * xmlDebugDumpDTD:
897 * @output: the FILE * for the output
898 * @dtd: the DTD
899 *
900 * Dumps debug information for the DTD
901 */
902void
903xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
904{
Daniel Veillard7db38712002-02-07 16:39:11 +0000905 if (output == NULL)
906 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000907 if (dtd == NULL) {
908 fprintf(output, "DTD is NULL\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000909 return;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000910 }
Owen Taylor3473f882001-02-23 17:55:21 +0000911 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000912 fprintf(output, "PBM: not a DTD\n");
913 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000914 }
915 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000916 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000917 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000918 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000919 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000920 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000921 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000922 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000923 fprintf(output, "\n");
924 /*
925 * Do a bit of checking
926 */
927 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000928 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000929 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000930 if ((dtd->parent != NULL)
931 && (dtd->parent->children != (xmlNodePtr) dtd))
932 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000933 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000934 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000935 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000936 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000937 }
938 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000939 if ((dtd->parent != NULL)
940 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000941 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000942 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000943 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000944 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000945 }
946 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000947 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000948 else
949 xmlDebugDumpNodeList(output, dtd->children, 1);
950}
951
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000952static void
953xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000954 if (cur == NULL) {
955 fprintf(output, "Entity is NULL");
956 return;
957 }
Owen Taylor3473f882001-02-23 17:55:21 +0000958 fprintf(output, "%s : ", cur->name);
959 switch (cur->etype) {
960 case XML_INTERNAL_GENERAL_ENTITY:
961 fprintf(output, "INTERNAL GENERAL, ");
962 break;
963 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
964 fprintf(output, "EXTERNAL PARSED, ");
965 break;
966 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
967 fprintf(output, "EXTERNAL UNPARSED, ");
968 break;
969 case XML_INTERNAL_PARAMETER_ENTITY:
970 fprintf(output, "INTERNAL PARAMETER, ");
971 break;
972 case XML_EXTERNAL_PARAMETER_ENTITY:
973 fprintf(output, "EXTERNAL PARAMETER, ");
974 break;
975 default:
976 fprintf(output, "UNKNOWN TYPE %d",
977 cur->etype);
978 }
979 if (cur->ExternalID != NULL)
980 fprintf(output, "ID \"%s\"", cur->ExternalID);
981 if (cur->SystemID != NULL)
982 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
983 if (cur->orig != NULL)
984 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000985 if ((cur->type != XML_ELEMENT_NODE) &&
986 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000987 fprintf(output, "\n content \"%s\"", cur->content);
988 fprintf(output, "\n");
989}
990
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000991/**
992 * xmlDebugDumpEntities:
993 * @output: the FILE * for the output
994 * @doc: the document
995 *
996 * Dumps debug information for all the entities in use by the document
997 */
998void
999xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1000{
1001 if (output == NULL)
1002 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001003 if (doc == NULL) {
1004 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001005 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001006 }
1007
1008 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001009 case XML_ELEMENT_NODE:
1010 fprintf(output, "Error, ELEMENT found here ");
1011 break;
1012 case XML_ATTRIBUTE_NODE:
1013 fprintf(output, "Error, ATTRIBUTE found here\n");
1014 break;
1015 case XML_TEXT_NODE:
1016 fprintf(output, "Error, TEXT\n");
1017 break;
1018 case XML_CDATA_SECTION_NODE:
1019 fprintf(output, "Error, CDATA_SECTION\n");
1020 break;
1021 case XML_ENTITY_REF_NODE:
1022 fprintf(output, "Error, ENTITY_REF\n");
1023 break;
1024 case XML_ENTITY_NODE:
1025 fprintf(output, "Error, ENTITY\n");
1026 break;
1027 case XML_PI_NODE:
1028 fprintf(output, "Error, PI\n");
1029 break;
1030 case XML_COMMENT_NODE:
1031 fprintf(output, "Error, COMMENT\n");
1032 break;
1033 case XML_DOCUMENT_NODE:
1034 fprintf(output, "DOCUMENT\n");
1035 break;
1036 case XML_HTML_DOCUMENT_NODE:
1037 fprintf(output, "HTML DOCUMENT\n");
1038 break;
1039 case XML_DOCUMENT_TYPE_NODE:
1040 fprintf(output, "Error, DOCUMENT_TYPE\n");
1041 break;
1042 case XML_DOCUMENT_FRAG_NODE:
1043 fprintf(output, "Error, DOCUMENT_FRAG\n");
1044 break;
1045 case XML_NOTATION_NODE:
1046 fprintf(output, "Error, NOTATION\n");
1047 break;
1048 default:
1049 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +00001050 }
1051 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001052 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1053 doc->intSubset->entities;
1054
1055 fprintf(output, "Entities in internal subset\n");
1056 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1057 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001058 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001059 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001060 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001061 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1062 doc->extSubset->entities;
1063
1064 fprintf(output, "Entities in external subset\n");
1065 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1066 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001067 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001068 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001069}
1070
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001071/**
1072 * xmlLsCountNode:
1073 * @node: the node to count
1074 *
1075 * Count the children of @node.
1076 *
1077 * Returns the number of children of @node.
1078 */
1079int
1080xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001081 int ret = 0;
1082 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001083
1084 if (node == NULL)
1085 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001086
1087 switch (node->type) {
1088 case XML_ELEMENT_NODE:
1089 list = node->children;
1090 break;
1091 case XML_DOCUMENT_NODE:
1092 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001093#ifdef LIBXML_DOCB_ENABLED
1094 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001095#endif
1096 list = ((xmlDocPtr) node)->children;
1097 break;
1098 case XML_ATTRIBUTE_NODE:
1099 list = ((xmlAttrPtr) node)->children;
1100 break;
1101 case XML_TEXT_NODE:
1102 case XML_CDATA_SECTION_NODE:
1103 case XML_PI_NODE:
1104 case XML_COMMENT_NODE:
1105 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001106 ret = xmlStrlen(node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001107 }
1108 break;
1109 case XML_ENTITY_REF_NODE:
1110 case XML_DOCUMENT_TYPE_NODE:
1111 case XML_ENTITY_NODE:
1112 case XML_DOCUMENT_FRAG_NODE:
1113 case XML_NOTATION_NODE:
1114 case XML_DTD_NODE:
1115 case XML_ELEMENT_DECL:
1116 case XML_ATTRIBUTE_DECL:
1117 case XML_ENTITY_DECL:
1118 case XML_NAMESPACE_DECL:
1119 case XML_XINCLUDE_START:
1120 case XML_XINCLUDE_END:
1121 ret = 1;
1122 break;
1123 }
1124 for (;list != NULL;ret++)
1125 list = list->next;
1126 return(ret);
1127}
1128
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001129/**
1130 * xmlLsOneNode:
1131 * @output: the FILE * for the output
1132 * @node: the node to dump
1133 *
1134 * Dump to @output the type and name of @node.
1135 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001136void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001137xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001138 if (node == NULL) {
1139 fprintf(output, "NULL\n");
1140 return;
1141 }
Owen Taylor3473f882001-02-23 17:55:21 +00001142 switch (node->type) {
1143 case XML_ELEMENT_NODE:
1144 fprintf(output, "-");
1145 break;
1146 case XML_ATTRIBUTE_NODE:
1147 fprintf(output, "a");
1148 break;
1149 case XML_TEXT_NODE:
1150 fprintf(output, "t");
1151 break;
1152 case XML_CDATA_SECTION_NODE:
Daniel Veillard75be0132002-03-13 10:03:35 +00001153 fprintf(output, "C");
Owen Taylor3473f882001-02-23 17:55:21 +00001154 break;
1155 case XML_ENTITY_REF_NODE:
1156 fprintf(output, "e");
1157 break;
1158 case XML_ENTITY_NODE:
1159 fprintf(output, "E");
1160 break;
1161 case XML_PI_NODE:
1162 fprintf(output, "p");
1163 break;
1164 case XML_COMMENT_NODE:
1165 fprintf(output, "c");
1166 break;
1167 case XML_DOCUMENT_NODE:
1168 fprintf(output, "d");
1169 break;
1170 case XML_HTML_DOCUMENT_NODE:
1171 fprintf(output, "h");
1172 break;
1173 case XML_DOCUMENT_TYPE_NODE:
1174 fprintf(output, "T");
1175 break;
1176 case XML_DOCUMENT_FRAG_NODE:
1177 fprintf(output, "F");
1178 break;
1179 case XML_NOTATION_NODE:
1180 fprintf(output, "N");
1181 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001182 case XML_NAMESPACE_DECL:
1183 fprintf(output, "n");
1184 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001185 default:
1186 fprintf(output, "?");
1187 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001188 if (node->type != XML_NAMESPACE_DECL) {
1189 if (node->properties != NULL)
1190 fprintf(output, "a");
1191 else
1192 fprintf(output, "-");
1193 if (node->nsDef != NULL)
1194 fprintf(output, "n");
1195 else
1196 fprintf(output, "-");
1197 }
Owen Taylor3473f882001-02-23 17:55:21 +00001198
1199 fprintf(output, " %8d ", xmlLsCountNode(node));
1200
1201 switch (node->type) {
1202 case XML_ELEMENT_NODE:
1203 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001204 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001205 break;
1206 case XML_ATTRIBUTE_NODE:
1207 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001208 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001209 break;
1210 case XML_TEXT_NODE:
1211 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001212 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001213 }
1214 break;
1215 case XML_CDATA_SECTION_NODE:
1216 break;
1217 case XML_ENTITY_REF_NODE:
1218 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001219 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001220 break;
1221 case XML_ENTITY_NODE:
1222 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001223 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001224 break;
1225 case XML_PI_NODE:
1226 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001227 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001228 break;
1229 case XML_COMMENT_NODE:
1230 break;
1231 case XML_DOCUMENT_NODE:
1232 break;
1233 case XML_HTML_DOCUMENT_NODE:
1234 break;
1235 case XML_DOCUMENT_TYPE_NODE:
1236 break;
1237 case XML_DOCUMENT_FRAG_NODE:
1238 break;
1239 case XML_NOTATION_NODE:
1240 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001241 case XML_NAMESPACE_DECL: {
1242 xmlNsPtr ns = (xmlNsPtr) node;
1243
1244 if (ns->prefix == NULL)
1245 fprintf(output, "default -> %s", ns->href);
1246 else
1247 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1248 break;
1249 }
Owen Taylor3473f882001-02-23 17:55:21 +00001250 default:
1251 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001252 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001253 }
1254 fprintf(output, "\n");
1255}
1256
Daniel Veillard78d12092001-10-11 09:12:24 +00001257/**
1258 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001259 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001260 *
1261 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001262 *
1263 * Returns a pointer to either "True" or "False"
1264 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001265const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001266xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001267{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001268 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001269 return("True");
1270 else
1271 return("False");
1272}
1273
Owen Taylor3473f882001-02-23 17:55:21 +00001274/****************************************************************
1275 * *
1276 * The XML shell related functions *
1277 * *
1278 ****************************************************************/
1279
Daniel Veillard78d12092001-10-11 09:12:24 +00001280
1281
Owen Taylor3473f882001-02-23 17:55:21 +00001282/*
1283 * TODO: Improvement/cleanups for the XML shell
1284 * - allow to shell out an editor on a subpart
1285 * - cleanup function registrations (with help) and calling
1286 * - provide registration routines
1287 */
1288
1289/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001290 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001291 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001292 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001293 *
1294 * Print the xpath error to libxml default error channel
1295 */
1296void
1297xmlShellPrintXPathError(int errorType, const char *arg)
1298{
1299 const char *default_arg = "Result";
1300
1301 if (!arg)
1302 arg = default_arg;
1303
1304 switch (errorType) {
1305 case XPATH_UNDEFINED:
1306 xmlGenericError(xmlGenericErrorContext,
1307 "%s: no such node\n", arg);
1308 break;
1309
1310 case XPATH_BOOLEAN:
1311 xmlGenericError(xmlGenericErrorContext,
1312 "%s is a Boolean\n", arg);
1313 break;
1314 case XPATH_NUMBER:
1315 xmlGenericError(xmlGenericErrorContext,
1316 "%s is a number\n", arg);
1317 break;
1318 case XPATH_STRING:
1319 xmlGenericError(xmlGenericErrorContext,
1320 "%s is a string\n", arg);
1321 break;
1322 case XPATH_POINT:
1323 xmlGenericError(xmlGenericErrorContext,
1324 "%s is a point\n", arg);
1325 break;
1326 case XPATH_RANGE:
1327 xmlGenericError(xmlGenericErrorContext,
1328 "%s is a range\n", arg);
1329 break;
1330 case XPATH_LOCATIONSET:
1331 xmlGenericError(xmlGenericErrorContext,
1332 "%s is a range\n", arg);
1333 break;
1334 case XPATH_USERS:
1335 xmlGenericError(xmlGenericErrorContext,
1336 "%s is user-defined\n", arg);
1337 break;
1338 case XPATH_XSLT_TREE:
1339 xmlGenericError(xmlGenericErrorContext,
1340 "%s is an XSLT value tree\n", arg);
1341 break;
1342 }
1343 xmlGenericError(xmlGenericErrorContext,
1344 "Try casting the result string function (xpath builtin)\n",
1345 arg);
1346}
1347
1348
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001349#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001350/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001351 * xmlShellPrintNodeCtxt:
1352 * @ctxt : a non-null shell context
1353 * @node : a non-null node to print to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001354 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001355 * Print node to the output FILE
1356 */
1357static void
1358xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1359{
Daniel Veillard01992e02002-10-09 10:20:30 +00001360 FILE *fp;
1361
1362 if (!node)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001363 return;
Daniel Veillard01992e02002-10-09 10:20:30 +00001364 if (ctxt == NULL)
1365 fp = stdout;
1366 else
1367 fp = ctxt->output;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001368
1369 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001370 xmlDocDump(fp, (xmlDocPtr) node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001371 else if (node->type == XML_ATTRIBUTE_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001372 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001373 else
Daniel Veillard01992e02002-10-09 10:20:30 +00001374 xmlElemDump(fp, node->doc, node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001375
Daniel Veillard01992e02002-10-09 10:20:30 +00001376 fprintf(fp, "\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00001377}
1378
1379/**
1380 * xmlShellPrintNode:
1381 * @node : a non-null node to print to the output FILE
1382 *
1383 * Print node to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001384 */
1385void
1386xmlShellPrintNode(xmlNodePtr node)
1387{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001388 xmlShellPrintNodeCtxt(NULL, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001389}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001390#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001391
Daniel Veillard78d12092001-10-11 09:12:24 +00001392/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001393 * xmlShellPrintXPathResultCtxt:
1394 * @ctxt: a valid shell context
Daniel Veillard9d06d302002-01-22 18:15:52 +00001395 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001396 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001397 * Prints result to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001398 */
Daniel Veillard321be0c2002-10-08 21:26:42 +00001399static void
1400xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
Daniel Veillard78d12092001-10-11 09:12:24 +00001401{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001402 if (!ctxt)
1403 return;
Daniel Veillard78d12092001-10-11 09:12:24 +00001404
1405 if (list != NULL) {
1406 switch (list->type) {
1407 case XPATH_NODESET:{
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001408#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001409 int indx;
1410
1411 if (list->nodesetval) {
1412 for (indx = 0; indx < list->nodesetval->nodeNr;
1413 indx++) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001414 xmlShellPrintNodeCtxt(ctxt,
1415 list->nodesetval->nodeTab[indx]);
Daniel Veillard78d12092001-10-11 09:12:24 +00001416 }
1417 } else {
1418 xmlGenericError(xmlGenericErrorContext,
1419 "Empty node set\n");
1420 }
1421 break;
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001422#else
1423 xmlGenericError(xmlGenericErrorContext,
1424 "Node set\n");
1425#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001426 }
1427 case XPATH_BOOLEAN:
1428 xmlGenericError(xmlGenericErrorContext,
1429 "Is a Boolean:%s\n",
1430 xmlBoolToText(list->boolval));
1431 break;
1432 case XPATH_NUMBER:
1433 xmlGenericError(xmlGenericErrorContext,
1434 "Is a number:%0g\n", list->floatval);
1435 break;
1436 case XPATH_STRING:
1437 xmlGenericError(xmlGenericErrorContext,
1438 "Is a string:%s\n", list->stringval);
1439 break;
1440
1441 default:
1442 xmlShellPrintXPathError(list->type, NULL);
1443 }
1444 }
1445}
1446
1447/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001448 * xmlShellPrintXPathResult:
1449 * @list: a valid result generated by an xpath evaluation
1450 *
1451 * Prints result to the output FILE
1452 */
1453void
1454xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1455{
1456 xmlShellPrintXPathResultCtxt(NULL, list);
1457}
1458
1459/**
Owen Taylor3473f882001-02-23 17:55:21 +00001460 * xmlShellList:
1461 * @ctxt: the shell context
1462 * @arg: unused
1463 * @node: a node
1464 * @node2: unused
1465 *
1466 * Implements the XML shell function "ls"
1467 * Does an Unix like listing of the given node (like a directory)
1468 *
1469 * Returns 0
1470 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001471int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001472xmlShellList(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001473 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1474 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1475{
Owen Taylor3473f882001-02-23 17:55:21 +00001476 xmlNodePtr cur;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001477 if (!ctxt)
1478 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001479 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001480 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001481 return (0);
1482 }
Owen Taylor3473f882001-02-23 17:55:21 +00001483 if ((node->type == XML_DOCUMENT_NODE) ||
1484 (node->type == XML_HTML_DOCUMENT_NODE)) {
1485 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001486 } else if (node->type == XML_NAMESPACE_DECL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001487 xmlLsOneNode(ctxt->output, node);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001488 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001489 } else if (node->children != NULL) {
1490 cur = node->children;
1491 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001492 xmlLsOneNode(ctxt->output, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001493 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001494 }
1495 while (cur != NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001496 xmlLsOneNode(ctxt->output, cur);
Daniel Veillard78d12092001-10-11 09:12:24 +00001497 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001498 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001499 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001500}
1501
1502/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001503 * xmlShellBase:
1504 * @ctxt: the shell context
1505 * @arg: unused
1506 * @node: a node
1507 * @node2: unused
1508 *
1509 * Implements the XML shell function "base"
1510 * dumps the current XML base of the node
1511 *
1512 * Returns 0
1513 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001514int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001515xmlShellBase(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001516 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1517 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1518{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001519 xmlChar *base;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001520 if (!ctxt)
1521 return 0;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001522 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001523 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001524 return (0);
1525 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001526
1527 base = xmlNodeGetBase(node->doc, node);
1528
1529 if (base == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001530 fprintf(ctxt->output, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001531 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001532 fprintf(ctxt->output, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001533 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001534 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001535 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001536}
1537
1538/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001539 * xmlShellSetBase:
1540 * @ctxt: the shell context
1541 * @arg: the new base
1542 * @node: a node
1543 * @node2: unused
1544 *
1545 * Implements the XML shell function "setbase"
1546 * change the current XML base of the node
1547 *
1548 * Returns 0
1549 */
1550static int
1551xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1552 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1553 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1554{
1555 xmlNodeSetBase(node, (xmlChar*) arg);
1556 return (0);
1557}
1558
1559/**
Daniel Veillard1e208222002-10-22 14:25:25 +00001560 * xmlShellGrep:
1561 * @ctxt: the shell context
1562 * @arg: the string or regular expression to find
1563 * @node: a node
1564 * @node2: unused
1565 *
1566 * Implements the XML shell function "grep"
1567 * dumps informations about the node (namespace, attributes, content).
1568 *
1569 * Returns 0
1570 */
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001571static int
Daniel Veillard1e208222002-10-22 14:25:25 +00001572xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1573 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1574{
1575 if (!ctxt)
1576 return (0);
1577 if (node == NULL)
1578 return (0);
1579 if (arg == NULL)
1580 return (0);
1581#ifdef LIBXML_REGEXP_ENABLED
1582 if ((xmlStrchr((xmlChar *) arg, '?')) ||
1583 (xmlStrchr((xmlChar *) arg, '*')) ||
1584 (xmlStrchr((xmlChar *) arg, '.')) ||
1585 (xmlStrchr((xmlChar *) arg, '['))) {
1586 }
1587#endif
1588 while (node != NULL) {
1589 if (node->type == XML_COMMENT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001590 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001591
1592 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
1593 xmlShellList(ctxt, NULL, node, NULL);
1594 }
1595 } else if (node->type == XML_TEXT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001596 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001597
1598 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001599 xmlShellList(ctxt, NULL, node->parent, NULL);
Daniel Veillard1e208222002-10-22 14:25:25 +00001600 }
1601 }
1602
1603 /*
1604 * Browse the full subtree, deep first
1605 */
1606
1607 if ((node->type == XML_DOCUMENT_NODE) ||
1608 (node->type == XML_HTML_DOCUMENT_NODE)) {
1609 node = ((xmlDocPtr) node)->children;
1610 } else if ((node->children != NULL)
1611 && (node->type != XML_ENTITY_REF_NODE)) {
1612 /* deep first */
1613 node = node->children;
1614 } else if (node->next != NULL) {
1615 /* then siblings */
1616 node = node->next;
1617 } else {
1618 /* go up to parents->next if needed */
1619 while (node != NULL) {
1620 if (node->parent != NULL) {
1621 node = node->parent;
1622 }
1623 if (node->next != NULL) {
1624 node = node->next;
1625 break;
1626 }
1627 if (node->parent == NULL) {
1628 node = NULL;
1629 break;
1630 }
1631 }
1632 }
1633 }
1634 return (0);
1635}
1636
1637/**
Owen Taylor3473f882001-02-23 17:55:21 +00001638 * xmlShellDir:
1639 * @ctxt: the shell context
1640 * @arg: unused
1641 * @node: a node
1642 * @node2: unused
1643 *
1644 * Implements the XML shell function "dir"
1645 * dumps informations about the node (namespace, attributes, content).
1646 *
1647 * Returns 0
1648 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001649int
1650xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1651 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1652 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1653{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001654 if (!ctxt)
1655 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001656 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001657 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001658 return (0);
1659 }
Owen Taylor3473f882001-02-23 17:55:21 +00001660 if ((node->type == XML_DOCUMENT_NODE) ||
1661 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001662 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001663 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001664 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001665 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001666 xmlDebugDumpOneNode(ctxt->output, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001667 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001668 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001669}
1670
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001671#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001672/**
1673 * xmlShellCat:
1674 * @ctxt: the shell context
1675 * @arg: unused
1676 * @node: a node
1677 * @node2: unused
1678 *
1679 * Implements the XML shell function "cat"
1680 * dumps the serialization node content (XML or HTML).
1681 *
1682 * Returns 0
1683 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001684int
1685xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1686 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1687{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001688 if (!ctxt)
1689 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001690 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001691 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001692 return (0);
1693 }
Owen Taylor3473f882001-02-23 17:55:21 +00001694 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1695#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001696 if (node->type == XML_HTML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001697 htmlDocDump(ctxt->output, (htmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001698 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001699 htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001700#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001701 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001702 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001703 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001704 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001705#endif /* LIBXML_HTML_ENABLED */
1706 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001707 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001708 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001709 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001710 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001711 }
Daniel Veillard321be0c2002-10-08 21:26:42 +00001712 fprintf(ctxt->output, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001713 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001714}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001715#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001716
1717/**
1718 * xmlShellLoad:
1719 * @ctxt: the shell context
1720 * @filename: the file name
1721 * @node: unused
1722 * @node2: unused
1723 *
1724 * Implements the XML shell function "load"
1725 * loads a new document specified by the filename
1726 *
1727 * Returns 0 or -1 if loading failed
1728 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001729int
1730xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1731 xmlNodePtr node ATTRIBUTE_UNUSED,
1732 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1733{
Owen Taylor3473f882001-02-23 17:55:21 +00001734 xmlDocPtr doc;
1735 int html = 0;
1736
1737 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001738 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001739
1740 if (html) {
1741#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001742 doc = htmlParseFile(filename, NULL);
1743#else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001744 fprintf(ctxt->output, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001745 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001746#endif /* LIBXML_HTML_ENABLED */
1747 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001748 doc = xmlParseFile(filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001749 }
1750 if (doc != NULL) {
1751 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001752 xmlFreeDoc(ctxt->doc);
1753 }
1754 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001755#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001756 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001757#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001758 xmlFree(ctxt->filename);
1759 ctxt->doc = doc;
1760 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001761#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001762 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001763#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard85095e22003-04-23 13:56:44 +00001764 ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001765 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001766 return (-1);
1767 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001768}
1769
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001770#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001771/**
1772 * xmlShellWrite:
1773 * @ctxt: the shell context
1774 * @filename: the file name
1775 * @node: a node in the tree
1776 * @node2: unused
1777 *
1778 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001779 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001780 * of the subtree under the @node specified
1781 *
1782 * Returns 0 or -1 in case of error
1783 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001784int
Owen Taylor3473f882001-02-23 17:55:21 +00001785xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001786 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1787{
Owen Taylor3473f882001-02-23 17:55:21 +00001788 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001789 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001790 if ((filename == NULL) || (filename[0] == 0)) {
1791 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001792 "Write command requires a filename argument\n");
1793 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001794 }
1795#ifdef W_OK
1796 if (access((char *) filename, W_OK)) {
1797 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001798 "Cannot write to %s\n", filename);
1799 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001800 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001801#endif
1802 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001803 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001804 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1805 xmlGenericError(xmlGenericErrorContext,
1806 "Failed to write to %s\n", filename);
1807 return (-1);
1808 }
1809 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001810 case XML_HTML_DOCUMENT_NODE:
1811#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001812 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1813 xmlGenericError(xmlGenericErrorContext,
1814 "Failed to write to %s\n", filename);
1815 return (-1);
1816 }
Owen Taylor3473f882001-02-23 17:55:21 +00001817#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001818 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1819 xmlGenericError(xmlGenericErrorContext,
1820 "Failed to write to %s\n", filename);
1821 return (-1);
1822 }
Owen Taylor3473f882001-02-23 17:55:21 +00001823#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001824 break;
1825 default:{
1826 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001827
Daniel Veillard78d12092001-10-11 09:12:24 +00001828 f = fopen((char *) filename, "w");
1829 if (f == NULL) {
1830 xmlGenericError(xmlGenericErrorContext,
1831 "Failed to write to %s\n", filename);
1832 return (-1);
1833 }
1834 xmlElemDump(f, ctxt->doc, node);
1835 fclose(f);
1836 }
Owen Taylor3473f882001-02-23 17:55:21 +00001837 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001838 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001839}
1840
1841/**
1842 * xmlShellSave:
1843 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001844 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001845 * @node: unused
1846 * @node2: unused
1847 *
1848 * Implements the XML shell function "save"
1849 * Write the current document to the filename, or it's original name
1850 *
1851 * Returns 0 or -1 in case of error
1852 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001853int
1854xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1855 xmlNodePtr node ATTRIBUTE_UNUSED,
1856 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1857{
Owen Taylor3473f882001-02-23 17:55:21 +00001858 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001859 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001860 if ((filename == NULL) || (filename[0] == 0))
1861 filename = ctxt->filename;
1862#ifdef W_OK
1863 if (access((char *) filename, W_OK)) {
1864 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001865 "Cannot save to %s\n", filename);
1866 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001867 }
1868#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001869 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001870 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001871 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1872 xmlGenericError(xmlGenericErrorContext,
1873 "Failed to save to %s\n", filename);
1874 }
1875 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001876 case XML_HTML_DOCUMENT_NODE:
1877#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001878 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1879 xmlGenericError(xmlGenericErrorContext,
1880 "Failed to save to %s\n", filename);
1881 }
Owen Taylor3473f882001-02-23 17:55:21 +00001882#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001883 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1884 xmlGenericError(xmlGenericErrorContext,
1885 "Failed to save to %s\n", filename);
1886 }
Owen Taylor3473f882001-02-23 17:55:21 +00001887#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001888 break;
1889 default:
1890 xmlGenericError(xmlGenericErrorContext,
1891 "To save to subparts of a document use the 'write' command\n");
1892 return (-1);
1893
Owen Taylor3473f882001-02-23 17:55:21 +00001894 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001895 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001896}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001897#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001898
1899/**
1900 * xmlShellValidate:
1901 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001902 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001903 * @node: unused
1904 * @node2: unused
1905 *
1906 * Implements the XML shell function "validate"
1907 * Validate the document, if a DTD path is provided, then the validation
1908 * is done against the given DTD.
1909 *
1910 * Returns 0 or -1 in case of error
1911 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001912int
1913xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1914 xmlNodePtr node ATTRIBUTE_UNUSED,
1915 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1916{
Owen Taylor3473f882001-02-23 17:55:21 +00001917 xmlValidCtxt vctxt;
1918 int res = -1;
1919
1920 vctxt.userData = stderr;
1921 vctxt.error = (xmlValidityErrorFunc) fprintf;
1922 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1923
1924 if ((dtd == NULL) || (dtd[0] == 0)) {
1925 res = xmlValidateDocument(&vctxt, ctxt->doc);
1926 } else {
1927 xmlDtdPtr subset;
1928
Daniel Veillard78d12092001-10-11 09:12:24 +00001929 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1930 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001931 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1932
Daniel Veillard78d12092001-10-11 09:12:24 +00001933 xmlFreeDtd(subset);
1934 }
Owen Taylor3473f882001-02-23 17:55:21 +00001935 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001936 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00001937}
1938
1939/**
1940 * xmlShellDu:
1941 * @ctxt: the shell context
1942 * @arg: unused
1943 * @tree: a node defining a subtree
1944 * @node2: unused
1945 *
1946 * Implements the XML shell function "du"
1947 * show the structure of the subtree under node @tree
1948 * If @tree is null, the command works on the current node.
1949 *
1950 * Returns 0 or -1 in case of error
1951 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001952int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001953xmlShellDu(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001954 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1955 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1956{
Owen Taylor3473f882001-02-23 17:55:21 +00001957 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00001958 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00001959
Daniel Veillard321be0c2002-10-08 21:26:42 +00001960 if (!ctxt)
1961 return (-1);
1962
Daniel Veillard78d12092001-10-11 09:12:24 +00001963 if (tree == NULL)
1964 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001965 node = tree;
1966 while (node != NULL) {
1967 if ((node->type == XML_DOCUMENT_NODE) ||
1968 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001969 fprintf(ctxt->output, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001970 } else if (node->type == XML_ELEMENT_NODE) {
1971 for (i = 0; i < indent; i++)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001972 fprintf(ctxt->output, " ");
1973 fprintf(ctxt->output, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00001974 } else {
1975 }
Owen Taylor3473f882001-02-23 17:55:21 +00001976
Daniel Veillard78d12092001-10-11 09:12:24 +00001977 /*
1978 * Browse the full subtree, deep first
1979 */
Owen Taylor3473f882001-02-23 17:55:21 +00001980
1981 if ((node->type == XML_DOCUMENT_NODE) ||
1982 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001983 node = ((xmlDocPtr) node)->children;
1984 } else if ((node->children != NULL)
1985 && (node->type != XML_ENTITY_REF_NODE)) {
1986 /* deep first */
1987 node = node->children;
1988 indent++;
1989 } else if ((node != tree) && (node->next != NULL)) {
1990 /* then siblings */
1991 node = node->next;
1992 } else if (node != tree) {
1993 /* go up to parents->next if needed */
1994 while (node != tree) {
1995 if (node->parent != NULL) {
1996 node = node->parent;
1997 indent--;
1998 }
1999 if ((node != tree) && (node->next != NULL)) {
2000 node = node->next;
2001 break;
2002 }
2003 if (node->parent == NULL) {
2004 node = NULL;
2005 break;
2006 }
2007 if (node == tree) {
2008 node = NULL;
2009 break;
2010 }
2011 }
2012 /* exit condition */
2013 if (node == tree)
2014 node = NULL;
2015 } else
2016 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002017 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002018 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002019}
2020
2021/**
2022 * xmlShellPwd:
2023 * @ctxt: the shell context
2024 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00002025 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00002026 * @node2: unused
2027 *
2028 * Implements the XML shell function "pwd"
2029 * Show the full path from the root to the node, if needed building
2030 * thumblers when similar elements exists at a given ancestor level.
2031 * The output is compatible with XPath commands.
2032 *
2033 * Returns 0 or -1 in case of error
2034 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002035int
2036xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2037 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2038{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002039 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00002040
Daniel Veillard78d12092001-10-11 09:12:24 +00002041 if (node == NULL)
2042 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002043
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002044 path = xmlGetNodePath(node);
2045 if (path == NULL)
2046 return (-1);
2047
2048 /*
2049 * This test prevents buffer overflow, because this routine
2050 * is only called by xmlShell, in which the second argument is
2051 * 500 chars long.
2052 * It is a dirty hack before a cleaner solution is found.
2053 * Documentation should mention that the second argument must
2054 * be at least 500 chars long, and could be stripped if too long.
2055 */
2056 snprintf(buffer, 499, "%s", path);
2057 buffer[499] = '0';
2058 xmlFree(path);
2059
Daniel Veillard78d12092001-10-11 09:12:24 +00002060 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002061}
2062
2063/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002064 * xmlShell:
Owen Taylor3473f882001-02-23 17:55:21 +00002065 * @doc: the initial document
2066 * @filename: the output buffer
2067 * @input: the line reading function
Daniel Veillard321be0c2002-10-08 21:26:42 +00002068 * @output: the output FILE*, defaults to stdout if NULL
Owen Taylor3473f882001-02-23 17:55:21 +00002069 *
2070 * Implements the XML shell
2071 * This allow to load, validate, view, modify and save a document
2072 * using a environment similar to a UNIX commandline.
2073 */
2074void
2075xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00002076 FILE * output)
2077{
Owen Taylor3473f882001-02-23 17:55:21 +00002078 char prompt[500] = "/ > ";
2079 char *cmdline = NULL, *cur;
2080 int nbargs;
2081 char command[100];
2082 char arg[400];
2083 int i;
2084 xmlShellCtxtPtr ctxt;
2085 xmlXPathObjectPtr list;
2086
2087 if (doc == NULL)
2088 return;
2089 if (filename == NULL)
2090 return;
2091 if (input == NULL)
2092 return;
2093 if (output == NULL)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002094 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00002095 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00002096 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00002097 return;
2098 ctxt->loaded = 0;
2099 ctxt->doc = doc;
2100 ctxt->input = input;
2101 ctxt->output = output;
2102 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00002103 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00002104
2105#ifdef LIBXML_XPATH_ENABLED
2106 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2107 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002108 xmlFree(ctxt);
2109 return;
Owen Taylor3473f882001-02-23 17:55:21 +00002110 }
2111#endif /* LIBXML_XPATH_ENABLED */
2112 while (1) {
2113 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002114 snprintf(prompt, sizeof(prompt), "%s > ", "/");
Daniel Veillard7a985a12003-07-06 17:57:42 +00002115 else if ((ctxt->node != NULL) && (ctxt->node->name))
Daniel Veillard78d12092001-10-11 09:12:24 +00002116 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00002117 else
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002118 snprintf(prompt, sizeof(prompt), "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00002119 prompt[sizeof(prompt) - 1] = 0;
2120
Daniel Veillard78d12092001-10-11 09:12:24 +00002121 /*
2122 * Get a new command line
2123 */
Owen Taylor3473f882001-02-23 17:55:21 +00002124 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00002125 if (cmdline == NULL)
2126 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002127
Daniel Veillard78d12092001-10-11 09:12:24 +00002128 /*
2129 * Parse the command itself
2130 */
2131 cur = cmdline;
2132 nbargs = 0;
2133 while ((*cur == ' ') || (*cur == '\t'))
2134 cur++;
2135 i = 0;
2136 while ((*cur != ' ') && (*cur != '\t') &&
2137 (*cur != '\n') && (*cur != '\r')) {
2138 if (*cur == 0)
2139 break;
2140 command[i++] = *cur++;
2141 }
2142 command[i] = 0;
2143 if (i == 0)
2144 continue;
2145 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002146
Daniel Veillard78d12092001-10-11 09:12:24 +00002147 /*
2148 * Parse the argument
2149 */
2150 while ((*cur == ' ') || (*cur == '\t'))
2151 cur++;
2152 i = 0;
2153 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2154 if (*cur == 0)
2155 break;
2156 arg[i++] = *cur++;
2157 }
2158 arg[i] = 0;
2159 if (i != 0)
2160 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002161
Daniel Veillard78d12092001-10-11 09:12:24 +00002162 /*
2163 * start interpreting the command
2164 */
Owen Taylor3473f882001-02-23 17:55:21 +00002165 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002166 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002167 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002168 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002169 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002170 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002171 if (!strcmp(command, "help")) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002172 fprintf(ctxt->output, "\tbase display XML base of the node\n");
2173 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2174 fprintf(ctxt->output, "\tbye leave shell\n");
2175 fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2176 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2177 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2178 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2179 fprintf(ctxt->output, "\texit leave shell\n");
2180 fprintf(ctxt->output, "\thelp display this help\n");
2181 fprintf(ctxt->output, "\tfree display memory usage\n");
2182 fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2183 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002184#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002185 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002186#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard321be0c2002-10-08 21:26:42 +00002187 fprintf(ctxt->output, "\tpwd display current working directory\n");
2188 fprintf(ctxt->output, "\tquit leave shell\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002189#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002190 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00002191 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002192#endif /* LIBXML_OUTPUT_ENABLED */
2193 fprintf(ctxt->output, "\tvalidate check the document for errors\n");
Daniel Veillard1e208222002-10-22 14:25:25 +00002194 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
Daniel Veillard5004f422001-11-08 13:53:05 +00002195 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002196 xmlShellValidate(ctxt, arg, NULL, NULL);
2197 } else if (!strcmp(command, "load")) {
2198 xmlShellLoad(ctxt, arg, NULL, NULL);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002199#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002200 } else if (!strcmp(command, "save")) {
2201 xmlShellSave(ctxt, arg, NULL, NULL);
2202 } else if (!strcmp(command, "write")) {
2203 xmlShellWrite(ctxt, arg, NULL, NULL);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002204#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard1e208222002-10-22 14:25:25 +00002205 } else if (!strcmp(command, "grep")) {
2206 xmlShellGrep(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002207 } else if (!strcmp(command, "free")) {
2208 if (arg[0] == 0) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002209 xmlMemShow(ctxt->output, 0);
Daniel Veillard78d12092001-10-11 09:12:24 +00002210 } else {
2211 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002212
Daniel Veillard78d12092001-10-11 09:12:24 +00002213 sscanf(arg, "%d", &len);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002214 xmlMemShow(ctxt->output, len);
Daniel Veillard78d12092001-10-11 09:12:24 +00002215 }
2216 } else if (!strcmp(command, "pwd")) {
2217 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002218
Daniel Veillard78d12092001-10-11 09:12:24 +00002219 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillard321be0c2002-10-08 21:26:42 +00002220 fprintf(ctxt->output, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002221 } else if (!strcmp(command, "du")) {
2222 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2223 } else if (!strcmp(command, "base")) {
2224 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002225#ifdef LIBXML_XPATH_ENABLED
2226 } else if (!strcmp(command, "xpath")) {
2227 if (arg[0] == 0) {
2228 xmlGenericError(xmlGenericErrorContext,
2229 "xpath: expression required\n");
2230 } else {
2231 ctxt->pctxt->node = ctxt->node;
2232 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002233 xmlXPathDebugDumpObject(ctxt->output, list, 0);
Daniel Veillard2070c482002-01-22 22:12:19 +00002234 xmlXPathFreeObject(list);
2235 }
2236#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002237 } else if (!strcmp(command, "setbase")) {
2238 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002239 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2240 int dir = (!strcmp(command, "dir"));
2241
2242 if (arg[0] == 0) {
2243 if (dir)
2244 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2245 else
2246 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2247 } else {
2248 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002249#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002250 ctxt->pctxt->node = ctxt->node;
2251 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2252#else
2253 list = NULL;
2254#endif /* LIBXML_XPATH_ENABLED */
2255 if (list != NULL) {
2256 switch (list->type) {
2257 case XPATH_UNDEFINED:
2258 xmlGenericError(xmlGenericErrorContext,
2259 "%s: no such node\n", arg);
2260 break;
2261 case XPATH_NODESET:{
2262 int indx;
2263
Daniel Veillarda6825e82001-11-07 13:33:59 +00002264 if (list->nodesetval == NULL)
2265 break;
2266
Daniel Veillard78d12092001-10-11 09:12:24 +00002267 for (indx = 0;
2268 indx < list->nodesetval->nodeNr;
2269 indx++) {
2270 if (dir)
2271 xmlShellDir(ctxt, NULL,
2272 list->nodesetval->
2273 nodeTab[indx], NULL);
2274 else
2275 xmlShellList(ctxt, NULL,
2276 list->nodesetval->
2277 nodeTab[indx], NULL);
2278 }
2279 break;
2280 }
2281 case XPATH_BOOLEAN:
2282 xmlGenericError(xmlGenericErrorContext,
2283 "%s is a Boolean\n", arg);
2284 break;
2285 case XPATH_NUMBER:
2286 xmlGenericError(xmlGenericErrorContext,
2287 "%s is a number\n", arg);
2288 break;
2289 case XPATH_STRING:
2290 xmlGenericError(xmlGenericErrorContext,
2291 "%s is a string\n", arg);
2292 break;
2293 case XPATH_POINT:
2294 xmlGenericError(xmlGenericErrorContext,
2295 "%s is a point\n", arg);
2296 break;
2297 case XPATH_RANGE:
2298 xmlGenericError(xmlGenericErrorContext,
2299 "%s is a range\n", arg);
2300 break;
2301 case XPATH_LOCATIONSET:
2302 xmlGenericError(xmlGenericErrorContext,
2303 "%s is a range\n", arg);
2304 break;
2305 case XPATH_USERS:
2306 xmlGenericError(xmlGenericErrorContext,
2307 "%s is user-defined\n", arg);
2308 break;
2309 case XPATH_XSLT_TREE:
2310 xmlGenericError(xmlGenericErrorContext,
2311 "%s is an XSLT value tree\n",
2312 arg);
2313 break;
2314 }
2315#ifdef LIBXML_XPATH_ENABLED
2316 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002317#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002318 } else {
2319 xmlGenericError(xmlGenericErrorContext,
2320 "%s: no such node\n", arg);
2321 }
2322 ctxt->pctxt->node = NULL;
2323 }
2324 } else if (!strcmp(command, "cd")) {
2325 if (arg[0] == 0) {
2326 ctxt->node = (xmlNodePtr) ctxt->doc;
2327 } else {
2328#ifdef LIBXML_XPATH_ENABLED
2329 ctxt->pctxt->node = ctxt->node;
2330 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2331#else
2332 list = NULL;
2333#endif /* LIBXML_XPATH_ENABLED */
2334 if (list != NULL) {
2335 switch (list->type) {
2336 case XPATH_UNDEFINED:
2337 xmlGenericError(xmlGenericErrorContext,
2338 "%s: no such node\n", arg);
2339 break;
2340 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002341 if (list->nodesetval != NULL) {
2342 if (list->nodesetval->nodeNr == 1) {
2343 ctxt->node = list->nodesetval->nodeTab[0];
Daniel Veillard7a985a12003-07-06 17:57:42 +00002344 if ((ctxt->node != NULL) &&
2345 (ctxt->node->type ==
2346 XML_NAMESPACE_DECL)) {
2347 xmlGenericError(xmlGenericErrorContext,
2348 "cannot cd to namespace\n");
2349 ctxt->node = NULL;
2350 }
Daniel Veillarda6825e82001-11-07 13:33:59 +00002351 } else
2352 xmlGenericError(xmlGenericErrorContext,
2353 "%s is a %d Node Set\n",
2354 arg,
2355 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002356 } else
2357 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002358 "%s is an empty Node Set\n",
2359 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002360 break;
2361 case XPATH_BOOLEAN:
2362 xmlGenericError(xmlGenericErrorContext,
2363 "%s is a Boolean\n", arg);
2364 break;
2365 case XPATH_NUMBER:
2366 xmlGenericError(xmlGenericErrorContext,
2367 "%s is a number\n", arg);
2368 break;
2369 case XPATH_STRING:
2370 xmlGenericError(xmlGenericErrorContext,
2371 "%s is a string\n", arg);
2372 break;
2373 case XPATH_POINT:
2374 xmlGenericError(xmlGenericErrorContext,
2375 "%s is a point\n", arg);
2376 break;
2377 case XPATH_RANGE:
2378 xmlGenericError(xmlGenericErrorContext,
2379 "%s is a range\n", arg);
2380 break;
2381 case XPATH_LOCATIONSET:
2382 xmlGenericError(xmlGenericErrorContext,
2383 "%s is a range\n", arg);
2384 break;
2385 case XPATH_USERS:
2386 xmlGenericError(xmlGenericErrorContext,
2387 "%s is user-defined\n", arg);
2388 break;
2389 case XPATH_XSLT_TREE:
2390 xmlGenericError(xmlGenericErrorContext,
2391 "%s is an XSLT value tree\n",
2392 arg);
2393 break;
2394 }
2395#ifdef LIBXML_XPATH_ENABLED
2396 xmlXPathFreeObject(list);
2397#endif
2398 } else {
2399 xmlGenericError(xmlGenericErrorContext,
2400 "%s: no such node\n", arg);
2401 }
2402 ctxt->pctxt->node = NULL;
2403 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002404#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002405 } else if (!strcmp(command, "cat")) {
2406 if (arg[0] == 0) {
2407 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2408 } else {
2409 ctxt->pctxt->node = ctxt->node;
2410#ifdef LIBXML_XPATH_ENABLED
2411 ctxt->pctxt->node = ctxt->node;
2412 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2413#else
2414 list = NULL;
2415#endif /* LIBXML_XPATH_ENABLED */
2416 if (list != NULL) {
2417 switch (list->type) {
2418 case XPATH_UNDEFINED:
2419 xmlGenericError(xmlGenericErrorContext,
2420 "%s: no such node\n", arg);
2421 break;
2422 case XPATH_NODESET:{
2423 int indx;
2424
Daniel Veillarda6825e82001-11-07 13:33:59 +00002425 if (list->nodesetval == NULL)
2426 break;
2427
Daniel Veillard78d12092001-10-11 09:12:24 +00002428 for (indx = 0;
2429 indx < list->nodesetval->nodeNr;
2430 indx++) {
2431 if (i > 0)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002432 fprintf(ctxt->output, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002433 xmlShellCat(ctxt, NULL,
2434 list->nodesetval->
2435 nodeTab[indx], NULL);
2436 }
2437 break;
2438 }
2439 case XPATH_BOOLEAN:
2440 xmlGenericError(xmlGenericErrorContext,
2441 "%s is a Boolean\n", arg);
2442 break;
2443 case XPATH_NUMBER:
2444 xmlGenericError(xmlGenericErrorContext,
2445 "%s is a number\n", arg);
2446 break;
2447 case XPATH_STRING:
2448 xmlGenericError(xmlGenericErrorContext,
2449 "%s is a string\n", arg);
2450 break;
2451 case XPATH_POINT:
2452 xmlGenericError(xmlGenericErrorContext,
2453 "%s is a point\n", arg);
2454 break;
2455 case XPATH_RANGE:
2456 xmlGenericError(xmlGenericErrorContext,
2457 "%s is a range\n", arg);
2458 break;
2459 case XPATH_LOCATIONSET:
2460 xmlGenericError(xmlGenericErrorContext,
2461 "%s is a range\n", arg);
2462 break;
2463 case XPATH_USERS:
2464 xmlGenericError(xmlGenericErrorContext,
2465 "%s is user-defined\n", arg);
2466 break;
2467 case XPATH_XSLT_TREE:
2468 xmlGenericError(xmlGenericErrorContext,
2469 "%s is an XSLT value tree\n",
2470 arg);
2471 break;
2472 }
2473#ifdef LIBXML_XPATH_ENABLED
2474 xmlXPathFreeObject(list);
2475#endif
2476 } else {
2477 xmlGenericError(xmlGenericErrorContext,
2478 "%s: no such node\n", arg);
2479 }
2480 ctxt->pctxt->node = NULL;
2481 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002482#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002483 } else {
2484 xmlGenericError(xmlGenericErrorContext,
2485 "Unknown command %s\n", command);
2486 }
2487 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002488 }
2489#ifdef LIBXML_XPATH_ENABLED
2490 xmlXPathFreeContext(ctxt->pctxt);
2491#endif /* LIBXML_XPATH_ENABLED */
2492 if (ctxt->loaded) {
2493 xmlFreeDoc(ctxt->doc);
2494 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002495 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002496 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002497 xmlFree(ctxt);
2498 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002499 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002500}
2501
2502#endif /* LIBXML_DEBUG_ENABLED */