blob: 768010d12e1ff34e524cb4ec0c4e4c410968cc76 [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>
Daniel Veillard522bc602004-02-21 11:53:09 +000033#ifdef LIBXML_SCHEMAS_ENABLED
34#include <libxml/relaxng.h>
35#endif
Owen Taylor3473f882001-02-23 17:55:21 +000036
Daniel Veillard5e2dace2001-07-18 19:30:27 +000037/**
38 * xmlDebugDumpString:
39 * @output: the FILE * for the output
40 * @str: the string
41 *
42 * Dumps informations about the string, shorten it if necessary
43 */
44void
45xmlDebugDumpString(FILE * output, const xmlChar * str)
46{
Owen Taylor3473f882001-02-23 17:55:21 +000047 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000048
Daniel Veillard7db38712002-02-07 16:39:11 +000049 if (output == NULL)
50 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +000051 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000052 fprintf(output, "(NULL)");
53 return;
Owen Taylor3473f882001-02-23 17:55:21 +000054 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000055 for (i = 0; i < 40; i++)
56 if (str[i] == 0)
57 return;
William M. Brack76e95df2003-10-18 16:20:14 +000058 else if (IS_BLANK_CH(str[i]))
Daniel Veillard5e2dace2001-07-18 19:30:27 +000059 fputc(' ', output);
60 else if (str[i] >= 0x80)
61 fprintf(output, "#%X", str[i]);
62 else
63 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000064 fprintf(output, "...");
65}
66
Daniel Veillard56a4cb82001-03-24 17:00:36 +000067static void
68xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000069 int i;
70 char shift[100];
71
72 for (i = 0;((i < depth) && (i < 25));i++)
73 shift[2 * i] = shift[2 * i + 1] = ' ';
74 shift[2 * i] = shift[2 * i + 1] = 0;
75
76 fprintf(output, shift);
77
Daniel Veillard5e926fa2002-01-22 21:44:25 +000078 if (dtd == NULL) {
79 fprintf(output, "DTD node is NULL\n");
80 return;
81 }
82
Owen Taylor3473f882001-02-23 17:55:21 +000083 if (dtd->type != XML_DTD_NODE) {
84 fprintf(output, "PBM: not a DTD\n");
85 return;
86 }
87 if (dtd->name != NULL)
88 fprintf(output, "DTD(%s)", dtd->name);
89 else
90 fprintf(output, "DTD");
91 if (dtd->ExternalID != NULL)
92 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
93 if (dtd->SystemID != NULL)
94 fprintf(output, ", SYSTEM %s", dtd->SystemID);
95 fprintf(output, "\n");
96 /*
97 * Do a bit of checking
98 */
99 if (dtd->parent == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000100 fprintf(output, "PBM: DTD has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000101 if (dtd->doc == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000102 fprintf(output, "PBM: DTD has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000103 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000104 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000105 if (dtd->prev == NULL) {
106 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000107 fprintf(output, "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000108 } else {
109 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000110 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000111 }
112 if (dtd->next == NULL) {
113 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000114 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000115 } else {
116 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000117 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000118 }
119}
120
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000121static void
122xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000123 int i;
124 char shift[100];
125
126 for (i = 0;((i < depth) && (i < 25));i++)
127 shift[2 * i] = shift[2 * i + 1] = ' ';
128 shift[2 * i] = shift[2 * i + 1] = 0;
129
130 fprintf(output, shift);
131
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000132 if (attr == NULL) {
133 fprintf(output, "Attribute declaration is NULL\n");
134 return;
135 }
Owen Taylor3473f882001-02-23 17:55:21 +0000136 if (attr->type != XML_ATTRIBUTE_DECL) {
137 fprintf(output, "PBM: not a Attr\n");
138 return;
139 }
140 if (attr->name != NULL)
141 fprintf(output, "ATTRDECL(%s)", attr->name);
142 else
143 fprintf(output, "PBM ATTRDECL noname!!!");
144 if (attr->elem != NULL)
145 fprintf(output, " for %s", attr->elem);
146 else
147 fprintf(output, " PBM noelem!!!");
148 switch (attr->atype) {
149 case XML_ATTRIBUTE_CDATA:
150 fprintf(output, " CDATA");
151 break;
152 case XML_ATTRIBUTE_ID:
153 fprintf(output, " ID");
154 break;
155 case XML_ATTRIBUTE_IDREF:
156 fprintf(output, " IDREF");
157 break;
158 case XML_ATTRIBUTE_IDREFS:
159 fprintf(output, " IDREFS");
160 break;
161 case XML_ATTRIBUTE_ENTITY:
162 fprintf(output, " ENTITY");
163 break;
164 case XML_ATTRIBUTE_ENTITIES:
165 fprintf(output, " ENTITIES");
166 break;
167 case XML_ATTRIBUTE_NMTOKEN:
168 fprintf(output, " NMTOKEN");
169 break;
170 case XML_ATTRIBUTE_NMTOKENS:
171 fprintf(output, " NMTOKENS");
172 break;
173 case XML_ATTRIBUTE_ENUMERATION:
174 fprintf(output, " ENUMERATION");
175 break;
176 case XML_ATTRIBUTE_NOTATION:
177 fprintf(output, " NOTATION ");
178 break;
179 }
180 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000181 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000182 xmlEnumerationPtr cur = attr->tree;
183
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000184 for (indx = 0;indx < 5; indx++) {
185 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000186 fprintf(output, "|%s", cur->name);
187 else
188 fprintf(output, " (%s", cur->name);
189 cur = cur->next;
190 if (cur == NULL) break;
191 }
192 if (cur == NULL)
193 fprintf(output, ")");
194 else
195 fprintf(output, "...)");
196 }
197 switch (attr->def) {
198 case XML_ATTRIBUTE_NONE:
199 break;
200 case XML_ATTRIBUTE_REQUIRED:
201 fprintf(output, " REQUIRED");
202 break;
203 case XML_ATTRIBUTE_IMPLIED:
204 fprintf(output, " IMPLIED");
205 break;
206 case XML_ATTRIBUTE_FIXED:
207 fprintf(output, " FIXED");
208 break;
209 }
210 if (attr->defaultValue != NULL) {
211 fprintf(output, "\"");
212 xmlDebugDumpString(output, attr->defaultValue);
213 fprintf(output, "\"");
214 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000215 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000216
217 /*
218 * Do a bit of checking
219 */
220 if (attr->parent == NULL)
221 fprintf(output, "PBM: Attr has no parent\n");
222 if (attr->doc == NULL)
223 fprintf(output, "PBM: Attr has no doc\n");
224 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
225 fprintf(output, "PBM: Attr doc differs from parent's one\n");
226 if (attr->prev == NULL) {
227 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
228 fprintf(output, "PBM: Attr has no prev and not first of list\n");
229 } else {
230 if (attr->prev->next != (xmlNodePtr) attr)
231 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
232 }
233 if (attr->next == NULL) {
234 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
235 fprintf(output, "PBM: Attr has no next and not last of list\n");
236 } else {
237 if (attr->next->prev != (xmlNodePtr) attr)
238 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
239 }
240}
241
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000242static void
243xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000244 int i;
245 char shift[100];
246
247 for (i = 0;((i < depth) && (i < 25));i++)
248 shift[2 * i] = shift[2 * i + 1] = ' ';
249 shift[2 * i] = shift[2 * i + 1] = 0;
250
251 fprintf(output, shift);
252
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000253 if (elem == NULL) {
254 fprintf(output, "Element declaration is NULL\n");
255 return;
256 }
Owen Taylor3473f882001-02-23 17:55:21 +0000257 if (elem->type != XML_ELEMENT_DECL) {
258 fprintf(output, "PBM: not a Elem\n");
259 return;
260 }
261 if (elem->name != NULL) {
262 fprintf(output, "ELEMDECL(");
263 xmlDebugDumpString(output, elem->name);
264 fprintf(output, ")");
265 } else
266 fprintf(output, "PBM ELEMDECL noname!!!");
267 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000268 case XML_ELEMENT_TYPE_UNDEFINED:
269 fprintf(output, ", UNDEFINED");
270 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000271 case XML_ELEMENT_TYPE_EMPTY:
272 fprintf(output, ", EMPTY");
273 break;
274 case XML_ELEMENT_TYPE_ANY:
275 fprintf(output, ", ANY");
276 break;
277 case XML_ELEMENT_TYPE_MIXED:
278 fprintf(output, ", MIXED ");
279 break;
280 case XML_ELEMENT_TYPE_ELEMENT:
281 fprintf(output, ", MIXED ");
282 break;
283 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000284 if ((elem->type != XML_ELEMENT_NODE) &&
285 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000286 char buf[5001];
287
288 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000289 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000290 buf[5000] = 0;
291 fprintf(output, "%s", buf);
292 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000293 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000294
295 /*
296 * Do a bit of checking
297 */
298 if (elem->parent == NULL)
299 fprintf(output, "PBM: Elem has no parent\n");
300 if (elem->doc == NULL)
301 fprintf(output, "PBM: Elem has no doc\n");
302 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
303 fprintf(output, "PBM: Elem doc differs from parent's one\n");
304 if (elem->prev == NULL) {
305 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
306 fprintf(output, "PBM: Elem has no prev and not first of list\n");
307 } else {
308 if (elem->prev->next != (xmlNodePtr) elem)
309 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
310 }
311 if (elem->next == NULL) {
312 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
313 fprintf(output, "PBM: Elem has no next and not last of list\n");
314 } else {
315 if (elem->next->prev != (xmlNodePtr) elem)
316 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
317 }
318}
319
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000320static void
321xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000322 int i;
323 char shift[100];
324
325 for (i = 0;((i < depth) && (i < 25));i++)
326 shift[2 * i] = shift[2 * i + 1] = ' ';
327 shift[2 * i] = shift[2 * i + 1] = 0;
328
329 fprintf(output, shift);
330
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000331 if (ent == NULL) {
332 fprintf(output, "Entity declaration is NULL\n");
333 return;
334 }
Owen Taylor3473f882001-02-23 17:55:21 +0000335 if (ent->type != XML_ENTITY_DECL) {
336 fprintf(output, "PBM: not a Entity decl\n");
337 return;
338 }
339 if (ent->name != NULL) {
340 fprintf(output, "ENTITYDECL(");
341 xmlDebugDumpString(output, ent->name);
342 fprintf(output, ")");
343 } else
344 fprintf(output, "PBM ENTITYDECL noname!!!");
345 switch (ent->etype) {
346 case XML_INTERNAL_GENERAL_ENTITY:
347 fprintf(output, ", internal\n");
348 break;
349 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
350 fprintf(output, ", external parsed\n");
351 break;
352 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
353 fprintf(output, ", unparsed\n");
354 break;
355 case XML_INTERNAL_PARAMETER_ENTITY:
356 fprintf(output, ", parameter\n");
357 break;
358 case XML_EXTERNAL_PARAMETER_ENTITY:
359 fprintf(output, ", external parameter\n");
360 break;
361 case XML_INTERNAL_PREDEFINED_ENTITY:
362 fprintf(output, ", predefined\n");
363 break;
364 }
365 if (ent->ExternalID) {
366 fprintf(output, shift);
367 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
368 }
369 if (ent->SystemID) {
370 fprintf(output, shift);
371 fprintf(output, " SystemID=%s\n", ent->SystemID);
372 }
373 if (ent->URI != NULL) {
374 fprintf(output, shift);
375 fprintf(output, " URI=%s\n", ent->URI);
376 }
377 if (ent->content) {
378 fprintf(output, shift);
379 fprintf(output, " content=");
380 xmlDebugDumpString(output, ent->content);
381 fprintf(output, "\n");
382 }
383
384 /*
385 * Do a bit of checking
386 */
387 if (ent->parent == NULL)
388 fprintf(output, "PBM: Ent has no parent\n");
389 if (ent->doc == NULL)
390 fprintf(output, "PBM: Ent has no doc\n");
391 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
392 fprintf(output, "PBM: Ent doc differs from parent's one\n");
393 if (ent->prev == NULL) {
394 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
395 fprintf(output, "PBM: Ent has no prev and not first of list\n");
396 } else {
397 if (ent->prev->next != (xmlNodePtr) ent)
398 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
399 }
400 if (ent->next == NULL) {
401 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
402 fprintf(output, "PBM: Ent has no next and not last of list\n");
403 } else {
404 if (ent->next->prev != (xmlNodePtr) ent)
405 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
406 }
407}
408
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000409static void
410xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000411 int i;
412 char shift[100];
413
414 for (i = 0;((i < depth) && (i < 25));i++)
415 shift[2 * i] = shift[2 * i + 1] = ' ';
416 shift[2 * i] = shift[2 * i + 1] = 0;
417
418 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000419
420 if (ns == NULL) {
421 fprintf(output, "namespace node is NULL\n");
422 return;
423 }
Owen Taylor3473f882001-02-23 17:55:21 +0000424 if (ns->type != XML_NAMESPACE_DECL) {
425 fprintf(output, "invalid namespace node %d\n", ns->type);
426 return;
427 }
428 if (ns->href == NULL) {
429 if (ns->prefix != NULL)
430 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
431 else
432 fprintf(output, "incomplete default namespace href=NULL\n");
433 } else {
434 if (ns->prefix != NULL)
435 fprintf(output, "namespace %s href=", ns->prefix);
436 else
437 fprintf(output, "default namespace href=");
438
439 xmlDebugDumpString(output, ns->href);
440 fprintf(output, "\n");
441 }
442}
443
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000444static void
445xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000446 while (ns != NULL) {
447 xmlDebugDumpNamespace(output, ns, depth);
448 ns = ns->next;
449 }
450}
451
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000452static void
453xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000454 int i;
455 char shift[100];
456
457 for (i = 0;((i < depth) && (i < 25));i++)
458 shift[2 * i] = shift[2 * i + 1] = ' ';
459 shift[2 * i] = shift[2 * i + 1] = 0;
460
461 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000462
463 if (ent == NULL) {
464 fprintf(output, "Entity is NULL\n");
465 return;
466 }
Owen Taylor3473f882001-02-23 17:55:21 +0000467 switch (ent->etype) {
468 case XML_INTERNAL_GENERAL_ENTITY:
469 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
470 break;
471 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
472 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
473 break;
474 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
475 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
476 break;
477 case XML_INTERNAL_PARAMETER_ENTITY:
478 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
479 break;
480 case XML_EXTERNAL_PARAMETER_ENTITY:
481 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
482 break;
483 default:
484 fprintf(output, "ENTITY_%d ! ", ent->etype);
485 }
486 fprintf(output, "%s\n", ent->name);
487 if (ent->ExternalID) {
488 fprintf(output, shift);
489 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
490 }
491 if (ent->SystemID) {
492 fprintf(output, shift);
493 fprintf(output, "SystemID=%s\n", ent->SystemID);
494 }
495 if (ent->URI) {
496 fprintf(output, shift);
497 fprintf(output, "URI=%s\n", ent->URI);
498 }
499 if (ent->content) {
500 fprintf(output, shift);
501 fprintf(output, "content=");
502 xmlDebugDumpString(output, ent->content);
503 fprintf(output, "\n");
504 }
505}
506
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000507/**
508 * xmlDebugDumpAttr:
509 * @output: the FILE * for the output
510 * @attr: the attribute
511 * @depth: the indentation level.
512 *
513 * Dumps debug information for the attribute
514 */
515void
516xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000517 int i;
518 char shift[100];
519
520 for (i = 0;((i < depth) && (i < 25));i++)
521 shift[2 * i] = shift[2 * i + 1] = ' ';
522 shift[2 * i] = shift[2 * i + 1] = 0;
523
524 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000525
526 if (attr == NULL) {
527 fprintf(output, "Attr is NULL");
528 return;
529 }
Owen Taylor3473f882001-02-23 17:55:21 +0000530 fprintf(output, "ATTRIBUTE ");
531 xmlDebugDumpString(output, attr->name);
532 fprintf(output, "\n");
533 if (attr->children != NULL)
534 xmlDebugDumpNodeList(output, attr->children, depth + 1);
535
536 /*
537 * Do a bit of checking
538 */
539 if (attr->parent == NULL)
540 fprintf(output, "PBM: Attr has no parent\n");
541 if (attr->doc == NULL)
542 fprintf(output, "PBM: Attr has no doc\n");
543 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
544 fprintf(output, "PBM: Attr doc differs from parent's one\n");
545 if (attr->prev == NULL) {
546 if ((attr->parent != NULL) && (attr->parent->properties != attr))
547 fprintf(output, "PBM: Attr has no prev and not first of list\n");
548 } else {
549 if (attr->prev->next != attr)
550 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
551 }
552 if (attr->next != NULL) {
553 if (attr->next->prev != attr)
554 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
555 }
556}
557
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000558/**
559 * xmlDebugDumpAttrList:
560 * @output: the FILE * for the output
561 * @attr: the attribute list
562 * @depth: the indentation level.
563 *
564 * Dumps debug information for the attribute list
565 */
566void
567xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
568{
Daniel Veillard7db38712002-02-07 16:39:11 +0000569 if (output == NULL)
570 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000571 while (attr != NULL) {
572 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000573 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000574 }
575}
576
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000577/**
578 * xmlDebugDumpOneNode:
579 * @output: the FILE * for the output
580 * @node: the node
581 * @depth: the indentation level.
582 *
583 * Dumps debug information for the element node, it is not recursive
584 */
585void
586xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
587{
Owen Taylor3473f882001-02-23 17:55:21 +0000588 int i;
589 char shift[100];
590
Daniel Veillard7db38712002-02-07 16:39:11 +0000591 if (output == NULL)
592 output = stdout;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000593 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000594 shift[2 * i] = shift[2 * i + 1] = ' ';
595 shift[2 * i] = shift[2 * i + 1] = 0;
596
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000597 if (node == NULL) {
598 fprintf(output, shift);
599 fprintf(output, "node is NULL\n");
600 return;
601 }
Owen Taylor3473f882001-02-23 17:55:21 +0000602 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000603 case XML_ELEMENT_NODE:
604 fprintf(output, shift);
605 fprintf(output, "ELEMENT ");
606 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
607 xmlDebugDumpString(output, node->ns->prefix);
608 fprintf(output, ":");
609 }
610 xmlDebugDumpString(output, node->name);
611 fprintf(output, "\n");
612 break;
613 case XML_ATTRIBUTE_NODE:
614 fprintf(output, shift);
615 fprintf(output, "Error, ATTRIBUTE found here\n");
616 break;
617 case XML_TEXT_NODE:
618 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000619 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000620 fprintf(output, "TEXT no enc\n");
621 else
622 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000623 break;
624 case XML_CDATA_SECTION_NODE:
625 fprintf(output, shift);
626 fprintf(output, "CDATA_SECTION\n");
627 break;
628 case XML_ENTITY_REF_NODE:
629 fprintf(output, shift);
630 fprintf(output, "ENTITY_REF(%s)\n", node->name);
631 break;
632 case XML_ENTITY_NODE:
633 fprintf(output, shift);
634 fprintf(output, "ENTITY\n");
635 break;
636 case XML_PI_NODE:
637 fprintf(output, shift);
638 fprintf(output, "PI %s\n", node->name);
639 break;
640 case XML_COMMENT_NODE:
641 fprintf(output, shift);
642 fprintf(output, "COMMENT\n");
643 break;
644 case XML_DOCUMENT_NODE:
645 case XML_HTML_DOCUMENT_NODE:
646 fprintf(output, shift);
647 fprintf(output, "Error, DOCUMENT found here\n");
648 break;
649 case XML_DOCUMENT_TYPE_NODE:
650 fprintf(output, shift);
651 fprintf(output, "DOCUMENT_TYPE\n");
652 break;
653 case XML_DOCUMENT_FRAG_NODE:
654 fprintf(output, shift);
655 fprintf(output, "DOCUMENT_FRAG\n");
656 break;
657 case XML_NOTATION_NODE:
658 fprintf(output, shift);
659 fprintf(output, "NOTATION\n");
660 break;
661 case XML_DTD_NODE:
662 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
663 return;
664 case XML_ELEMENT_DECL:
665 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
666 return;
667 case XML_ATTRIBUTE_DECL:
668 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
669 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000670 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000671 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
672 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000673 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000674 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
675 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000676 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000677 fprintf(output, shift);
678 fprintf(output, "INCLUDE START\n");
679 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000680 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000681 fprintf(output, shift);
682 fprintf(output, "INCLUDE END\n");
683 return;
684 default:
685 fprintf(output, shift);
686 fprintf(output, "NODE_%d !!!\n", node->type);
687 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000688 }
689 if (node->doc == NULL) {
690 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000691 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000692 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000693 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000694 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
695 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000696 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000697 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000698 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
699 shift[2 * i] = shift[2 * i + 1] = ' ';
700 shift[2 * i + 2] = shift[2 * i + 3] = 0;
701 fprintf(output, shift);
702 fprintf(output, "content=");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000703 xmlDebugDumpString(output, node->content);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000704 fprintf(output, "\n");
705 }
Owen Taylor3473f882001-02-23 17:55:21 +0000706 } else {
707 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000708
709 ent = xmlGetDocEntity(node->doc, node->name);
710 if (ent != NULL)
711 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000712 }
713 /*
714 * Do a bit of checking
715 */
716 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000717 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000718 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000719 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000720 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000721 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000722 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000723 if ((node->parent != NULL) && (node->parent->children != node))
724 fprintf(output,
725 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000726 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000727 if (node->prev->next != node)
728 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000729 }
730 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000731 if ((node->parent != NULL) && (node->parent->last != node))
732 fprintf(output,
733 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000734 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000735 if (node->next->prev != node)
736 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000737 }
738}
739
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000740/**
741 * xmlDebugDumpNode:
742 * @output: the FILE * for the output
743 * @node: the node
744 * @depth: the indentation level.
745 *
746 * Dumps debug information for the element node, it is recursive
747 */
748void
749xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
750{
Daniel Veillard7db38712002-02-07 16:39:11 +0000751 if (output == NULL)
752 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000753 if (node == NULL) {
754 int i;
755 char shift[100];
756
757 for (i = 0; ((i < depth) && (i < 25)); i++)
758 shift[2 * i] = shift[2 * i + 1] = ' ';
759 shift[2 * i] = shift[2 * i + 1] = 0;
760
761 fprintf(output, shift);
762 fprintf(output, "node is NULL\n");
763 return;
764 }
Owen Taylor3473f882001-02-23 17:55:21 +0000765 xmlDebugDumpOneNode(output, node, depth);
766 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000767 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000768}
769
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000770/**
771 * xmlDebugDumpNodeList:
772 * @output: the FILE * for the output
773 * @node: the node list
774 * @depth: the indentation level.
775 *
776 * Dumps debug information for the list of element node, it is recursive
777 */
778void
779xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
780{
Daniel Veillard7db38712002-02-07 16:39:11 +0000781 if (output == NULL)
782 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000783 while (node != NULL) {
784 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000785 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000786 }
787}
788
789
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000790/**
791 * xmlDebugDumpDocumentHead:
792 * @output: the FILE * for the output
793 * @doc: the document
794 *
795 * Dumps debug information cncerning the document, not recursive
796 */
797void
798xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
799{
800 if (output == NULL)
801 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000802 if (doc == NULL) {
803 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000804 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000805 }
806
807 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000808 case XML_ELEMENT_NODE:
809 fprintf(output, "Error, ELEMENT found here ");
810 break;
811 case XML_ATTRIBUTE_NODE:
812 fprintf(output, "Error, ATTRIBUTE found here\n");
813 break;
814 case XML_TEXT_NODE:
815 fprintf(output, "Error, TEXT\n");
816 break;
817 case XML_CDATA_SECTION_NODE:
818 fprintf(output, "Error, CDATA_SECTION\n");
819 break;
820 case XML_ENTITY_REF_NODE:
821 fprintf(output, "Error, ENTITY_REF\n");
822 break;
823 case XML_ENTITY_NODE:
824 fprintf(output, "Error, ENTITY\n");
825 break;
826 case XML_PI_NODE:
827 fprintf(output, "Error, PI\n");
828 break;
829 case XML_COMMENT_NODE:
830 fprintf(output, "Error, COMMENT\n");
831 break;
832 case XML_DOCUMENT_NODE:
833 fprintf(output, "DOCUMENT\n");
834 break;
835 case XML_HTML_DOCUMENT_NODE:
836 fprintf(output, "HTML DOCUMENT\n");
837 break;
838 case XML_DOCUMENT_TYPE_NODE:
839 fprintf(output, "Error, DOCUMENT_TYPE\n");
840 break;
841 case XML_DOCUMENT_FRAG_NODE:
842 fprintf(output, "Error, DOCUMENT_FRAG\n");
843 break;
844 case XML_NOTATION_NODE:
845 fprintf(output, "Error, NOTATION\n");
846 break;
847 default:
848 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000849 }
850 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000851 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000852 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000853 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000854 }
855 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000856 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000857 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000858 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000859 }
860 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000861 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000862 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000863 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000864 }
865 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000866 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000867 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000868 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000869 }
870 if (doc->standalone)
871 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000872 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000873 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
874}
875
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000876/**
877 * xmlDebugDumpDocument:
878 * @output: the FILE * for the output
879 * @doc: the document
880 *
881 * Dumps debug information for the document, it's recursive
882 */
883void
884xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
885{
886 if (output == NULL)
887 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000888 if (doc == NULL) {
889 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000890 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000891 }
892 xmlDebugDumpDocumentHead(output, doc);
893 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000894 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000895 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000896}
Owen Taylor3473f882001-02-23 17:55:21 +0000897
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000898/**
899 * xmlDebugDumpDTD:
900 * @output: the FILE * for the output
901 * @dtd: the DTD
902 *
903 * Dumps debug information for the DTD
904 */
905void
906xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
907{
Daniel Veillard7db38712002-02-07 16:39:11 +0000908 if (output == NULL)
909 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000910 if (dtd == NULL) {
911 fprintf(output, "DTD is NULL\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000912 return;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000913 }
Owen Taylor3473f882001-02-23 17:55:21 +0000914 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000915 fprintf(output, "PBM: not a DTD\n");
916 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000917 }
918 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000919 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000920 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000921 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000922 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000923 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000924 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000925 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000926 fprintf(output, "\n");
927 /*
928 * Do a bit of checking
929 */
930 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000931 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000932 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000933 if ((dtd->parent != NULL)
934 && (dtd->parent->children != (xmlNodePtr) dtd))
935 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000936 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000937 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000938 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000939 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000940 }
941 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000942 if ((dtd->parent != NULL)
943 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000944 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000945 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000946 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000947 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000948 }
949 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000950 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000951 else
952 xmlDebugDumpNodeList(output, dtd->children, 1);
953}
954
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000955static void
956xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000957 if (cur == NULL) {
958 fprintf(output, "Entity is NULL");
959 return;
960 }
Owen Taylor3473f882001-02-23 17:55:21 +0000961 fprintf(output, "%s : ", cur->name);
962 switch (cur->etype) {
963 case XML_INTERNAL_GENERAL_ENTITY:
964 fprintf(output, "INTERNAL GENERAL, ");
965 break;
966 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
967 fprintf(output, "EXTERNAL PARSED, ");
968 break;
969 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
970 fprintf(output, "EXTERNAL UNPARSED, ");
971 break;
972 case XML_INTERNAL_PARAMETER_ENTITY:
973 fprintf(output, "INTERNAL PARAMETER, ");
974 break;
975 case XML_EXTERNAL_PARAMETER_ENTITY:
976 fprintf(output, "EXTERNAL PARAMETER, ");
977 break;
978 default:
979 fprintf(output, "UNKNOWN TYPE %d",
980 cur->etype);
981 }
982 if (cur->ExternalID != NULL)
983 fprintf(output, "ID \"%s\"", cur->ExternalID);
984 if (cur->SystemID != NULL)
985 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
986 if (cur->orig != NULL)
987 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000988 if ((cur->type != XML_ELEMENT_NODE) &&
989 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000990 fprintf(output, "\n content \"%s\"", cur->content);
991 fprintf(output, "\n");
992}
993
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000994/**
995 * xmlDebugDumpEntities:
996 * @output: the FILE * for the output
997 * @doc: the document
998 *
999 * Dumps debug information for all the entities in use by the document
1000 */
1001void
1002xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1003{
1004 if (output == NULL)
1005 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001006 if (doc == NULL) {
1007 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001008 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001009 }
1010
1011 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001012 case XML_ELEMENT_NODE:
1013 fprintf(output, "Error, ELEMENT found here ");
1014 break;
1015 case XML_ATTRIBUTE_NODE:
1016 fprintf(output, "Error, ATTRIBUTE found here\n");
1017 break;
1018 case XML_TEXT_NODE:
1019 fprintf(output, "Error, TEXT\n");
1020 break;
1021 case XML_CDATA_SECTION_NODE:
1022 fprintf(output, "Error, CDATA_SECTION\n");
1023 break;
1024 case XML_ENTITY_REF_NODE:
1025 fprintf(output, "Error, ENTITY_REF\n");
1026 break;
1027 case XML_ENTITY_NODE:
1028 fprintf(output, "Error, ENTITY\n");
1029 break;
1030 case XML_PI_NODE:
1031 fprintf(output, "Error, PI\n");
1032 break;
1033 case XML_COMMENT_NODE:
1034 fprintf(output, "Error, COMMENT\n");
1035 break;
1036 case XML_DOCUMENT_NODE:
1037 fprintf(output, "DOCUMENT\n");
1038 break;
1039 case XML_HTML_DOCUMENT_NODE:
1040 fprintf(output, "HTML DOCUMENT\n");
1041 break;
1042 case XML_DOCUMENT_TYPE_NODE:
1043 fprintf(output, "Error, DOCUMENT_TYPE\n");
1044 break;
1045 case XML_DOCUMENT_FRAG_NODE:
1046 fprintf(output, "Error, DOCUMENT_FRAG\n");
1047 break;
1048 case XML_NOTATION_NODE:
1049 fprintf(output, "Error, NOTATION\n");
1050 break;
1051 default:
1052 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +00001053 }
1054 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001055 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1056 doc->intSubset->entities;
1057
1058 fprintf(output, "Entities in internal subset\n");
1059 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1060 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001061 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001062 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001063 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001064 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1065 doc->extSubset->entities;
1066
1067 fprintf(output, "Entities in external subset\n");
1068 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1069 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001070 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001071 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001072}
1073
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001074/**
1075 * xmlLsCountNode:
1076 * @node: the node to count
1077 *
1078 * Count the children of @node.
1079 *
1080 * Returns the number of children of @node.
1081 */
1082int
1083xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001084 int ret = 0;
1085 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001086
1087 if (node == NULL)
1088 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001089
1090 switch (node->type) {
1091 case XML_ELEMENT_NODE:
1092 list = node->children;
1093 break;
1094 case XML_DOCUMENT_NODE:
1095 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001096#ifdef LIBXML_DOCB_ENABLED
1097 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001098#endif
1099 list = ((xmlDocPtr) node)->children;
1100 break;
1101 case XML_ATTRIBUTE_NODE:
1102 list = ((xmlAttrPtr) node)->children;
1103 break;
1104 case XML_TEXT_NODE:
1105 case XML_CDATA_SECTION_NODE:
1106 case XML_PI_NODE:
1107 case XML_COMMENT_NODE:
1108 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001109 ret = xmlStrlen(node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001110 }
1111 break;
1112 case XML_ENTITY_REF_NODE:
1113 case XML_DOCUMENT_TYPE_NODE:
1114 case XML_ENTITY_NODE:
1115 case XML_DOCUMENT_FRAG_NODE:
1116 case XML_NOTATION_NODE:
1117 case XML_DTD_NODE:
1118 case XML_ELEMENT_DECL:
1119 case XML_ATTRIBUTE_DECL:
1120 case XML_ENTITY_DECL:
1121 case XML_NAMESPACE_DECL:
1122 case XML_XINCLUDE_START:
1123 case XML_XINCLUDE_END:
1124 ret = 1;
1125 break;
1126 }
1127 for (;list != NULL;ret++)
1128 list = list->next;
1129 return(ret);
1130}
1131
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001132/**
1133 * xmlLsOneNode:
1134 * @output: the FILE * for the output
1135 * @node: the node to dump
1136 *
1137 * Dump to @output the type and name of @node.
1138 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001139void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001140xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001141 if (node == NULL) {
1142 fprintf(output, "NULL\n");
1143 return;
1144 }
Owen Taylor3473f882001-02-23 17:55:21 +00001145 switch (node->type) {
1146 case XML_ELEMENT_NODE:
1147 fprintf(output, "-");
1148 break;
1149 case XML_ATTRIBUTE_NODE:
1150 fprintf(output, "a");
1151 break;
1152 case XML_TEXT_NODE:
1153 fprintf(output, "t");
1154 break;
1155 case XML_CDATA_SECTION_NODE:
Daniel Veillard75be0132002-03-13 10:03:35 +00001156 fprintf(output, "C");
Owen Taylor3473f882001-02-23 17:55:21 +00001157 break;
1158 case XML_ENTITY_REF_NODE:
1159 fprintf(output, "e");
1160 break;
1161 case XML_ENTITY_NODE:
1162 fprintf(output, "E");
1163 break;
1164 case XML_PI_NODE:
1165 fprintf(output, "p");
1166 break;
1167 case XML_COMMENT_NODE:
1168 fprintf(output, "c");
1169 break;
1170 case XML_DOCUMENT_NODE:
1171 fprintf(output, "d");
1172 break;
1173 case XML_HTML_DOCUMENT_NODE:
1174 fprintf(output, "h");
1175 break;
1176 case XML_DOCUMENT_TYPE_NODE:
1177 fprintf(output, "T");
1178 break;
1179 case XML_DOCUMENT_FRAG_NODE:
1180 fprintf(output, "F");
1181 break;
1182 case XML_NOTATION_NODE:
1183 fprintf(output, "N");
1184 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001185 case XML_NAMESPACE_DECL:
1186 fprintf(output, "n");
1187 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001188 default:
1189 fprintf(output, "?");
1190 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001191 if (node->type != XML_NAMESPACE_DECL) {
1192 if (node->properties != NULL)
1193 fprintf(output, "a");
1194 else
1195 fprintf(output, "-");
1196 if (node->nsDef != NULL)
1197 fprintf(output, "n");
1198 else
1199 fprintf(output, "-");
1200 }
Owen Taylor3473f882001-02-23 17:55:21 +00001201
1202 fprintf(output, " %8d ", xmlLsCountNode(node));
1203
1204 switch (node->type) {
1205 case XML_ELEMENT_NODE:
1206 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001207 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001208 break;
1209 case XML_ATTRIBUTE_NODE:
1210 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001211 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001212 break;
1213 case XML_TEXT_NODE:
1214 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001215 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001216 }
1217 break;
1218 case XML_CDATA_SECTION_NODE:
1219 break;
1220 case XML_ENTITY_REF_NODE:
1221 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001222 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001223 break;
1224 case XML_ENTITY_NODE:
1225 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001226 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001227 break;
1228 case XML_PI_NODE:
1229 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001230 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001231 break;
1232 case XML_COMMENT_NODE:
1233 break;
1234 case XML_DOCUMENT_NODE:
1235 break;
1236 case XML_HTML_DOCUMENT_NODE:
1237 break;
1238 case XML_DOCUMENT_TYPE_NODE:
1239 break;
1240 case XML_DOCUMENT_FRAG_NODE:
1241 break;
1242 case XML_NOTATION_NODE:
1243 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001244 case XML_NAMESPACE_DECL: {
1245 xmlNsPtr ns = (xmlNsPtr) node;
1246
1247 if (ns->prefix == NULL)
1248 fprintf(output, "default -> %s", ns->href);
1249 else
1250 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1251 break;
1252 }
Owen Taylor3473f882001-02-23 17:55:21 +00001253 default:
1254 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001255 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001256 }
1257 fprintf(output, "\n");
1258}
1259
Daniel Veillard78d12092001-10-11 09:12:24 +00001260/**
1261 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001262 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001263 *
1264 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001265 *
1266 * Returns a pointer to either "True" or "False"
1267 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001268const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001269xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001270{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001271 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001272 return("True");
1273 else
1274 return("False");
1275}
1276
Owen Taylor3473f882001-02-23 17:55:21 +00001277/****************************************************************
1278 * *
1279 * The XML shell related functions *
1280 * *
1281 ****************************************************************/
1282
Daniel Veillard78d12092001-10-11 09:12:24 +00001283
1284
Owen Taylor3473f882001-02-23 17:55:21 +00001285/*
1286 * TODO: Improvement/cleanups for the XML shell
1287 * - allow to shell out an editor on a subpart
1288 * - cleanup function registrations (with help) and calling
1289 * - provide registration routines
1290 */
1291
1292/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001293 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001294 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001295 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001296 *
1297 * Print the xpath error to libxml default error channel
1298 */
1299void
1300xmlShellPrintXPathError(int errorType, const char *arg)
1301{
1302 const char *default_arg = "Result";
1303
1304 if (!arg)
1305 arg = default_arg;
1306
1307 switch (errorType) {
1308 case XPATH_UNDEFINED:
1309 xmlGenericError(xmlGenericErrorContext,
1310 "%s: no such node\n", arg);
1311 break;
1312
1313 case XPATH_BOOLEAN:
1314 xmlGenericError(xmlGenericErrorContext,
1315 "%s is a Boolean\n", arg);
1316 break;
1317 case XPATH_NUMBER:
1318 xmlGenericError(xmlGenericErrorContext,
1319 "%s is a number\n", arg);
1320 break;
1321 case XPATH_STRING:
1322 xmlGenericError(xmlGenericErrorContext,
1323 "%s is a string\n", arg);
1324 break;
1325 case XPATH_POINT:
1326 xmlGenericError(xmlGenericErrorContext,
1327 "%s is a point\n", arg);
1328 break;
1329 case XPATH_RANGE:
1330 xmlGenericError(xmlGenericErrorContext,
1331 "%s is a range\n", arg);
1332 break;
1333 case XPATH_LOCATIONSET:
1334 xmlGenericError(xmlGenericErrorContext,
1335 "%s is a range\n", arg);
1336 break;
1337 case XPATH_USERS:
1338 xmlGenericError(xmlGenericErrorContext,
1339 "%s is user-defined\n", arg);
1340 break;
1341 case XPATH_XSLT_TREE:
1342 xmlGenericError(xmlGenericErrorContext,
1343 "%s is an XSLT value tree\n", arg);
1344 break;
1345 }
1346 xmlGenericError(xmlGenericErrorContext,
1347 "Try casting the result string function (xpath builtin)\n",
1348 arg);
1349}
1350
1351
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001352#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001353/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001354 * xmlShellPrintNodeCtxt:
1355 * @ctxt : a non-null shell context
1356 * @node : a non-null node to print to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001357 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001358 * Print node to the output FILE
1359 */
1360static void
1361xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1362{
Daniel Veillard01992e02002-10-09 10:20:30 +00001363 FILE *fp;
1364
1365 if (!node)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001366 return;
Daniel Veillard01992e02002-10-09 10:20:30 +00001367 if (ctxt == NULL)
1368 fp = stdout;
1369 else
1370 fp = ctxt->output;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001371
1372 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001373 xmlDocDump(fp, (xmlDocPtr) node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001374 else if (node->type == XML_ATTRIBUTE_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001375 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001376 else
Daniel Veillard01992e02002-10-09 10:20:30 +00001377 xmlElemDump(fp, node->doc, node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001378
Daniel Veillard01992e02002-10-09 10:20:30 +00001379 fprintf(fp, "\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00001380}
1381
1382/**
1383 * xmlShellPrintNode:
1384 * @node : a non-null node to print to the output FILE
1385 *
1386 * Print node to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001387 */
1388void
1389xmlShellPrintNode(xmlNodePtr node)
1390{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001391 xmlShellPrintNodeCtxt(NULL, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001392}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001393#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001394
Daniel Veillard78d12092001-10-11 09:12:24 +00001395/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001396 * xmlShellPrintXPathResultCtxt:
1397 * @ctxt: a valid shell context
Daniel Veillard9d06d302002-01-22 18:15:52 +00001398 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001399 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001400 * Prints result to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001401 */
Daniel Veillard321be0c2002-10-08 21:26:42 +00001402static void
1403xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
Daniel Veillard78d12092001-10-11 09:12:24 +00001404{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001405 if (!ctxt)
1406 return;
Daniel Veillard78d12092001-10-11 09:12:24 +00001407
1408 if (list != NULL) {
1409 switch (list->type) {
1410 case XPATH_NODESET:{
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001411#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001412 int indx;
1413
1414 if (list->nodesetval) {
1415 for (indx = 0; indx < list->nodesetval->nodeNr;
1416 indx++) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001417 xmlShellPrintNodeCtxt(ctxt,
1418 list->nodesetval->nodeTab[indx]);
Daniel Veillard78d12092001-10-11 09:12:24 +00001419 }
1420 } else {
1421 xmlGenericError(xmlGenericErrorContext,
1422 "Empty node set\n");
1423 }
1424 break;
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001425#else
1426 xmlGenericError(xmlGenericErrorContext,
1427 "Node set\n");
1428#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001429 }
1430 case XPATH_BOOLEAN:
1431 xmlGenericError(xmlGenericErrorContext,
1432 "Is a Boolean:%s\n",
1433 xmlBoolToText(list->boolval));
1434 break;
1435 case XPATH_NUMBER:
1436 xmlGenericError(xmlGenericErrorContext,
1437 "Is a number:%0g\n", list->floatval);
1438 break;
1439 case XPATH_STRING:
1440 xmlGenericError(xmlGenericErrorContext,
1441 "Is a string:%s\n", list->stringval);
1442 break;
1443
1444 default:
1445 xmlShellPrintXPathError(list->type, NULL);
1446 }
1447 }
1448}
1449
1450/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001451 * xmlShellPrintXPathResult:
1452 * @list: a valid result generated by an xpath evaluation
1453 *
1454 * Prints result to the output FILE
1455 */
1456void
1457xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1458{
1459 xmlShellPrintXPathResultCtxt(NULL, list);
1460}
1461
1462/**
Owen Taylor3473f882001-02-23 17:55:21 +00001463 * xmlShellList:
1464 * @ctxt: the shell context
1465 * @arg: unused
1466 * @node: a node
1467 * @node2: unused
1468 *
1469 * Implements the XML shell function "ls"
1470 * Does an Unix like listing of the given node (like a directory)
1471 *
1472 * Returns 0
1473 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001474int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001475xmlShellList(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001476 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1477 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1478{
Owen Taylor3473f882001-02-23 17:55:21 +00001479 xmlNodePtr cur;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001480 if (!ctxt)
1481 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001482 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001483 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001484 return (0);
1485 }
Owen Taylor3473f882001-02-23 17:55:21 +00001486 if ((node->type == XML_DOCUMENT_NODE) ||
1487 (node->type == XML_HTML_DOCUMENT_NODE)) {
1488 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001489 } else if (node->type == XML_NAMESPACE_DECL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001490 xmlLsOneNode(ctxt->output, node);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001491 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001492 } else if (node->children != NULL) {
1493 cur = node->children;
1494 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001495 xmlLsOneNode(ctxt->output, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001496 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001497 }
1498 while (cur != NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001499 xmlLsOneNode(ctxt->output, cur);
Daniel Veillard78d12092001-10-11 09:12:24 +00001500 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001501 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001502 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001503}
1504
1505/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001506 * xmlShellBase:
1507 * @ctxt: the shell context
1508 * @arg: unused
1509 * @node: a node
1510 * @node2: unused
1511 *
1512 * Implements the XML shell function "base"
1513 * dumps the current XML base of the node
1514 *
1515 * Returns 0
1516 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001517int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001518xmlShellBase(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001519 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1520 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1521{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001522 xmlChar *base;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001523 if (!ctxt)
1524 return 0;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001525 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001526 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001527 return (0);
1528 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001529
1530 base = xmlNodeGetBase(node->doc, node);
1531
1532 if (base == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001533 fprintf(ctxt->output, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001534 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001535 fprintf(ctxt->output, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001536 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001537 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001538 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001539}
1540
Daniel Veillardb34321c2004-03-04 17:09:47 +00001541#ifdef LIBXML_TREE_ENABLED
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001542/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001543 * xmlShellSetBase:
1544 * @ctxt: the shell context
1545 * @arg: the new base
1546 * @node: a node
1547 * @node2: unused
1548 *
1549 * Implements the XML shell function "setbase"
1550 * change the current XML base of the node
1551 *
1552 * Returns 0
1553 */
1554static int
1555xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1556 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1557 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1558{
1559 xmlNodeSetBase(node, (xmlChar*) arg);
1560 return (0);
1561}
Daniel Veillard2156d432004-03-04 15:59:36 +00001562#endif
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001563
Daniel Veillardbbaa9972004-06-16 14:08:33 +00001564#ifdef LIBXML_XPATH_ENABLED
1565/**
1566 * xmlShellRegisterNamespace:
1567 * @ctxt: the shell context
1568 * @arg: a string in prefix=nsuri format
1569 * @node: unused
1570 * @node2: unused
1571 *
1572 * Implements the XML shell function "setns"
1573 * register/unregister a prefix=namespace pair
1574 * on the XPath context
1575 *
1576 * Returns 0 on success and a negative value otherwise.
1577 */
1578static int
1579xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
1580 xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1581{
1582 xmlChar* nsListDup;
1583 xmlChar* prefix;
1584 xmlChar* href;
1585 xmlChar* next;
1586
1587 nsListDup = xmlStrdup((xmlChar *) arg);
1588 next = nsListDup;
1589 while(next != NULL) {
1590 /* skip spaces */
1591 /*while((*next) == ' ') next++;*/
1592 if((*next) == '\0') break;
1593
1594 /* find prefix */
1595 prefix = next;
1596 next = (xmlChar*)xmlStrchr(next, '=');
1597 if(next == NULL) {
1598 fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
1599 xmlFree(nsListDup);
1600 return(-1);
1601 }
1602 *(next++) = '\0';
1603
1604 /* find href */
1605 href = next;
1606 next = (xmlChar*)xmlStrchr(next, ' ');
1607 if(next != NULL) {
1608 *(next++) = '\0';
1609 }
1610
1611 /* do register namespace */
1612 if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
1613 fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
1614 xmlFree(nsListDup);
1615 return(-1);
1616 }
1617 }
1618
1619 xmlFree(nsListDup);
1620 return(0);
1621}
1622#endif
1623
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001624/**
Daniel Veillard1e208222002-10-22 14:25:25 +00001625 * xmlShellGrep:
1626 * @ctxt: the shell context
1627 * @arg: the string or regular expression to find
1628 * @node: a node
1629 * @node2: unused
1630 *
1631 * Implements the XML shell function "grep"
1632 * dumps informations about the node (namespace, attributes, content).
1633 *
1634 * Returns 0
1635 */
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001636static int
Daniel Veillard1e208222002-10-22 14:25:25 +00001637xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1638 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1639{
1640 if (!ctxt)
1641 return (0);
1642 if (node == NULL)
1643 return (0);
1644 if (arg == NULL)
1645 return (0);
1646#ifdef LIBXML_REGEXP_ENABLED
1647 if ((xmlStrchr((xmlChar *) arg, '?')) ||
1648 (xmlStrchr((xmlChar *) arg, '*')) ||
1649 (xmlStrchr((xmlChar *) arg, '.')) ||
1650 (xmlStrchr((xmlChar *) arg, '['))) {
1651 }
1652#endif
1653 while (node != NULL) {
1654 if (node->type == XML_COMMENT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001655 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001656
1657 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
1658 xmlShellList(ctxt, NULL, node, NULL);
1659 }
1660 } else if (node->type == XML_TEXT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001661 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001662
1663 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001664 xmlShellList(ctxt, NULL, node->parent, NULL);
Daniel Veillard1e208222002-10-22 14:25:25 +00001665 }
1666 }
1667
1668 /*
1669 * Browse the full subtree, deep first
1670 */
1671
1672 if ((node->type == XML_DOCUMENT_NODE) ||
1673 (node->type == XML_HTML_DOCUMENT_NODE)) {
1674 node = ((xmlDocPtr) node)->children;
1675 } else if ((node->children != NULL)
1676 && (node->type != XML_ENTITY_REF_NODE)) {
1677 /* deep first */
1678 node = node->children;
1679 } else if (node->next != NULL) {
1680 /* then siblings */
1681 node = node->next;
1682 } else {
1683 /* go up to parents->next if needed */
1684 while (node != NULL) {
1685 if (node->parent != NULL) {
1686 node = node->parent;
1687 }
1688 if (node->next != NULL) {
1689 node = node->next;
1690 break;
1691 }
1692 if (node->parent == NULL) {
1693 node = NULL;
1694 break;
1695 }
1696 }
1697 }
1698 }
1699 return (0);
1700}
1701
1702/**
Owen Taylor3473f882001-02-23 17:55:21 +00001703 * xmlShellDir:
1704 * @ctxt: the shell context
1705 * @arg: unused
1706 * @node: a node
1707 * @node2: unused
1708 *
1709 * Implements the XML shell function "dir"
1710 * dumps informations about the node (namespace, attributes, content).
1711 *
1712 * Returns 0
1713 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001714int
1715xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1716 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1717 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1718{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001719 if (!ctxt)
1720 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001721 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001722 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001723 return (0);
1724 }
Owen Taylor3473f882001-02-23 17:55:21 +00001725 if ((node->type == XML_DOCUMENT_NODE) ||
1726 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001727 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001728 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001729 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001730 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001731 xmlDebugDumpOneNode(ctxt->output, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001732 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001733 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001734}
1735
Daniel Veillard522bc602004-02-21 11:53:09 +00001736#ifdef LIBXML_SCHEMAS_ENABLED
1737/**
1738 * xmlShellRNGValidate:
1739 * @ctxt: the shell context
1740 * @schemas: the path to the Relax-NG schemas
1741 * @node: a node
1742 * @node2: unused
1743 *
1744 * Implements the XML shell function "relaxng"
1745 * validating the instance against a Relax-NG schemas
1746 *
1747 * Returns 0
1748 */
1749static int
1750xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
1751 xmlNodePtr node ATTRIBUTE_UNUSED,
1752 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1753{
1754 xmlRelaxNGPtr relaxngschemas;
1755 xmlRelaxNGParserCtxtPtr ctxt;
1756 xmlRelaxNGValidCtxtPtr vctxt;
1757 int ret;
1758
1759 ctxt = xmlRelaxNGNewParserCtxt(schemas);
1760 xmlRelaxNGSetParserErrors(ctxt,
1761 (xmlRelaxNGValidityErrorFunc) fprintf,
1762 (xmlRelaxNGValidityWarningFunc) fprintf,
1763 stderr);
1764 relaxngschemas = xmlRelaxNGParse(ctxt);
1765 xmlRelaxNGFreeParserCtxt(ctxt);
1766 if (relaxngschemas == NULL) {
1767 xmlGenericError(xmlGenericErrorContext,
1768 "Relax-NG schema %s failed to compile\n", schemas);
1769 return(-1);
1770 }
1771 vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
1772 xmlRelaxNGSetValidErrors(vctxt,
1773 (xmlRelaxNGValidityErrorFunc) fprintf,
1774 (xmlRelaxNGValidityWarningFunc) fprintf,
1775 stderr);
1776 ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
1777 if (ret == 0) {
1778 fprintf(stderr, "%s validates\n", sctxt->filename);
1779 } else if (ret > 0) {
1780 fprintf(stderr, "%s fails to validate\n", sctxt->filename);
1781 } else {
1782 fprintf(stderr, "%s validation generated an internal error\n",
1783 sctxt->filename);
1784 }
1785 xmlRelaxNGFreeValidCtxt(vctxt);
1786 if (relaxngschemas != NULL)
1787 xmlRelaxNGFree(relaxngschemas);
1788 return(0);
1789}
1790#endif
1791
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001792#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001793/**
1794 * xmlShellCat:
1795 * @ctxt: the shell context
1796 * @arg: unused
1797 * @node: a node
1798 * @node2: unused
1799 *
1800 * Implements the XML shell function "cat"
1801 * dumps the serialization node content (XML or HTML).
1802 *
1803 * Returns 0
1804 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001805int
1806xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1807 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1808{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001809 if (!ctxt)
1810 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001811 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001812 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001813 return (0);
1814 }
Owen Taylor3473f882001-02-23 17:55:21 +00001815 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1816#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001817 if (node->type == XML_HTML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001818 htmlDocDump(ctxt->output, (htmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001819 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001820 htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001821#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001822 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001823 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001824 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001825 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001826#endif /* LIBXML_HTML_ENABLED */
1827 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001828 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001829 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001830 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001831 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001832 }
Daniel Veillard321be0c2002-10-08 21:26:42 +00001833 fprintf(ctxt->output, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001834 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001835}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001836#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001837
1838/**
1839 * xmlShellLoad:
1840 * @ctxt: the shell context
1841 * @filename: the file name
1842 * @node: unused
1843 * @node2: unused
1844 *
1845 * Implements the XML shell function "load"
1846 * loads a new document specified by the filename
1847 *
1848 * Returns 0 or -1 if loading failed
1849 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001850int
1851xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1852 xmlNodePtr node ATTRIBUTE_UNUSED,
1853 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1854{
Owen Taylor3473f882001-02-23 17:55:21 +00001855 xmlDocPtr doc;
1856 int html = 0;
1857
1858 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001859 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001860
1861 if (html) {
1862#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001863 doc = htmlParseFile(filename, NULL);
1864#else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001865 fprintf(ctxt->output, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001866 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001867#endif /* LIBXML_HTML_ENABLED */
1868 } else {
Daniel Veillardebe25d42004-03-25 09:35:49 +00001869 doc = xmlReadFile(filename,NULL,0);
Owen Taylor3473f882001-02-23 17:55:21 +00001870 }
1871 if (doc != NULL) {
1872 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001873 xmlFreeDoc(ctxt->doc);
1874 }
1875 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001876#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001877 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001878#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001879 xmlFree(ctxt->filename);
1880 ctxt->doc = doc;
1881 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001882#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001883 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001884#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard85095e22003-04-23 13:56:44 +00001885 ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001886 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001887 return (-1);
1888 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001889}
1890
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001891#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001892/**
1893 * xmlShellWrite:
1894 * @ctxt: the shell context
1895 * @filename: the file name
1896 * @node: a node in the tree
1897 * @node2: unused
1898 *
1899 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001900 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001901 * of the subtree under the @node specified
1902 *
1903 * Returns 0 or -1 in case of error
1904 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001905int
Owen Taylor3473f882001-02-23 17:55:21 +00001906xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001907 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1908{
Owen Taylor3473f882001-02-23 17:55:21 +00001909 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001910 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001911 if ((filename == NULL) || (filename[0] == 0)) {
1912 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001913 "Write command requires a filename argument\n");
1914 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001915 }
1916#ifdef W_OK
1917 if (access((char *) filename, W_OK)) {
1918 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001919 "Cannot write to %s\n", filename);
1920 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001921 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001922#endif
1923 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001924 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001925 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1926 xmlGenericError(xmlGenericErrorContext,
1927 "Failed to write to %s\n", filename);
1928 return (-1);
1929 }
1930 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001931 case XML_HTML_DOCUMENT_NODE:
1932#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001933 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1934 xmlGenericError(xmlGenericErrorContext,
1935 "Failed to write to %s\n", filename);
1936 return (-1);
1937 }
Owen Taylor3473f882001-02-23 17:55:21 +00001938#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001939 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1940 xmlGenericError(xmlGenericErrorContext,
1941 "Failed to write to %s\n", filename);
1942 return (-1);
1943 }
Owen Taylor3473f882001-02-23 17:55:21 +00001944#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001945 break;
1946 default:{
1947 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001948
Daniel Veillard78d12092001-10-11 09:12:24 +00001949 f = fopen((char *) filename, "w");
1950 if (f == NULL) {
1951 xmlGenericError(xmlGenericErrorContext,
1952 "Failed to write to %s\n", filename);
1953 return (-1);
1954 }
1955 xmlElemDump(f, ctxt->doc, node);
1956 fclose(f);
1957 }
Owen Taylor3473f882001-02-23 17:55:21 +00001958 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001959 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001960}
1961
1962/**
1963 * xmlShellSave:
1964 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001965 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00001966 * @node: unused
1967 * @node2: unused
1968 *
1969 * Implements the XML shell function "save"
1970 * Write the current document to the filename, or it's original name
1971 *
1972 * Returns 0 or -1 in case of error
1973 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001974int
1975xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1976 xmlNodePtr node ATTRIBUTE_UNUSED,
1977 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1978{
Owen Taylor3473f882001-02-23 17:55:21 +00001979 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001980 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001981 if ((filename == NULL) || (filename[0] == 0))
1982 filename = ctxt->filename;
1983#ifdef W_OK
1984 if (access((char *) filename, W_OK)) {
1985 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001986 "Cannot save to %s\n", filename);
1987 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001988 }
1989#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001990 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001991 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001992 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1993 xmlGenericError(xmlGenericErrorContext,
1994 "Failed to save to %s\n", filename);
1995 }
1996 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001997 case XML_HTML_DOCUMENT_NODE:
1998#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001999 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2000 xmlGenericError(xmlGenericErrorContext,
2001 "Failed to save to %s\n", filename);
2002 }
Owen Taylor3473f882001-02-23 17:55:21 +00002003#else
Daniel Veillard78d12092001-10-11 09:12:24 +00002004 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2005 xmlGenericError(xmlGenericErrorContext,
2006 "Failed to save to %s\n", filename);
2007 }
Owen Taylor3473f882001-02-23 17:55:21 +00002008#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002009 break;
2010 default:
2011 xmlGenericError(xmlGenericErrorContext,
2012 "To save to subparts of a document use the 'write' command\n");
2013 return (-1);
2014
Owen Taylor3473f882001-02-23 17:55:21 +00002015 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002016 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002017}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002018#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002019
Daniel Veillardf54cd532004-02-25 11:52:31 +00002020#ifdef LIBXML_VALID_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002021/**
2022 * xmlShellValidate:
2023 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002024 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00002025 * @node: unused
2026 * @node2: unused
2027 *
2028 * Implements the XML shell function "validate"
2029 * Validate the document, if a DTD path is provided, then the validation
2030 * is done against the given DTD.
2031 *
2032 * Returns 0 or -1 in case of error
2033 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002034int
2035xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
2036 xmlNodePtr node ATTRIBUTE_UNUSED,
2037 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2038{
Owen Taylor3473f882001-02-23 17:55:21 +00002039 xmlValidCtxt vctxt;
2040 int res = -1;
2041
2042 vctxt.userData = stderr;
2043 vctxt.error = (xmlValidityErrorFunc) fprintf;
2044 vctxt.warning = (xmlValidityWarningFunc) fprintf;
2045
2046 if ((dtd == NULL) || (dtd[0] == 0)) {
2047 res = xmlValidateDocument(&vctxt, ctxt->doc);
2048 } else {
2049 xmlDtdPtr subset;
2050
Daniel Veillard78d12092001-10-11 09:12:24 +00002051 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
2052 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00002053 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
2054
Daniel Veillard78d12092001-10-11 09:12:24 +00002055 xmlFreeDtd(subset);
2056 }
Owen Taylor3473f882001-02-23 17:55:21 +00002057 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002058 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00002059}
Daniel Veillardf54cd532004-02-25 11:52:31 +00002060#endif /* LIBXML_VALID_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002061
2062/**
2063 * xmlShellDu:
2064 * @ctxt: the shell context
2065 * @arg: unused
2066 * @tree: a node defining a subtree
2067 * @node2: unused
2068 *
2069 * Implements the XML shell function "du"
2070 * show the structure of the subtree under node @tree
2071 * If @tree is null, the command works on the current node.
2072 *
2073 * Returns 0 or -1 in case of error
2074 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002075int
Daniel Veillard321be0c2002-10-08 21:26:42 +00002076xmlShellDu(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00002077 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
2078 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2079{
Owen Taylor3473f882001-02-23 17:55:21 +00002080 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00002081 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00002082
Daniel Veillard321be0c2002-10-08 21:26:42 +00002083 if (!ctxt)
2084 return (-1);
2085
Daniel Veillard78d12092001-10-11 09:12:24 +00002086 if (tree == NULL)
2087 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002088 node = tree;
2089 while (node != NULL) {
2090 if ((node->type == XML_DOCUMENT_NODE) ||
2091 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002092 fprintf(ctxt->output, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002093 } else if (node->type == XML_ELEMENT_NODE) {
2094 for (i = 0; i < indent; i++)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002095 fprintf(ctxt->output, " ");
2096 fprintf(ctxt->output, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00002097 } else {
2098 }
Owen Taylor3473f882001-02-23 17:55:21 +00002099
Daniel Veillard78d12092001-10-11 09:12:24 +00002100 /*
2101 * Browse the full subtree, deep first
2102 */
Owen Taylor3473f882001-02-23 17:55:21 +00002103
2104 if ((node->type == XML_DOCUMENT_NODE) ||
2105 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002106 node = ((xmlDocPtr) node)->children;
2107 } else if ((node->children != NULL)
2108 && (node->type != XML_ENTITY_REF_NODE)) {
2109 /* deep first */
2110 node = node->children;
2111 indent++;
2112 } else if ((node != tree) && (node->next != NULL)) {
2113 /* then siblings */
2114 node = node->next;
2115 } else if (node != tree) {
2116 /* go up to parents->next if needed */
2117 while (node != tree) {
2118 if (node->parent != NULL) {
2119 node = node->parent;
2120 indent--;
2121 }
2122 if ((node != tree) && (node->next != NULL)) {
2123 node = node->next;
2124 break;
2125 }
2126 if (node->parent == NULL) {
2127 node = NULL;
2128 break;
2129 }
2130 if (node == tree) {
2131 node = NULL;
2132 break;
2133 }
2134 }
2135 /* exit condition */
2136 if (node == tree)
2137 node = NULL;
2138 } else
2139 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002140 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002141 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002142}
2143
2144/**
2145 * xmlShellPwd:
2146 * @ctxt: the shell context
2147 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00002148 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00002149 * @node2: unused
2150 *
2151 * Implements the XML shell function "pwd"
2152 * Show the full path from the root to the node, if needed building
2153 * thumblers when similar elements exists at a given ancestor level.
2154 * The output is compatible with XPath commands.
2155 *
2156 * Returns 0 or -1 in case of error
2157 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002158int
2159xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2160 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2161{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002162 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00002163
Daniel Veillard78d12092001-10-11 09:12:24 +00002164 if (node == NULL)
2165 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002166
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002167 path = xmlGetNodePath(node);
2168 if (path == NULL)
2169 return (-1);
2170
2171 /*
2172 * This test prevents buffer overflow, because this routine
2173 * is only called by xmlShell, in which the second argument is
2174 * 500 chars long.
2175 * It is a dirty hack before a cleaner solution is found.
2176 * Documentation should mention that the second argument must
2177 * be at least 500 chars long, and could be stripped if too long.
2178 */
2179 snprintf(buffer, 499, "%s", path);
2180 buffer[499] = '0';
2181 xmlFree(path);
2182
Daniel Veillard78d12092001-10-11 09:12:24 +00002183 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002184}
2185
2186/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002187 * xmlShell:
Owen Taylor3473f882001-02-23 17:55:21 +00002188 * @doc: the initial document
2189 * @filename: the output buffer
2190 * @input: the line reading function
Daniel Veillard321be0c2002-10-08 21:26:42 +00002191 * @output: the output FILE*, defaults to stdout if NULL
Owen Taylor3473f882001-02-23 17:55:21 +00002192 *
2193 * Implements the XML shell
2194 * This allow to load, validate, view, modify and save a document
2195 * using a environment similar to a UNIX commandline.
2196 */
2197void
2198xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00002199 FILE * output)
2200{
Owen Taylor3473f882001-02-23 17:55:21 +00002201 char prompt[500] = "/ > ";
2202 char *cmdline = NULL, *cur;
2203 int nbargs;
2204 char command[100];
2205 char arg[400];
2206 int i;
2207 xmlShellCtxtPtr ctxt;
2208 xmlXPathObjectPtr list;
2209
2210 if (doc == NULL)
2211 return;
2212 if (filename == NULL)
2213 return;
2214 if (input == NULL)
2215 return;
2216 if (output == NULL)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002217 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00002218 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00002219 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00002220 return;
2221 ctxt->loaded = 0;
2222 ctxt->doc = doc;
2223 ctxt->input = input;
2224 ctxt->output = output;
2225 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00002226 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00002227
2228#ifdef LIBXML_XPATH_ENABLED
2229 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2230 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002231 xmlFree(ctxt);
2232 return;
Owen Taylor3473f882001-02-23 17:55:21 +00002233 }
2234#endif /* LIBXML_XPATH_ENABLED */
2235 while (1) {
2236 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002237 snprintf(prompt, sizeof(prompt), "%s > ", "/");
Daniel Veillard7a985a12003-07-06 17:57:42 +00002238 else if ((ctxt->node != NULL) && (ctxt->node->name))
Daniel Veillard78d12092001-10-11 09:12:24 +00002239 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00002240 else
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002241 snprintf(prompt, sizeof(prompt), "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00002242 prompt[sizeof(prompt) - 1] = 0;
2243
Daniel Veillard78d12092001-10-11 09:12:24 +00002244 /*
2245 * Get a new command line
2246 */
Owen Taylor3473f882001-02-23 17:55:21 +00002247 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00002248 if (cmdline == NULL)
2249 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002250
Daniel Veillard78d12092001-10-11 09:12:24 +00002251 /*
2252 * Parse the command itself
2253 */
2254 cur = cmdline;
2255 nbargs = 0;
2256 while ((*cur == ' ') || (*cur == '\t'))
2257 cur++;
2258 i = 0;
2259 while ((*cur != ' ') && (*cur != '\t') &&
2260 (*cur != '\n') && (*cur != '\r')) {
2261 if (*cur == 0)
2262 break;
2263 command[i++] = *cur++;
2264 }
2265 command[i] = 0;
2266 if (i == 0)
2267 continue;
2268 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002269
Daniel Veillard78d12092001-10-11 09:12:24 +00002270 /*
2271 * Parse the argument
2272 */
2273 while ((*cur == ' ') || (*cur == '\t'))
2274 cur++;
2275 i = 0;
2276 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2277 if (*cur == 0)
2278 break;
2279 arg[i++] = *cur++;
2280 }
2281 arg[i] = 0;
2282 if (i != 0)
2283 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002284
Daniel Veillard78d12092001-10-11 09:12:24 +00002285 /*
2286 * start interpreting the command
2287 */
Owen Taylor3473f882001-02-23 17:55:21 +00002288 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002289 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002290 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002291 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002292 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002293 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002294 if (!strcmp(command, "help")) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002295 fprintf(ctxt->output, "\tbase display XML base of the node\n");
2296 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2297 fprintf(ctxt->output, "\tbye leave shell\n");
2298 fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2299 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2300 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2301 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2302 fprintf(ctxt->output, "\texit leave shell\n");
2303 fprintf(ctxt->output, "\thelp display this help\n");
2304 fprintf(ctxt->output, "\tfree display memory usage\n");
2305 fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2306 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002307#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002308 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
Daniel Veillardbbaa9972004-06-16 14:08:33 +00002309 fprintf(ctxt->output, "\tsetns nsreg register a namespace to a prefix in the XPath evaluation context\n");
2310 fprintf(ctxt->output, "\t format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002311#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard321be0c2002-10-08 21:26:42 +00002312 fprintf(ctxt->output, "\tpwd display current working directory\n");
2313 fprintf(ctxt->output, "\tquit leave shell\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002314#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002315 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00002316 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002317#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf54cd532004-02-25 11:52:31 +00002318#ifdef LIBXML_VALID_ENABLED
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002319 fprintf(ctxt->output, "\tvalidate check the document for errors\n");
Daniel Veillardf54cd532004-02-25 11:52:31 +00002320#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard522bc602004-02-21 11:53:09 +00002321#ifdef LIBXML_SCHEMAS_ENABLED
2322 fprintf(ctxt->output, "\trelaxng rng validate the document agaisnt the Relax-NG schemas\n");
2323#endif
Daniel Veillard1e208222002-10-22 14:25:25 +00002324 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
Daniel Veillardf54cd532004-02-25 11:52:31 +00002325#ifdef LIBXML_VALID_ENABLED
Daniel Veillard5004f422001-11-08 13:53:05 +00002326 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002327 xmlShellValidate(ctxt, arg, NULL, NULL);
Daniel Veillardf54cd532004-02-25 11:52:31 +00002328#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002329 } else if (!strcmp(command, "load")) {
2330 xmlShellLoad(ctxt, arg, NULL, NULL);
Daniel Veillard522bc602004-02-21 11:53:09 +00002331#ifdef LIBXML_SCHEMAS_ENABLED
2332 } else if (!strcmp(command, "relaxng")) {
2333 xmlShellRNGValidate(ctxt, arg, NULL, NULL);
2334#endif
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002335#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002336 } else if (!strcmp(command, "save")) {
2337 xmlShellSave(ctxt, arg, NULL, NULL);
2338 } else if (!strcmp(command, "write")) {
2339 xmlShellWrite(ctxt, arg, NULL, NULL);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002340#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard1e208222002-10-22 14:25:25 +00002341 } else if (!strcmp(command, "grep")) {
2342 xmlShellGrep(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002343 } else if (!strcmp(command, "free")) {
2344 if (arg[0] == 0) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002345 xmlMemShow(ctxt->output, 0);
Daniel Veillard78d12092001-10-11 09:12:24 +00002346 } else {
2347 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002348
Daniel Veillard78d12092001-10-11 09:12:24 +00002349 sscanf(arg, "%d", &len);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002350 xmlMemShow(ctxt->output, len);
Daniel Veillard78d12092001-10-11 09:12:24 +00002351 }
2352 } else if (!strcmp(command, "pwd")) {
2353 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002354
Daniel Veillard78d12092001-10-11 09:12:24 +00002355 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillard321be0c2002-10-08 21:26:42 +00002356 fprintf(ctxt->output, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002357 } else if (!strcmp(command, "du")) {
2358 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2359 } else if (!strcmp(command, "base")) {
2360 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002361#ifdef LIBXML_XPATH_ENABLED
Daniel Veillardbbaa9972004-06-16 14:08:33 +00002362 } else if (!strcmp(command, "setns")) {
2363 if (arg[0] == 0) {
2364 xmlGenericError(xmlGenericErrorContext,
2365 "setns: prefix=[nsuri] required\n");
2366 } else {
2367 xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
2368 }
Daniel Veillard2070c482002-01-22 22:12:19 +00002369 } else if (!strcmp(command, "xpath")) {
2370 if (arg[0] == 0) {
2371 xmlGenericError(xmlGenericErrorContext,
2372 "xpath: expression required\n");
2373 } else {
2374 ctxt->pctxt->node = ctxt->node;
2375 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002376 xmlXPathDebugDumpObject(ctxt->output, list, 0);
Daniel Veillard2070c482002-01-22 22:12:19 +00002377 xmlXPathFreeObject(list);
2378 }
2379#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard2156d432004-03-04 15:59:36 +00002380#ifdef LIBXML_TREE_ENABLED
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002381 } else if (!strcmp(command, "setbase")) {
2382 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard2156d432004-03-04 15:59:36 +00002383#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002384 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2385 int dir = (!strcmp(command, "dir"));
2386
2387 if (arg[0] == 0) {
2388 if (dir)
2389 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2390 else
2391 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2392 } else {
2393 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002394#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002395 ctxt->pctxt->node = ctxt->node;
2396 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2397#else
2398 list = NULL;
2399#endif /* LIBXML_XPATH_ENABLED */
2400 if (list != NULL) {
2401 switch (list->type) {
2402 case XPATH_UNDEFINED:
2403 xmlGenericError(xmlGenericErrorContext,
2404 "%s: no such node\n", arg);
2405 break;
2406 case XPATH_NODESET:{
2407 int indx;
2408
Daniel Veillarda6825e82001-11-07 13:33:59 +00002409 if (list->nodesetval == NULL)
2410 break;
2411
Daniel Veillard78d12092001-10-11 09:12:24 +00002412 for (indx = 0;
2413 indx < list->nodesetval->nodeNr;
2414 indx++) {
2415 if (dir)
2416 xmlShellDir(ctxt, NULL,
2417 list->nodesetval->
2418 nodeTab[indx], NULL);
2419 else
2420 xmlShellList(ctxt, NULL,
2421 list->nodesetval->
2422 nodeTab[indx], NULL);
2423 }
2424 break;
2425 }
2426 case XPATH_BOOLEAN:
2427 xmlGenericError(xmlGenericErrorContext,
2428 "%s is a Boolean\n", arg);
2429 break;
2430 case XPATH_NUMBER:
2431 xmlGenericError(xmlGenericErrorContext,
2432 "%s is a number\n", arg);
2433 break;
2434 case XPATH_STRING:
2435 xmlGenericError(xmlGenericErrorContext,
2436 "%s is a string\n", arg);
2437 break;
2438 case XPATH_POINT:
2439 xmlGenericError(xmlGenericErrorContext,
2440 "%s is a point\n", arg);
2441 break;
2442 case XPATH_RANGE:
2443 xmlGenericError(xmlGenericErrorContext,
2444 "%s is a range\n", arg);
2445 break;
2446 case XPATH_LOCATIONSET:
2447 xmlGenericError(xmlGenericErrorContext,
2448 "%s is a range\n", arg);
2449 break;
2450 case XPATH_USERS:
2451 xmlGenericError(xmlGenericErrorContext,
2452 "%s is user-defined\n", arg);
2453 break;
2454 case XPATH_XSLT_TREE:
2455 xmlGenericError(xmlGenericErrorContext,
2456 "%s is an XSLT value tree\n",
2457 arg);
2458 break;
2459 }
2460#ifdef LIBXML_XPATH_ENABLED
2461 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002462#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002463 } else {
2464 xmlGenericError(xmlGenericErrorContext,
2465 "%s: no such node\n", arg);
2466 }
2467 ctxt->pctxt->node = NULL;
2468 }
2469 } else if (!strcmp(command, "cd")) {
2470 if (arg[0] == 0) {
2471 ctxt->node = (xmlNodePtr) ctxt->doc;
2472 } else {
2473#ifdef LIBXML_XPATH_ENABLED
2474 ctxt->pctxt->node = ctxt->node;
2475 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2476#else
2477 list = NULL;
2478#endif /* LIBXML_XPATH_ENABLED */
2479 if (list != NULL) {
2480 switch (list->type) {
2481 case XPATH_UNDEFINED:
2482 xmlGenericError(xmlGenericErrorContext,
2483 "%s: no such node\n", arg);
2484 break;
2485 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002486 if (list->nodesetval != NULL) {
2487 if (list->nodesetval->nodeNr == 1) {
2488 ctxt->node = list->nodesetval->nodeTab[0];
Daniel Veillard7a985a12003-07-06 17:57:42 +00002489 if ((ctxt->node != NULL) &&
2490 (ctxt->node->type ==
2491 XML_NAMESPACE_DECL)) {
2492 xmlGenericError(xmlGenericErrorContext,
2493 "cannot cd to namespace\n");
2494 ctxt->node = NULL;
2495 }
Daniel Veillarda6825e82001-11-07 13:33:59 +00002496 } else
2497 xmlGenericError(xmlGenericErrorContext,
2498 "%s is a %d Node Set\n",
2499 arg,
2500 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002501 } else
2502 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002503 "%s is an empty Node Set\n",
2504 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002505 break;
2506 case XPATH_BOOLEAN:
2507 xmlGenericError(xmlGenericErrorContext,
2508 "%s is a Boolean\n", arg);
2509 break;
2510 case XPATH_NUMBER:
2511 xmlGenericError(xmlGenericErrorContext,
2512 "%s is a number\n", arg);
2513 break;
2514 case XPATH_STRING:
2515 xmlGenericError(xmlGenericErrorContext,
2516 "%s is a string\n", arg);
2517 break;
2518 case XPATH_POINT:
2519 xmlGenericError(xmlGenericErrorContext,
2520 "%s is a point\n", arg);
2521 break;
2522 case XPATH_RANGE:
2523 xmlGenericError(xmlGenericErrorContext,
2524 "%s is a range\n", arg);
2525 break;
2526 case XPATH_LOCATIONSET:
2527 xmlGenericError(xmlGenericErrorContext,
2528 "%s is a range\n", arg);
2529 break;
2530 case XPATH_USERS:
2531 xmlGenericError(xmlGenericErrorContext,
2532 "%s is user-defined\n", arg);
2533 break;
2534 case XPATH_XSLT_TREE:
2535 xmlGenericError(xmlGenericErrorContext,
2536 "%s is an XSLT value tree\n",
2537 arg);
2538 break;
2539 }
2540#ifdef LIBXML_XPATH_ENABLED
2541 xmlXPathFreeObject(list);
2542#endif
2543 } else {
2544 xmlGenericError(xmlGenericErrorContext,
2545 "%s: no such node\n", arg);
2546 }
2547 ctxt->pctxt->node = NULL;
2548 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002549#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002550 } else if (!strcmp(command, "cat")) {
2551 if (arg[0] == 0) {
2552 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2553 } else {
2554 ctxt->pctxt->node = ctxt->node;
2555#ifdef LIBXML_XPATH_ENABLED
2556 ctxt->pctxt->node = ctxt->node;
2557 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2558#else
2559 list = NULL;
2560#endif /* LIBXML_XPATH_ENABLED */
2561 if (list != NULL) {
2562 switch (list->type) {
2563 case XPATH_UNDEFINED:
2564 xmlGenericError(xmlGenericErrorContext,
2565 "%s: no such node\n", arg);
2566 break;
2567 case XPATH_NODESET:{
2568 int indx;
2569
Daniel Veillarda6825e82001-11-07 13:33:59 +00002570 if (list->nodesetval == NULL)
2571 break;
2572
Daniel Veillard78d12092001-10-11 09:12:24 +00002573 for (indx = 0;
2574 indx < list->nodesetval->nodeNr;
2575 indx++) {
2576 if (i > 0)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002577 fprintf(ctxt->output, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002578 xmlShellCat(ctxt, NULL,
2579 list->nodesetval->
2580 nodeTab[indx], NULL);
2581 }
2582 break;
2583 }
2584 case XPATH_BOOLEAN:
2585 xmlGenericError(xmlGenericErrorContext,
2586 "%s is a Boolean\n", arg);
2587 break;
2588 case XPATH_NUMBER:
2589 xmlGenericError(xmlGenericErrorContext,
2590 "%s is a number\n", arg);
2591 break;
2592 case XPATH_STRING:
2593 xmlGenericError(xmlGenericErrorContext,
2594 "%s is a string\n", arg);
2595 break;
2596 case XPATH_POINT:
2597 xmlGenericError(xmlGenericErrorContext,
2598 "%s is a point\n", arg);
2599 break;
2600 case XPATH_RANGE:
2601 xmlGenericError(xmlGenericErrorContext,
2602 "%s is a range\n", arg);
2603 break;
2604 case XPATH_LOCATIONSET:
2605 xmlGenericError(xmlGenericErrorContext,
2606 "%s is a range\n", arg);
2607 break;
2608 case XPATH_USERS:
2609 xmlGenericError(xmlGenericErrorContext,
2610 "%s is user-defined\n", arg);
2611 break;
2612 case XPATH_XSLT_TREE:
2613 xmlGenericError(xmlGenericErrorContext,
2614 "%s is an XSLT value tree\n",
2615 arg);
2616 break;
2617 }
2618#ifdef LIBXML_XPATH_ENABLED
2619 xmlXPathFreeObject(list);
2620#endif
2621 } else {
2622 xmlGenericError(xmlGenericErrorContext,
2623 "%s: no such node\n", arg);
2624 }
2625 ctxt->pctxt->node = NULL;
2626 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002627#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002628 } else {
2629 xmlGenericError(xmlGenericErrorContext,
2630 "Unknown command %s\n", command);
2631 }
2632 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002633 }
2634#ifdef LIBXML_XPATH_ENABLED
2635 xmlXPathFreeContext(ctxt->pctxt);
2636#endif /* LIBXML_XPATH_ENABLED */
2637 if (ctxt->loaded) {
2638 xmlFreeDoc(ctxt->doc);
2639 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002640 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002641 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002642 xmlFree(ctxt);
2643 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002644 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002645}
2646
2647#endif /* LIBXML_DEBUG_ENABLED */