blob: dbdd1f377b32a88b566fda34e3ea10e5690d4f83 [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * debugXML.c : This is a set of routines used for debugging the tree
3 * produced by the XML parser.
4 *
5 * See Copyright for the status of this software.
6 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00007 * Daniel Veillard <daniel@veillard.com>
Owen Taylor3473f882001-02-23 17:55:21 +00008 */
9
Bjorn Reese70a9da52001-04-21 16:57:29 +000010#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000011#ifdef LIBXML_DEBUG_ENABLED
12
Owen Taylor3473f882001-02-23 17:55:21 +000013#include <string.h>
14#ifdef HAVE_STDLIB_H
15#include <stdlib.h>
16#endif
17#ifdef HAVE_STRING_H
18#include <string.h>
19#endif
20#include <libxml/xmlmemory.h>
21#include <libxml/tree.h>
22#include <libxml/parser.h>
Daniel Veillard567e1b42001-08-01 15:53:47 +000023#include <libxml/parserInternals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000024#include <libxml/valid.h>
25#include <libxml/debugXML.h>
26#include <libxml/HTMLtree.h>
27#include <libxml/HTMLparser.h>
28#include <libxml/xmlerror.h>
29
Daniel Veillard5e2dace2001-07-18 19:30:27 +000030/**
31 * xmlDebugDumpString:
32 * @output: the FILE * for the output
33 * @str: the string
34 *
35 * Dumps informations about the string, shorten it if necessary
36 */
37void
38xmlDebugDumpString(FILE * output, const xmlChar * str)
39{
Owen Taylor3473f882001-02-23 17:55:21 +000040 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000041
Owen Taylor3473f882001-02-23 17:55:21 +000042 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000043 fprintf(output, "(NULL)");
44 return;
Owen Taylor3473f882001-02-23 17:55:21 +000045 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000046 for (i = 0; i < 40; i++)
47 if (str[i] == 0)
48 return;
49 else if (IS_BLANK(str[i]))
50 fputc(' ', output);
51 else if (str[i] >= 0x80)
52 fprintf(output, "#%X", str[i]);
53 else
54 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000055 fprintf(output, "...");
56}
57
Daniel Veillard56a4cb82001-03-24 17:00:36 +000058static void
59xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000060 int i;
61 char shift[100];
62
63 for (i = 0;((i < depth) && (i < 25));i++)
64 shift[2 * i] = shift[2 * i + 1] = ' ';
65 shift[2 * i] = shift[2 * i + 1] = 0;
66
67 fprintf(output, shift);
68
69 if (dtd->type != XML_DTD_NODE) {
70 fprintf(output, "PBM: not a DTD\n");
71 return;
72 }
73 if (dtd->name != NULL)
74 fprintf(output, "DTD(%s)", dtd->name);
75 else
76 fprintf(output, "DTD");
77 if (dtd->ExternalID != NULL)
78 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
79 if (dtd->SystemID != NULL)
80 fprintf(output, ", SYSTEM %s", dtd->SystemID);
81 fprintf(output, "\n");
82 /*
83 * Do a bit of checking
84 */
85 if (dtd->parent == NULL)
86 fprintf(output, "PBM: Dtd has no parent\n");
87 if (dtd->doc == NULL)
88 fprintf(output, "PBM: Dtd has no doc\n");
89 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
90 fprintf(output, "PBM: Dtd doc differs from parent's one\n");
91 if (dtd->prev == NULL) {
92 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
93 fprintf(output, "PBM: Dtd has no prev and not first of list\n");
94 } else {
95 if (dtd->prev->next != (xmlNodePtr) dtd)
96 fprintf(output, "PBM: Dtd prev->next : back link wrong\n");
97 }
98 if (dtd->next == NULL) {
99 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
100 fprintf(output, "PBM: Dtd has no next and not last of list\n");
101 } else {
102 if (dtd->next->prev != (xmlNodePtr) dtd)
103 fprintf(output, "PBM: Dtd next->prev : forward link wrong\n");
104 }
105}
106
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000107static void
108xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000109 int i;
110 char shift[100];
111
112 for (i = 0;((i < depth) && (i < 25));i++)
113 shift[2 * i] = shift[2 * i + 1] = ' ';
114 shift[2 * i] = shift[2 * i + 1] = 0;
115
116 fprintf(output, shift);
117
118 if (attr->type != XML_ATTRIBUTE_DECL) {
119 fprintf(output, "PBM: not a Attr\n");
120 return;
121 }
122 if (attr->name != NULL)
123 fprintf(output, "ATTRDECL(%s)", attr->name);
124 else
125 fprintf(output, "PBM ATTRDECL noname!!!");
126 if (attr->elem != NULL)
127 fprintf(output, " for %s", attr->elem);
128 else
129 fprintf(output, " PBM noelem!!!");
130 switch (attr->atype) {
131 case XML_ATTRIBUTE_CDATA:
132 fprintf(output, " CDATA");
133 break;
134 case XML_ATTRIBUTE_ID:
135 fprintf(output, " ID");
136 break;
137 case XML_ATTRIBUTE_IDREF:
138 fprintf(output, " IDREF");
139 break;
140 case XML_ATTRIBUTE_IDREFS:
141 fprintf(output, " IDREFS");
142 break;
143 case XML_ATTRIBUTE_ENTITY:
144 fprintf(output, " ENTITY");
145 break;
146 case XML_ATTRIBUTE_ENTITIES:
147 fprintf(output, " ENTITIES");
148 break;
149 case XML_ATTRIBUTE_NMTOKEN:
150 fprintf(output, " NMTOKEN");
151 break;
152 case XML_ATTRIBUTE_NMTOKENS:
153 fprintf(output, " NMTOKENS");
154 break;
155 case XML_ATTRIBUTE_ENUMERATION:
156 fprintf(output, " ENUMERATION");
157 break;
158 case XML_ATTRIBUTE_NOTATION:
159 fprintf(output, " NOTATION ");
160 break;
161 }
162 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000163 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000164 xmlEnumerationPtr cur = attr->tree;
165
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000166 for (indx = 0;indx < 5; indx++) {
167 if (indx != 0)
Owen Taylor3473f882001-02-23 17:55:21 +0000168 fprintf(output, "|%s", cur->name);
169 else
170 fprintf(output, " (%s", cur->name);
171 cur = cur->next;
172 if (cur == NULL) break;
173 }
174 if (cur == NULL)
175 fprintf(output, ")");
176 else
177 fprintf(output, "...)");
178 }
179 switch (attr->def) {
180 case XML_ATTRIBUTE_NONE:
181 break;
182 case XML_ATTRIBUTE_REQUIRED:
183 fprintf(output, " REQUIRED");
184 break;
185 case XML_ATTRIBUTE_IMPLIED:
186 fprintf(output, " IMPLIED");
187 break;
188 case XML_ATTRIBUTE_FIXED:
189 fprintf(output, " FIXED");
190 break;
191 }
192 if (attr->defaultValue != NULL) {
193 fprintf(output, "\"");
194 xmlDebugDumpString(output, attr->defaultValue);
195 fprintf(output, "\"");
196 }
197 printf("\n");
198
199 /*
200 * Do a bit of checking
201 */
202 if (attr->parent == NULL)
203 fprintf(output, "PBM: Attr has no parent\n");
204 if (attr->doc == NULL)
205 fprintf(output, "PBM: Attr has no doc\n");
206 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
207 fprintf(output, "PBM: Attr doc differs from parent's one\n");
208 if (attr->prev == NULL) {
209 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
210 fprintf(output, "PBM: Attr has no prev and not first of list\n");
211 } else {
212 if (attr->prev->next != (xmlNodePtr) attr)
213 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
214 }
215 if (attr->next == NULL) {
216 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
217 fprintf(output, "PBM: Attr has no next and not last of list\n");
218 } else {
219 if (attr->next->prev != (xmlNodePtr) attr)
220 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
221 }
222}
223
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000224static void
225xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000226 int i;
227 char shift[100];
228
229 for (i = 0;((i < depth) && (i < 25));i++)
230 shift[2 * i] = shift[2 * i + 1] = ' ';
231 shift[2 * i] = shift[2 * i + 1] = 0;
232
233 fprintf(output, shift);
234
235 if (elem->type != XML_ELEMENT_DECL) {
236 fprintf(output, "PBM: not a Elem\n");
237 return;
238 }
239 if (elem->name != NULL) {
240 fprintf(output, "ELEMDECL(");
241 xmlDebugDumpString(output, elem->name);
242 fprintf(output, ")");
243 } else
244 fprintf(output, "PBM ELEMDECL noname!!!");
245 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000246 case XML_ELEMENT_TYPE_UNDEFINED:
247 fprintf(output, ", UNDEFINED");
248 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000249 case XML_ELEMENT_TYPE_EMPTY:
250 fprintf(output, ", EMPTY");
251 break;
252 case XML_ELEMENT_TYPE_ANY:
253 fprintf(output, ", ANY");
254 break;
255 case XML_ELEMENT_TYPE_MIXED:
256 fprintf(output, ", MIXED ");
257 break;
258 case XML_ELEMENT_TYPE_ELEMENT:
259 fprintf(output, ", MIXED ");
260 break;
261 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000262 if ((elem->type != XML_ELEMENT_NODE) &&
263 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000264 char buf[5001];
265
266 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000267 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000268 buf[5000] = 0;
269 fprintf(output, "%s", buf);
270 }
271 printf("\n");
272
273 /*
274 * Do a bit of checking
275 */
276 if (elem->parent == NULL)
277 fprintf(output, "PBM: Elem has no parent\n");
278 if (elem->doc == NULL)
279 fprintf(output, "PBM: Elem has no doc\n");
280 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
281 fprintf(output, "PBM: Elem doc differs from parent's one\n");
282 if (elem->prev == NULL) {
283 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
284 fprintf(output, "PBM: Elem has no prev and not first of list\n");
285 } else {
286 if (elem->prev->next != (xmlNodePtr) elem)
287 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
288 }
289 if (elem->next == NULL) {
290 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
291 fprintf(output, "PBM: Elem has no next and not last of list\n");
292 } else {
293 if (elem->next->prev != (xmlNodePtr) elem)
294 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
295 }
296}
297
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000298static void
299xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000300 int i;
301 char shift[100];
302
303 for (i = 0;((i < depth) && (i < 25));i++)
304 shift[2 * i] = shift[2 * i + 1] = ' ';
305 shift[2 * i] = shift[2 * i + 1] = 0;
306
307 fprintf(output, shift);
308
309 if (ent->type != XML_ENTITY_DECL) {
310 fprintf(output, "PBM: not a Entity decl\n");
311 return;
312 }
313 if (ent->name != NULL) {
314 fprintf(output, "ENTITYDECL(");
315 xmlDebugDumpString(output, ent->name);
316 fprintf(output, ")");
317 } else
318 fprintf(output, "PBM ENTITYDECL noname!!!");
319 switch (ent->etype) {
320 case XML_INTERNAL_GENERAL_ENTITY:
321 fprintf(output, ", internal\n");
322 break;
323 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
324 fprintf(output, ", external parsed\n");
325 break;
326 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
327 fprintf(output, ", unparsed\n");
328 break;
329 case XML_INTERNAL_PARAMETER_ENTITY:
330 fprintf(output, ", parameter\n");
331 break;
332 case XML_EXTERNAL_PARAMETER_ENTITY:
333 fprintf(output, ", external parameter\n");
334 break;
335 case XML_INTERNAL_PREDEFINED_ENTITY:
336 fprintf(output, ", predefined\n");
337 break;
338 }
339 if (ent->ExternalID) {
340 fprintf(output, shift);
341 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
342 }
343 if (ent->SystemID) {
344 fprintf(output, shift);
345 fprintf(output, " SystemID=%s\n", ent->SystemID);
346 }
347 if (ent->URI != NULL) {
348 fprintf(output, shift);
349 fprintf(output, " URI=%s\n", ent->URI);
350 }
351 if (ent->content) {
352 fprintf(output, shift);
353 fprintf(output, " content=");
354 xmlDebugDumpString(output, ent->content);
355 fprintf(output, "\n");
356 }
357
358 /*
359 * Do a bit of checking
360 */
361 if (ent->parent == NULL)
362 fprintf(output, "PBM: Ent has no parent\n");
363 if (ent->doc == NULL)
364 fprintf(output, "PBM: Ent has no doc\n");
365 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
366 fprintf(output, "PBM: Ent doc differs from parent's one\n");
367 if (ent->prev == NULL) {
368 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
369 fprintf(output, "PBM: Ent has no prev and not first of list\n");
370 } else {
371 if (ent->prev->next != (xmlNodePtr) ent)
372 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
373 }
374 if (ent->next == NULL) {
375 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
376 fprintf(output, "PBM: Ent has no next and not last of list\n");
377 } else {
378 if (ent->next->prev != (xmlNodePtr) ent)
379 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
380 }
381}
382
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000383static void
384xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000385 int i;
386 char shift[100];
387
388 for (i = 0;((i < depth) && (i < 25));i++)
389 shift[2 * i] = shift[2 * i + 1] = ' ';
390 shift[2 * i] = shift[2 * i + 1] = 0;
391
392 fprintf(output, shift);
393 if (ns->type != XML_NAMESPACE_DECL) {
394 fprintf(output, "invalid namespace node %d\n", ns->type);
395 return;
396 }
397 if (ns->href == NULL) {
398 if (ns->prefix != NULL)
399 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
400 else
401 fprintf(output, "incomplete default namespace href=NULL\n");
402 } else {
403 if (ns->prefix != NULL)
404 fprintf(output, "namespace %s href=", ns->prefix);
405 else
406 fprintf(output, "default namespace href=");
407
408 xmlDebugDumpString(output, ns->href);
409 fprintf(output, "\n");
410 }
411}
412
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000413static void
414xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000415 while (ns != NULL) {
416 xmlDebugDumpNamespace(output, ns, depth);
417 ns = ns->next;
418 }
419}
420
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000421static void
422xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000423 int i;
424 char shift[100];
425
426 for (i = 0;((i < depth) && (i < 25));i++)
427 shift[2 * i] = shift[2 * i + 1] = ' ';
428 shift[2 * i] = shift[2 * i + 1] = 0;
429
430 fprintf(output, shift);
431 switch (ent->etype) {
432 case XML_INTERNAL_GENERAL_ENTITY:
433 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
434 break;
435 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
436 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
437 break;
438 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
439 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
440 break;
441 case XML_INTERNAL_PARAMETER_ENTITY:
442 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
443 break;
444 case XML_EXTERNAL_PARAMETER_ENTITY:
445 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
446 break;
447 default:
448 fprintf(output, "ENTITY_%d ! ", ent->etype);
449 }
450 fprintf(output, "%s\n", ent->name);
451 if (ent->ExternalID) {
452 fprintf(output, shift);
453 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
454 }
455 if (ent->SystemID) {
456 fprintf(output, shift);
457 fprintf(output, "SystemID=%s\n", ent->SystemID);
458 }
459 if (ent->URI) {
460 fprintf(output, shift);
461 fprintf(output, "URI=%s\n", ent->URI);
462 }
463 if (ent->content) {
464 fprintf(output, shift);
465 fprintf(output, "content=");
466 xmlDebugDumpString(output, ent->content);
467 fprintf(output, "\n");
468 }
469}
470
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000471/**
472 * xmlDebugDumpAttr:
473 * @output: the FILE * for the output
474 * @attr: the attribute
475 * @depth: the indentation level.
476 *
477 * Dumps debug information for the attribute
478 */
479void
480xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000481 int i;
482 char shift[100];
483
484 for (i = 0;((i < depth) && (i < 25));i++)
485 shift[2 * i] = shift[2 * i + 1] = ' ';
486 shift[2 * i] = shift[2 * i + 1] = 0;
487
488 fprintf(output, shift);
489
490 fprintf(output, "ATTRIBUTE ");
491 xmlDebugDumpString(output, attr->name);
492 fprintf(output, "\n");
493 if (attr->children != NULL)
494 xmlDebugDumpNodeList(output, attr->children, depth + 1);
495
496 /*
497 * Do a bit of checking
498 */
499 if (attr->parent == NULL)
500 fprintf(output, "PBM: Attr has no parent\n");
501 if (attr->doc == NULL)
502 fprintf(output, "PBM: Attr has no doc\n");
503 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
504 fprintf(output, "PBM: Attr doc differs from parent's one\n");
505 if (attr->prev == NULL) {
506 if ((attr->parent != NULL) && (attr->parent->properties != attr))
507 fprintf(output, "PBM: Attr has no prev and not first of list\n");
508 } else {
509 if (attr->prev->next != attr)
510 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
511 }
512 if (attr->next != NULL) {
513 if (attr->next->prev != attr)
514 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
515 }
516}
517
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000518/**
519 * xmlDebugDumpAttrList:
520 * @output: the FILE * for the output
521 * @attr: the attribute list
522 * @depth: the indentation level.
523 *
524 * Dumps debug information for the attribute list
525 */
526void
527xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
528{
Owen Taylor3473f882001-02-23 17:55:21 +0000529 while (attr != NULL) {
530 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000531 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000532 }
533}
534
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000535/**
536 * xmlDebugDumpOneNode:
537 * @output: the FILE * for the output
538 * @node: the node
539 * @depth: the indentation level.
540 *
541 * Dumps debug information for the element node, it is not recursive
542 */
543void
544xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
545{
Owen Taylor3473f882001-02-23 17:55:21 +0000546 int i;
547 char shift[100];
548
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000549 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000550 shift[2 * i] = shift[2 * i + 1] = ' ';
551 shift[2 * i] = shift[2 * i + 1] = 0;
552
553 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000554 case XML_ELEMENT_NODE:
555 fprintf(output, shift);
556 fprintf(output, "ELEMENT ");
557 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
558 xmlDebugDumpString(output, node->ns->prefix);
559 fprintf(output, ":");
560 }
561 xmlDebugDumpString(output, node->name);
562 fprintf(output, "\n");
563 break;
564 case XML_ATTRIBUTE_NODE:
565 fprintf(output, shift);
566 fprintf(output, "Error, ATTRIBUTE found here\n");
567 break;
568 case XML_TEXT_NODE:
569 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000570 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000571 fprintf(output, "TEXT no enc\n");
572 else
573 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000574 break;
575 case XML_CDATA_SECTION_NODE:
576 fprintf(output, shift);
577 fprintf(output, "CDATA_SECTION\n");
578 break;
579 case XML_ENTITY_REF_NODE:
580 fprintf(output, shift);
581 fprintf(output, "ENTITY_REF(%s)\n", node->name);
582 break;
583 case XML_ENTITY_NODE:
584 fprintf(output, shift);
585 fprintf(output, "ENTITY\n");
586 break;
587 case XML_PI_NODE:
588 fprintf(output, shift);
589 fprintf(output, "PI %s\n", node->name);
590 break;
591 case XML_COMMENT_NODE:
592 fprintf(output, shift);
593 fprintf(output, "COMMENT\n");
594 break;
595 case XML_DOCUMENT_NODE:
596 case XML_HTML_DOCUMENT_NODE:
597 fprintf(output, shift);
598 fprintf(output, "Error, DOCUMENT found here\n");
599 break;
600 case XML_DOCUMENT_TYPE_NODE:
601 fprintf(output, shift);
602 fprintf(output, "DOCUMENT_TYPE\n");
603 break;
604 case XML_DOCUMENT_FRAG_NODE:
605 fprintf(output, shift);
606 fprintf(output, "DOCUMENT_FRAG\n");
607 break;
608 case XML_NOTATION_NODE:
609 fprintf(output, shift);
610 fprintf(output, "NOTATION\n");
611 break;
612 case XML_DTD_NODE:
613 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
614 return;
615 case XML_ELEMENT_DECL:
616 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
617 return;
618 case XML_ATTRIBUTE_DECL:
619 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
620 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000621 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000622 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
623 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000624 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000625 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
626 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000627 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000628 fprintf(output, shift);
629 fprintf(output, "INCLUDE START\n");
630 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000631 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000632 fprintf(output, shift);
633 fprintf(output, "INCLUDE END\n");
634 return;
635 default:
636 fprintf(output, shift);
637 fprintf(output, "NODE_%d !!!\n", node->type);
638 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000639 }
640 if (node->doc == NULL) {
641 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000642 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000643 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000644 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000645 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
646 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000647 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000648 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000649 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
650 shift[2 * i] = shift[2 * i + 1] = ' ';
651 shift[2 * i + 2] = shift[2 * i + 3] = 0;
652 fprintf(output, shift);
653 fprintf(output, "content=");
654#ifndef XML_USE_BUFFER_CONTENT
655 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +0000656#else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000657 xmlDebugDumpString(output, xmlBufferContent(node->content));
Owen Taylor3473f882001-02-23 17:55:21 +0000658#endif
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000659 fprintf(output, "\n");
660 }
Owen Taylor3473f882001-02-23 17:55:21 +0000661 } else {
662 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000663
664 ent = xmlGetDocEntity(node->doc, node->name);
665 if (ent != NULL)
666 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000667 }
668 /*
669 * Do a bit of checking
670 */
671 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000672 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000673 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000674 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000675 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000676 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000677 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000678 if ((node->parent != NULL) && (node->parent->children != node))
679 fprintf(output,
680 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000681 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000682 if (node->prev->next != node)
683 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000684 }
685 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000686 if ((node->parent != NULL) && (node->parent->last != node))
687 fprintf(output,
688 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000689 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000690 if (node->next->prev != node)
691 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000692 }
693}
694
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000695/**
696 * xmlDebugDumpNode:
697 * @output: the FILE * for the output
698 * @node: the node
699 * @depth: the indentation level.
700 *
701 * Dumps debug information for the element node, it is recursive
702 */
703void
704xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
705{
Owen Taylor3473f882001-02-23 17:55:21 +0000706 xmlDebugDumpOneNode(output, node, depth);
707 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000708 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000709}
710
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000711/**
712 * xmlDebugDumpNodeList:
713 * @output: the FILE * for the output
714 * @node: the node list
715 * @depth: the indentation level.
716 *
717 * Dumps debug information for the list of element node, it is recursive
718 */
719void
720xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
721{
Owen Taylor3473f882001-02-23 17:55:21 +0000722 while (node != NULL) {
723 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000724 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000725 }
726}
727
728
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000729/**
730 * xmlDebugDumpDocumentHead:
731 * @output: the FILE * for the output
732 * @doc: the document
733 *
734 * Dumps debug information cncerning the document, not recursive
735 */
736void
737xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
738{
739 if (output == NULL)
740 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000741 if (doc == NULL) {
742 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000743 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000744 }
745
746 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000747 case XML_ELEMENT_NODE:
748 fprintf(output, "Error, ELEMENT found here ");
749 break;
750 case XML_ATTRIBUTE_NODE:
751 fprintf(output, "Error, ATTRIBUTE found here\n");
752 break;
753 case XML_TEXT_NODE:
754 fprintf(output, "Error, TEXT\n");
755 break;
756 case XML_CDATA_SECTION_NODE:
757 fprintf(output, "Error, CDATA_SECTION\n");
758 break;
759 case XML_ENTITY_REF_NODE:
760 fprintf(output, "Error, ENTITY_REF\n");
761 break;
762 case XML_ENTITY_NODE:
763 fprintf(output, "Error, ENTITY\n");
764 break;
765 case XML_PI_NODE:
766 fprintf(output, "Error, PI\n");
767 break;
768 case XML_COMMENT_NODE:
769 fprintf(output, "Error, COMMENT\n");
770 break;
771 case XML_DOCUMENT_NODE:
772 fprintf(output, "DOCUMENT\n");
773 break;
774 case XML_HTML_DOCUMENT_NODE:
775 fprintf(output, "HTML DOCUMENT\n");
776 break;
777 case XML_DOCUMENT_TYPE_NODE:
778 fprintf(output, "Error, DOCUMENT_TYPE\n");
779 break;
780 case XML_DOCUMENT_FRAG_NODE:
781 fprintf(output, "Error, DOCUMENT_FRAG\n");
782 break;
783 case XML_NOTATION_NODE:
784 fprintf(output, "Error, NOTATION\n");
785 break;
786 default:
787 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000788 }
789 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000790 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000791 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000792 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000793 }
794 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000795 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000796 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000797 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000798 }
799 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000800 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000801 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000802 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000803 }
804 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000805 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000806 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000807 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000808 }
809 if (doc->standalone)
810 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000811 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000812 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
813}
814
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000815/**
816 * xmlDebugDumpDocument:
817 * @output: the FILE * for the output
818 * @doc: the document
819 *
820 * Dumps debug information for the document, it's recursive
821 */
822void
823xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
824{
825 if (output == NULL)
826 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000827 if (doc == NULL) {
828 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000829 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000830 }
831 xmlDebugDumpDocumentHead(output, doc);
832 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000833 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000834 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000835}
Owen Taylor3473f882001-02-23 17:55:21 +0000836
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000837/**
838 * xmlDebugDumpDTD:
839 * @output: the FILE * for the output
840 * @dtd: the DTD
841 *
842 * Dumps debug information for the DTD
843 */
844void
845xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
846{
Owen Taylor3473f882001-02-23 17:55:21 +0000847 if (dtd == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000848 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000849 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000850 fprintf(output, "PBM: not a DTD\n");
851 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000852 }
853 if (dtd->name != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000854 fprintf(output, "DTD(%s)", dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000855 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000856 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000857 if (dtd->ExternalID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000858 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000859 if (dtd->SystemID != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000860 fprintf(output, ", SYSTEM %s", dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000861 fprintf(output, "\n");
862 /*
863 * Do a bit of checking
864 */
865 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000866 fprintf(output, "PBM: Dtd doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000867 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000868 if ((dtd->parent != NULL)
869 && (dtd->parent->children != (xmlNodePtr) dtd))
870 fprintf(output,
871 "PBM: Dtd has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000872 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000873 if (dtd->prev->next != (xmlNodePtr) dtd)
874 fprintf(output, "PBM: Dtd prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000875 }
876 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000877 if ((dtd->parent != NULL)
878 && (dtd->parent->last != (xmlNodePtr) dtd))
879 fprintf(output, "PBM: Dtd has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000880 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000881 if (dtd->next->prev != (xmlNodePtr) dtd)
882 fprintf(output, "PBM: Dtd next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000883 }
884 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000885 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000886 else
887 xmlDebugDumpNodeList(output, dtd->children, 1);
888}
889
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000890static void
891xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Owen Taylor3473f882001-02-23 17:55:21 +0000892 fprintf(output, "%s : ", cur->name);
893 switch (cur->etype) {
894 case XML_INTERNAL_GENERAL_ENTITY:
895 fprintf(output, "INTERNAL GENERAL, ");
896 break;
897 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
898 fprintf(output, "EXTERNAL PARSED, ");
899 break;
900 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
901 fprintf(output, "EXTERNAL UNPARSED, ");
902 break;
903 case XML_INTERNAL_PARAMETER_ENTITY:
904 fprintf(output, "INTERNAL PARAMETER, ");
905 break;
906 case XML_EXTERNAL_PARAMETER_ENTITY:
907 fprintf(output, "EXTERNAL PARAMETER, ");
908 break;
909 default:
910 fprintf(output, "UNKNOWN TYPE %d",
911 cur->etype);
912 }
913 if (cur->ExternalID != NULL)
914 fprintf(output, "ID \"%s\"", cur->ExternalID);
915 if (cur->SystemID != NULL)
916 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
917 if (cur->orig != NULL)
918 fprintf(output, "\n orig \"%s\"", cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000919 if ((cur->type != XML_ELEMENT_NODE) &&
920 (cur->content != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000921 fprintf(output, "\n content \"%s\"", cur->content);
922 fprintf(output, "\n");
923}
924
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000925/**
926 * xmlDebugDumpEntities:
927 * @output: the FILE * for the output
928 * @doc: the document
929 *
930 * Dumps debug information for all the entities in use by the document
931 */
932void
933xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
934{
935 if (output == NULL)
936 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000937 if (doc == NULL) {
938 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000939 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000940 }
941
942 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000943 case XML_ELEMENT_NODE:
944 fprintf(output, "Error, ELEMENT found here ");
945 break;
946 case XML_ATTRIBUTE_NODE:
947 fprintf(output, "Error, ATTRIBUTE found here\n");
948 break;
949 case XML_TEXT_NODE:
950 fprintf(output, "Error, TEXT\n");
951 break;
952 case XML_CDATA_SECTION_NODE:
953 fprintf(output, "Error, CDATA_SECTION\n");
954 break;
955 case XML_ENTITY_REF_NODE:
956 fprintf(output, "Error, ENTITY_REF\n");
957 break;
958 case XML_ENTITY_NODE:
959 fprintf(output, "Error, ENTITY\n");
960 break;
961 case XML_PI_NODE:
962 fprintf(output, "Error, PI\n");
963 break;
964 case XML_COMMENT_NODE:
965 fprintf(output, "Error, COMMENT\n");
966 break;
967 case XML_DOCUMENT_NODE:
968 fprintf(output, "DOCUMENT\n");
969 break;
970 case XML_HTML_DOCUMENT_NODE:
971 fprintf(output, "HTML DOCUMENT\n");
972 break;
973 case XML_DOCUMENT_TYPE_NODE:
974 fprintf(output, "Error, DOCUMENT_TYPE\n");
975 break;
976 case XML_DOCUMENT_FRAG_NODE:
977 fprintf(output, "Error, DOCUMENT_FRAG\n");
978 break;
979 case XML_NOTATION_NODE:
980 fprintf(output, "Error, NOTATION\n");
981 break;
982 default:
983 fprintf(output, "NODE_%d\n", doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000984 }
985 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000986 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
987 doc->intSubset->entities;
988
989 fprintf(output, "Entities in internal subset\n");
990 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
991 output);
Owen Taylor3473f882001-02-23 17:55:21 +0000992 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000993 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000994 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000995 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
996 doc->extSubset->entities;
997
998 fprintf(output, "Entities in external subset\n");
999 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1000 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001001 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001002 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001003}
1004
Daniel Veillard78d12092001-10-11 09:12:24 +00001005int xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001006 int ret = 0;
1007 xmlNodePtr list = NULL;
1008
1009 switch (node->type) {
1010 case XML_ELEMENT_NODE:
1011 list = node->children;
1012 break;
1013 case XML_DOCUMENT_NODE:
1014 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001015#ifdef LIBXML_DOCB_ENABLED
1016 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001017#endif
1018 list = ((xmlDocPtr) node)->children;
1019 break;
1020 case XML_ATTRIBUTE_NODE:
1021 list = ((xmlAttrPtr) node)->children;
1022 break;
1023 case XML_TEXT_NODE:
1024 case XML_CDATA_SECTION_NODE:
1025 case XML_PI_NODE:
1026 case XML_COMMENT_NODE:
1027 if (node->content != NULL) {
1028#ifndef XML_USE_BUFFER_CONTENT
1029 ret = xmlStrlen(node->content);
1030#else
1031 ret = xmlBufferLength(node->content);
1032#endif
1033 }
1034 break;
1035 case XML_ENTITY_REF_NODE:
1036 case XML_DOCUMENT_TYPE_NODE:
1037 case XML_ENTITY_NODE:
1038 case XML_DOCUMENT_FRAG_NODE:
1039 case XML_NOTATION_NODE:
1040 case XML_DTD_NODE:
1041 case XML_ELEMENT_DECL:
1042 case XML_ATTRIBUTE_DECL:
1043 case XML_ENTITY_DECL:
1044 case XML_NAMESPACE_DECL:
1045 case XML_XINCLUDE_START:
1046 case XML_XINCLUDE_END:
1047 ret = 1;
1048 break;
1049 }
1050 for (;list != NULL;ret++)
1051 list = list->next;
1052 return(ret);
1053}
1054
Daniel Veillard78d12092001-10-11 09:12:24 +00001055void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001056xmlLsOneNode(FILE *output, xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001057 switch (node->type) {
1058 case XML_ELEMENT_NODE:
1059 fprintf(output, "-");
1060 break;
1061 case XML_ATTRIBUTE_NODE:
1062 fprintf(output, "a");
1063 break;
1064 case XML_TEXT_NODE:
1065 fprintf(output, "t");
1066 break;
1067 case XML_CDATA_SECTION_NODE:
1068 fprintf(output, "c");
1069 break;
1070 case XML_ENTITY_REF_NODE:
1071 fprintf(output, "e");
1072 break;
1073 case XML_ENTITY_NODE:
1074 fprintf(output, "E");
1075 break;
1076 case XML_PI_NODE:
1077 fprintf(output, "p");
1078 break;
1079 case XML_COMMENT_NODE:
1080 fprintf(output, "c");
1081 break;
1082 case XML_DOCUMENT_NODE:
1083 fprintf(output, "d");
1084 break;
1085 case XML_HTML_DOCUMENT_NODE:
1086 fprintf(output, "h");
1087 break;
1088 case XML_DOCUMENT_TYPE_NODE:
1089 fprintf(output, "T");
1090 break;
1091 case XML_DOCUMENT_FRAG_NODE:
1092 fprintf(output, "F");
1093 break;
1094 case XML_NOTATION_NODE:
1095 fprintf(output, "N");
1096 break;
1097 default:
1098 fprintf(output, "?");
1099 }
1100 if (node->properties != NULL)
1101 fprintf(output, "a");
1102 else
1103 fprintf(output, "-");
1104 if (node->nsDef != NULL)
1105 fprintf(output, "n");
1106 else
1107 fprintf(output, "-");
1108
1109 fprintf(output, " %8d ", xmlLsCountNode(node));
1110
1111 switch (node->type) {
1112 case XML_ELEMENT_NODE:
1113 if (node->name != NULL)
1114 fprintf(output, "%s", node->name);
1115 break;
1116 case XML_ATTRIBUTE_NODE:
1117 if (node->name != NULL)
1118 fprintf(output, "%s", node->name);
1119 break;
1120 case XML_TEXT_NODE:
1121 if (node->content != NULL) {
1122#ifndef XML_USE_BUFFER_CONTENT
1123 xmlDebugDumpString(output, node->content);
1124#else
1125 xmlDebugDumpString(output, xmlBufferContent(node->content));
1126#endif
1127 }
1128 break;
1129 case XML_CDATA_SECTION_NODE:
1130 break;
1131 case XML_ENTITY_REF_NODE:
1132 if (node->name != NULL)
1133 fprintf(output, "%s", node->name);
1134 break;
1135 case XML_ENTITY_NODE:
1136 if (node->name != NULL)
1137 fprintf(output, "%s", node->name);
1138 break;
1139 case XML_PI_NODE:
1140 if (node->name != NULL)
1141 fprintf(output, "%s", node->name);
1142 break;
1143 case XML_COMMENT_NODE:
1144 break;
1145 case XML_DOCUMENT_NODE:
1146 break;
1147 case XML_HTML_DOCUMENT_NODE:
1148 break;
1149 case XML_DOCUMENT_TYPE_NODE:
1150 break;
1151 case XML_DOCUMENT_FRAG_NODE:
1152 break;
1153 case XML_NOTATION_NODE:
1154 break;
1155 default:
1156 if (node->name != NULL)
1157 fprintf(output, "%s", node->name);
1158 }
1159 fprintf(output, "\n");
1160}
1161
Daniel Veillard78d12092001-10-11 09:12:24 +00001162/**
1163 * xmlBoolToText:
1164 * @bool : a bool to turn into text
1165 *
1166 * Convenient way to turn bool into text
1167*/
1168const char *
1169xmlBoolToText(int bool)
1170{
1171 if (bool)
1172 return("True");
1173 else
1174 return("False");
1175}
1176
1177
1178/**
1179 * xmlGetLineNo:
1180 * @node : valid node
1181 *
1182 * Get line number of node
1183 *
1184 * Returns the line number if sucessfull, -1 otherwise
1185 */
1186long
1187xmlGetLineNo(xmlNodePtr node)
1188{
1189 long result = -1;
1190
1191 if (!node)
1192 return result;
1193 if (node->type == XML_ELEMENT_NODE)
1194 result = (long) node->content;
1195 else if ((node->prev != NULL) &&
1196 (node->prev->type == XML_ELEMENT_NODE))
1197 result = (long) node->prev->content;
1198 else if ((node->parent != NULL) &&
1199 (node->parent->type == XML_ELEMENT_NODE))
1200 result = (long) node->parent->content;
1201
1202 return result;
1203}
1204
Owen Taylor3473f882001-02-23 17:55:21 +00001205/****************************************************************
1206 * *
1207 * The XML shell related functions *
1208 * *
1209 ****************************************************************/
1210
Daniel Veillard78d12092001-10-11 09:12:24 +00001211
1212
Owen Taylor3473f882001-02-23 17:55:21 +00001213/*
1214 * TODO: Improvement/cleanups for the XML shell
1215 * - allow to shell out an editor on a subpart
1216 * - cleanup function registrations (with help) and calling
1217 * - provide registration routines
1218 */
1219
1220/**
Daniel Veillard78d12092001-10-11 09:12:24 +00001221 * xmlShellPrintXpathError:
1222 * @errorType: valid xpath error id
1223 * @arg : the argument that cause xpath to fail
1224 *
1225 * Print the xpath error to libxml default error channel
1226 */
1227void
1228xmlShellPrintXPathError(int errorType, const char *arg)
1229{
1230 const char *default_arg = "Result";
1231
1232 if (!arg)
1233 arg = default_arg;
1234
1235 switch (errorType) {
1236 case XPATH_UNDEFINED:
1237 xmlGenericError(xmlGenericErrorContext,
1238 "%s: no such node\n", arg);
1239 break;
1240
1241 case XPATH_BOOLEAN:
1242 xmlGenericError(xmlGenericErrorContext,
1243 "%s is a Boolean\n", arg);
1244 break;
1245 case XPATH_NUMBER:
1246 xmlGenericError(xmlGenericErrorContext,
1247 "%s is a number\n", arg);
1248 break;
1249 case XPATH_STRING:
1250 xmlGenericError(xmlGenericErrorContext,
1251 "%s is a string\n", arg);
1252 break;
1253 case XPATH_POINT:
1254 xmlGenericError(xmlGenericErrorContext,
1255 "%s is a point\n", arg);
1256 break;
1257 case XPATH_RANGE:
1258 xmlGenericError(xmlGenericErrorContext,
1259 "%s is a range\n", arg);
1260 break;
1261 case XPATH_LOCATIONSET:
1262 xmlGenericError(xmlGenericErrorContext,
1263 "%s is a range\n", arg);
1264 break;
1265 case XPATH_USERS:
1266 xmlGenericError(xmlGenericErrorContext,
1267 "%s is user-defined\n", arg);
1268 break;
1269 case XPATH_XSLT_TREE:
1270 xmlGenericError(xmlGenericErrorContext,
1271 "%s is an XSLT value tree\n", arg);
1272 break;
1273 }
1274 xmlGenericError(xmlGenericErrorContext,
1275 "Try casting the result string function (xpath builtin)\n",
1276 arg);
1277}
1278
1279
1280/**
1281 * xmlShellPrintNode:
1282 * @node : a non-null node to print to stdout
1283 *
1284 * Print node to stdout
1285 */
1286void
1287xmlShellPrintNode(xmlNodePtr node)
1288{
1289 if (!node)
1290 return;
1291
1292 if (node->type == XML_DOCUMENT_NODE)
1293 xmlDocDump(stdout, (xmlDocPtr) node);
1294 else if (node->type == XML_ATTRIBUTE_NODE)
1295 xmlDebugDumpAttrList(stdout, (xmlAttrPtr) node, 0);
1296 else
1297 xmlElemDump(stdout, node->doc, node);
1298
1299 fprintf(stdout, "\n");
1300}
1301
1302
1303/**
1304 * xmlShellPrintXPathResult:
1305 * list : a valid result generated by an xpath evaluation
1306 *
1307 * Prints result to stdout
1308 */
1309void
1310xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1311{
1312 int i = 0;
1313
1314 if (list != NULL) {
1315 switch (list->type) {
1316 case XPATH_NODESET:{
1317 int indx;
1318
1319 if (list->nodesetval) {
1320 for (indx = 0; indx < list->nodesetval->nodeNr;
1321 indx++) {
1322 if (i > 0)
1323 fprintf(stderr, " -------\n");
1324 xmlShellPrintNode(list->nodesetval->
1325 nodeTab[indx]);
1326 }
1327 } else {
1328 xmlGenericError(xmlGenericErrorContext,
1329 "Empty node set\n");
1330 }
1331 break;
1332 }
1333 case XPATH_BOOLEAN:
1334 xmlGenericError(xmlGenericErrorContext,
1335 "Is a Boolean:%s\n",
1336 xmlBoolToText(list->boolval));
1337 break;
1338 case XPATH_NUMBER:
1339 xmlGenericError(xmlGenericErrorContext,
1340 "Is a number:%0g\n", list->floatval);
1341 break;
1342 case XPATH_STRING:
1343 xmlGenericError(xmlGenericErrorContext,
1344 "Is a string:%s\n", list->stringval);
1345 break;
1346
1347 default:
1348 xmlShellPrintXPathError(list->type, NULL);
1349 }
1350 }
1351}
1352
1353/**
Owen Taylor3473f882001-02-23 17:55:21 +00001354 * xmlShellList:
1355 * @ctxt: the shell context
1356 * @arg: unused
1357 * @node: a node
1358 * @node2: unused
1359 *
1360 * Implements the XML shell function "ls"
1361 * Does an Unix like listing of the given node (like a directory)
1362 *
1363 * Returns 0
1364 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001365int
1366xmlShellList(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1367 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1368 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1369{
Owen Taylor3473f882001-02-23 17:55:21 +00001370 xmlNodePtr cur;
1371
1372 if ((node->type == XML_DOCUMENT_NODE) ||
1373 (node->type == XML_HTML_DOCUMENT_NODE)) {
1374 cur = ((xmlDocPtr) node)->children;
1375 } else if (node->children != NULL) {
1376 cur = node->children;
1377 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001378 xmlLsOneNode(stdout, node);
1379 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001380 }
1381 while (cur != NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001382 xmlLsOneNode(stdout, cur);
1383 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001384 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001385 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001386}
1387
1388/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001389 * xmlShellBase:
1390 * @ctxt: the shell context
1391 * @arg: unused
1392 * @node: a node
1393 * @node2: unused
1394 *
1395 * Implements the XML shell function "base"
1396 * dumps the current XML base of the node
1397 *
1398 * Returns 0
1399 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001400int
1401xmlShellBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1402 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1403 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1404{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001405 xmlChar *base;
1406
1407 base = xmlNodeGetBase(node->doc, node);
1408
1409 if (base == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001410 printf(" No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001411 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001412 printf("%s\n", base);
1413 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001414 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001415 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001416}
1417
1418/**
Owen Taylor3473f882001-02-23 17:55:21 +00001419 * xmlShellDir:
1420 * @ctxt: the shell context
1421 * @arg: unused
1422 * @node: a node
1423 * @node2: unused
1424 *
1425 * Implements the XML shell function "dir"
1426 * dumps informations about the node (namespace, attributes, content).
1427 *
1428 * Returns 0
1429 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001430int
1431xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1432 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1433 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1434{
Owen Taylor3473f882001-02-23 17:55:21 +00001435 if ((node->type == XML_DOCUMENT_NODE) ||
1436 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001437 xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001438 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001439 xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001440 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001441 xmlDebugDumpOneNode(stdout, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001442 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001443 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001444}
1445
1446/**
1447 * xmlShellCat:
1448 * @ctxt: the shell context
1449 * @arg: unused
1450 * @node: a node
1451 * @node2: unused
1452 *
1453 * Implements the XML shell function "cat"
1454 * dumps the serialization node content (XML or HTML).
1455 *
1456 * Returns 0
1457 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001458int
1459xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1460 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1461{
Owen Taylor3473f882001-02-23 17:55:21 +00001462 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1463#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001464 if (node->type == XML_HTML_DOCUMENT_NODE)
1465 htmlDocDump(stdout, (htmlDocPtr) node);
1466 else
1467 htmlNodeDumpFile(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001468#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001469 if (node->type == XML_DOCUMENT_NODE)
1470 xmlDocDump(stdout, (xmlDocPtr) node);
1471 else
1472 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001473#endif /* LIBXML_HTML_ENABLED */
1474 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001475 if (node->type == XML_DOCUMENT_NODE)
1476 xmlDocDump(stdout, (xmlDocPtr) node);
1477 else
1478 xmlElemDump(stdout, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001479 }
1480 printf("\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001481 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001482}
1483
1484/**
1485 * xmlShellLoad:
1486 * @ctxt: the shell context
1487 * @filename: the file name
1488 * @node: unused
1489 * @node2: unused
1490 *
1491 * Implements the XML shell function "load"
1492 * loads a new document specified by the filename
1493 *
1494 * Returns 0 or -1 if loading failed
1495 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001496int
1497xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1498 xmlNodePtr node ATTRIBUTE_UNUSED,
1499 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1500{
Owen Taylor3473f882001-02-23 17:55:21 +00001501 xmlDocPtr doc;
1502 int html = 0;
1503
1504 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001505 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001506
1507 if (html) {
1508#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001509 doc = htmlParseFile(filename, NULL);
1510#else
1511 printf("HTML support not compiled in\n");
1512 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001513#endif /* LIBXML_HTML_ENABLED */
1514 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001515 doc = xmlParseFile(filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001516 }
1517 if (doc != NULL) {
1518 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001519 xmlFreeDoc(ctxt->doc);
1520 }
1521 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001522#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001523 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001524#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001525 xmlFree(ctxt->filename);
1526 ctxt->doc = doc;
1527 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001528#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001529 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001530#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001531 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001532 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001533 return (-1);
1534 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001535}
1536
1537/**
1538 * xmlShellWrite:
1539 * @ctxt: the shell context
1540 * @filename: the file name
1541 * @node: a node in the tree
1542 * @node2: unused
1543 *
1544 * Implements the XML shell function "write"
1545 * Write the current node to the filename, it saves the serailization
1546 * of the subtree under the @node specified
1547 *
1548 * Returns 0 or -1 in case of error
1549 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001550int
Owen Taylor3473f882001-02-23 17:55:21 +00001551xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001552 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1553{
Owen Taylor3473f882001-02-23 17:55:21 +00001554 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001555 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001556 if ((filename == NULL) || (filename[0] == 0)) {
1557 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001558 "Write command requires a filename argument\n");
1559 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001560 }
1561#ifdef W_OK
1562 if (access((char *) filename, W_OK)) {
1563 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001564 "Cannot write to %s\n", filename);
1565 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001566 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001567#endif
1568 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001569 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001570 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1571 xmlGenericError(xmlGenericErrorContext,
1572 "Failed to write to %s\n", filename);
1573 return (-1);
1574 }
1575 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001576 case XML_HTML_DOCUMENT_NODE:
1577#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001578 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1579 xmlGenericError(xmlGenericErrorContext,
1580 "Failed to write to %s\n", filename);
1581 return (-1);
1582 }
Owen Taylor3473f882001-02-23 17:55:21 +00001583#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001584 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1585 xmlGenericError(xmlGenericErrorContext,
1586 "Failed to write to %s\n", filename);
1587 return (-1);
1588 }
Owen Taylor3473f882001-02-23 17:55:21 +00001589#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001590 break;
1591 default:{
1592 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001593
Daniel Veillard78d12092001-10-11 09:12:24 +00001594 f = fopen((char *) filename, "w");
1595 if (f == NULL) {
1596 xmlGenericError(xmlGenericErrorContext,
1597 "Failed to write to %s\n", filename);
1598 return (-1);
1599 }
1600 xmlElemDump(f, ctxt->doc, node);
1601 fclose(f);
1602 }
Owen Taylor3473f882001-02-23 17:55:21 +00001603 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001604 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001605}
1606
1607/**
1608 * xmlShellSave:
1609 * @ctxt: the shell context
1610 * @filename: the file name (optionnal)
1611 * @node: unused
1612 * @node2: unused
1613 *
1614 * Implements the XML shell function "save"
1615 * Write the current document to the filename, or it's original name
1616 *
1617 * Returns 0 or -1 in case of error
1618 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001619int
1620xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1621 xmlNodePtr node ATTRIBUTE_UNUSED,
1622 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1623{
Owen Taylor3473f882001-02-23 17:55:21 +00001624 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001625 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001626 if ((filename == NULL) || (filename[0] == 0))
1627 filename = ctxt->filename;
1628#ifdef W_OK
1629 if (access((char *) filename, W_OK)) {
1630 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001631 "Cannot save to %s\n", filename);
1632 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001633 }
1634#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00001635 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001636 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001637 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1638 xmlGenericError(xmlGenericErrorContext,
1639 "Failed to save to %s\n", filename);
1640 }
1641 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001642 case XML_HTML_DOCUMENT_NODE:
1643#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001644 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1645 xmlGenericError(xmlGenericErrorContext,
1646 "Failed to save to %s\n", filename);
1647 }
Owen Taylor3473f882001-02-23 17:55:21 +00001648#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001649 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1650 xmlGenericError(xmlGenericErrorContext,
1651 "Failed to save to %s\n", filename);
1652 }
Owen Taylor3473f882001-02-23 17:55:21 +00001653#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001654 break;
1655 default:
1656 xmlGenericError(xmlGenericErrorContext,
1657 "To save to subparts of a document use the 'write' command\n");
1658 return (-1);
1659
Owen Taylor3473f882001-02-23 17:55:21 +00001660 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001661 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001662}
1663
1664/**
1665 * xmlShellValidate:
1666 * @ctxt: the shell context
1667 * @dtd: the DTD URI (optionnal)
1668 * @node: unused
1669 * @node2: unused
1670 *
1671 * Implements the XML shell function "validate"
1672 * Validate the document, if a DTD path is provided, then the validation
1673 * is done against the given DTD.
1674 *
1675 * Returns 0 or -1 in case of error
1676 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001677int
1678xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1679 xmlNodePtr node ATTRIBUTE_UNUSED,
1680 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1681{
Owen Taylor3473f882001-02-23 17:55:21 +00001682 xmlValidCtxt vctxt;
1683 int res = -1;
1684
1685 vctxt.userData = stderr;
1686 vctxt.error = (xmlValidityErrorFunc) fprintf;
1687 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1688
1689 if ((dtd == NULL) || (dtd[0] == 0)) {
1690 res = xmlValidateDocument(&vctxt, ctxt->doc);
1691 } else {
1692 xmlDtdPtr subset;
1693
Daniel Veillard78d12092001-10-11 09:12:24 +00001694 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1695 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001696 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1697
Daniel Veillard78d12092001-10-11 09:12:24 +00001698 xmlFreeDtd(subset);
1699 }
Owen Taylor3473f882001-02-23 17:55:21 +00001700 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001701 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00001702}
1703
1704/**
1705 * xmlShellDu:
1706 * @ctxt: the shell context
1707 * @arg: unused
1708 * @tree: a node defining a subtree
1709 * @node2: unused
1710 *
1711 * Implements the XML shell function "du"
1712 * show the structure of the subtree under node @tree
1713 * If @tree is null, the command works on the current node.
1714 *
1715 * Returns 0 or -1 in case of error
1716 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001717int
1718xmlShellDu(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1719 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1720 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1721{
Owen Taylor3473f882001-02-23 17:55:21 +00001722 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00001723 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00001724
Daniel Veillard78d12092001-10-11 09:12:24 +00001725 if (tree == NULL)
1726 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001727 node = tree;
1728 while (node != NULL) {
1729 if ((node->type == XML_DOCUMENT_NODE) ||
1730 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001731 printf("/\n");
1732 } else if (node->type == XML_ELEMENT_NODE) {
1733 for (i = 0; i < indent; i++)
1734 printf(" ");
1735 printf("%s\n", node->name);
1736 } else {
1737 }
Owen Taylor3473f882001-02-23 17:55:21 +00001738
Daniel Veillard78d12092001-10-11 09:12:24 +00001739 /*
1740 * Browse the full subtree, deep first
1741 */
Owen Taylor3473f882001-02-23 17:55:21 +00001742
1743 if ((node->type == XML_DOCUMENT_NODE) ||
1744 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001745 node = ((xmlDocPtr) node)->children;
1746 } else if ((node->children != NULL)
1747 && (node->type != XML_ENTITY_REF_NODE)) {
1748 /* deep first */
1749 node = node->children;
1750 indent++;
1751 } else if ((node != tree) && (node->next != NULL)) {
1752 /* then siblings */
1753 node = node->next;
1754 } else if (node != tree) {
1755 /* go up to parents->next if needed */
1756 while (node != tree) {
1757 if (node->parent != NULL) {
1758 node = node->parent;
1759 indent--;
1760 }
1761 if ((node != tree) && (node->next != NULL)) {
1762 node = node->next;
1763 break;
1764 }
1765 if (node->parent == NULL) {
1766 node = NULL;
1767 break;
1768 }
1769 if (node == tree) {
1770 node = NULL;
1771 break;
1772 }
1773 }
1774 /* exit condition */
1775 if (node == tree)
1776 node = NULL;
1777 } else
1778 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001779 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001780 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001781}
1782
1783/**
1784 * xmlShellPwd:
1785 * @ctxt: the shell context
1786 * @buffer: the output buffer
1787 * @tree: a node
1788 * @node2: unused
1789 *
1790 * Implements the XML shell function "pwd"
1791 * Show the full path from the root to the node, if needed building
1792 * thumblers when similar elements exists at a given ancestor level.
1793 * The output is compatible with XPath commands.
1794 *
1795 * Returns 0 or -1 in case of error
1796 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001797int
1798xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
1799 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1800{
Owen Taylor3473f882001-02-23 17:55:21 +00001801 xmlNodePtr cur, tmp, next;
1802 char buf[500];
1803 char sep;
1804 const char *name;
Daniel Veillard78d12092001-10-11 09:12:24 +00001805 char nametemp[100];
Owen Taylor3473f882001-02-23 17:55:21 +00001806 int occur = 0;
1807
1808 buffer[0] = 0;
Daniel Veillard78d12092001-10-11 09:12:24 +00001809 if (node == NULL)
1810 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001811 cur = node;
1812 do {
Daniel Veillard78d12092001-10-11 09:12:24 +00001813 name = "";
1814 sep = '?';
1815 occur = 0;
1816 if ((cur->type == XML_DOCUMENT_NODE) ||
1817 (cur->type == XML_HTML_DOCUMENT_NODE)) {
1818 sep = '/';
1819 next = NULL;
1820 } else if (cur->type == XML_ELEMENT_NODE) {
1821 sep = '/';
1822 name = (const char *) cur->name;
1823 if (cur->ns) {
1824 snprintf(nametemp, 99, "%s:%s", cur->ns->prefix,
1825 cur->name);
1826 name = nametemp;
1827 }
1828 next = cur->parent;
Owen Taylor3473f882001-02-23 17:55:21 +00001829
Daniel Veillard78d12092001-10-11 09:12:24 +00001830 /*
1831 * Thumbler index computation
1832 */
1833 tmp = cur->prev;
Owen Taylor3473f882001-02-23 17:55:21 +00001834 while (tmp != NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001835 if (xmlStrEqual(cur->name, tmp->name))
1836 occur++;
1837 tmp = tmp->prev;
1838 }
1839 if (occur == 0) {
1840 tmp = cur->next;
1841 while (tmp != NULL) {
1842 if (xmlStrEqual(cur->name, tmp->name))
1843 occur++;
1844 tmp = tmp->next;
1845 }
1846 if (occur != 0)
1847 occur = 1;
1848 } else
1849 occur++;
1850 } else if (cur->type == XML_ATTRIBUTE_NODE) {
1851 sep = '@';
1852 name = (const char *) (((xmlAttrPtr) cur)->name);
1853 next = ((xmlAttrPtr) cur)->parent;
1854 } else {
1855 next = cur->parent;
1856 }
1857 if (occur == 0)
1858 snprintf(buf, sizeof(buf), "%c%s%s", sep, name, buffer);
Owen Taylor3473f882001-02-23 17:55:21 +00001859 else
Daniel Veillard78d12092001-10-11 09:12:24 +00001860 snprintf(buf, sizeof(buf), "%c%s[%d]%s",
1861 sep, name, occur, buffer);
Owen Taylor3473f882001-02-23 17:55:21 +00001862 buf[sizeof(buf) - 1] = 0;
1863 /*
1864 * This test prevents buffer overflow, because this routine
1865 * is only called by xmlShell, in which the second argument is
1866 * 500 chars long.
1867 * It is a dirty hack before a cleaner solution is found.
1868 * Documentation should mention that the second argument must
1869 * be at least 500 chars long, and could be stripped if too long.
1870 */
1871 if (strlen(buffer) + strlen(buf) > 499)
Daniel Veillard78d12092001-10-11 09:12:24 +00001872 break;
1873 strcpy(buffer, buf);
Owen Taylor3473f882001-02-23 17:55:21 +00001874 cur = next;
1875 } while (cur != NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00001876 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001877}
1878
1879/**
1880 * xmlShell
1881 * @doc: the initial document
1882 * @filename: the output buffer
1883 * @input: the line reading function
1884 * @output: the output FILE*
1885 *
1886 * Implements the XML shell
1887 * This allow to load, validate, view, modify and save a document
1888 * using a environment similar to a UNIX commandline.
1889 */
1890void
1891xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00001892 FILE * output)
1893{
Owen Taylor3473f882001-02-23 17:55:21 +00001894 char prompt[500] = "/ > ";
1895 char *cmdline = NULL, *cur;
1896 int nbargs;
1897 char command[100];
1898 char arg[400];
1899 int i;
1900 xmlShellCtxtPtr ctxt;
1901 xmlXPathObjectPtr list;
1902
1903 if (doc == NULL)
1904 return;
1905 if (filename == NULL)
1906 return;
1907 if (input == NULL)
1908 return;
1909 if (output == NULL)
1910 return;
1911 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00001912 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00001913 return;
1914 ctxt->loaded = 0;
1915 ctxt->doc = doc;
1916 ctxt->input = input;
1917 ctxt->output = output;
1918 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00001919 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001920
1921#ifdef LIBXML_XPATH_ENABLED
1922 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1923 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001924 xmlFree(ctxt);
1925 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001926 }
1927#endif /* LIBXML_XPATH_ENABLED */
1928 while (1) {
1929 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Daniel Veillard78d12092001-10-11 09:12:24 +00001930 sprintf(prompt, "%s > ", "/");
1931 else if (ctxt->node->name)
1932 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001933 else
Daniel Veillard78d12092001-10-11 09:12:24 +00001934 sprintf(prompt, "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00001935 prompt[sizeof(prompt) - 1] = 0;
1936
Daniel Veillard78d12092001-10-11 09:12:24 +00001937 /*
1938 * Get a new command line
1939 */
Owen Taylor3473f882001-02-23 17:55:21 +00001940 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00001941 if (cmdline == NULL)
1942 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001943
Daniel Veillard78d12092001-10-11 09:12:24 +00001944 /*
1945 * Parse the command itself
1946 */
1947 cur = cmdline;
1948 nbargs = 0;
1949 while ((*cur == ' ') || (*cur == '\t'))
1950 cur++;
1951 i = 0;
1952 while ((*cur != ' ') && (*cur != '\t') &&
1953 (*cur != '\n') && (*cur != '\r')) {
1954 if (*cur == 0)
1955 break;
1956 command[i++] = *cur++;
1957 }
1958 command[i] = 0;
1959 if (i == 0)
1960 continue;
1961 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00001962
Daniel Veillard78d12092001-10-11 09:12:24 +00001963 /*
1964 * Parse the argument
1965 */
1966 while ((*cur == ' ') || (*cur == '\t'))
1967 cur++;
1968 i = 0;
1969 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
1970 if (*cur == 0)
1971 break;
1972 arg[i++] = *cur++;
1973 }
1974 arg[i] = 0;
1975 if (i != 0)
1976 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00001977
Daniel Veillard78d12092001-10-11 09:12:24 +00001978 /*
1979 * start interpreting the command
1980 */
Owen Taylor3473f882001-02-23 17:55:21 +00001981 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00001982 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001983 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00001984 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001985 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00001986 break;
1987 if (!strcmp(command, "validate")) {
1988 xmlShellValidate(ctxt, arg, NULL, NULL);
1989 } else if (!strcmp(command, "load")) {
1990 xmlShellLoad(ctxt, arg, NULL, NULL);
1991 } else if (!strcmp(command, "save")) {
1992 xmlShellSave(ctxt, arg, NULL, NULL);
1993 } else if (!strcmp(command, "write")) {
1994 xmlShellWrite(ctxt, arg, NULL, NULL);
1995 } else if (!strcmp(command, "free")) {
1996 if (arg[0] == 0) {
1997 xmlMemShow(stdout, 0);
1998 } else {
1999 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002000
Daniel Veillard78d12092001-10-11 09:12:24 +00002001 sscanf(arg, "%d", &len);
2002 xmlMemShow(stdout, len);
2003 }
2004 } else if (!strcmp(command, "pwd")) {
2005 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002006
Daniel Veillard78d12092001-10-11 09:12:24 +00002007 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
2008 printf("%s\n", dir);
2009 } else if (!strcmp(command, "du")) {
2010 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2011 } else if (!strcmp(command, "base")) {
2012 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
2013 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2014 int dir = (!strcmp(command, "dir"));
2015
2016 if (arg[0] == 0) {
2017 if (dir)
2018 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2019 else
2020 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2021 } else {
2022 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002023#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002024 ctxt->pctxt->node = ctxt->node;
2025 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2026#else
2027 list = NULL;
2028#endif /* LIBXML_XPATH_ENABLED */
2029 if (list != NULL) {
2030 switch (list->type) {
2031 case XPATH_UNDEFINED:
2032 xmlGenericError(xmlGenericErrorContext,
2033 "%s: no such node\n", arg);
2034 break;
2035 case XPATH_NODESET:{
2036 int indx;
2037
2038 for (indx = 0;
2039 indx < list->nodesetval->nodeNr;
2040 indx++) {
2041 if (dir)
2042 xmlShellDir(ctxt, NULL,
2043 list->nodesetval->
2044 nodeTab[indx], NULL);
2045 else
2046 xmlShellList(ctxt, NULL,
2047 list->nodesetval->
2048 nodeTab[indx], NULL);
2049 }
2050 break;
2051 }
2052 case XPATH_BOOLEAN:
2053 xmlGenericError(xmlGenericErrorContext,
2054 "%s is a Boolean\n", arg);
2055 break;
2056 case XPATH_NUMBER:
2057 xmlGenericError(xmlGenericErrorContext,
2058 "%s is a number\n", arg);
2059 break;
2060 case XPATH_STRING:
2061 xmlGenericError(xmlGenericErrorContext,
2062 "%s is a string\n", arg);
2063 break;
2064 case XPATH_POINT:
2065 xmlGenericError(xmlGenericErrorContext,
2066 "%s is a point\n", arg);
2067 break;
2068 case XPATH_RANGE:
2069 xmlGenericError(xmlGenericErrorContext,
2070 "%s is a range\n", arg);
2071 break;
2072 case XPATH_LOCATIONSET:
2073 xmlGenericError(xmlGenericErrorContext,
2074 "%s is a range\n", arg);
2075 break;
2076 case XPATH_USERS:
2077 xmlGenericError(xmlGenericErrorContext,
2078 "%s is user-defined\n", arg);
2079 break;
2080 case XPATH_XSLT_TREE:
2081 xmlGenericError(xmlGenericErrorContext,
2082 "%s is an XSLT value tree\n",
2083 arg);
2084 break;
2085 }
2086#ifdef LIBXML_XPATH_ENABLED
2087 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002088#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002089 } else {
2090 xmlGenericError(xmlGenericErrorContext,
2091 "%s: no such node\n", arg);
2092 }
2093 ctxt->pctxt->node = NULL;
2094 }
2095 } else if (!strcmp(command, "cd")) {
2096 if (arg[0] == 0) {
2097 ctxt->node = (xmlNodePtr) ctxt->doc;
2098 } else {
2099#ifdef LIBXML_XPATH_ENABLED
2100 ctxt->pctxt->node = ctxt->node;
2101 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2102#else
2103 list = NULL;
2104#endif /* LIBXML_XPATH_ENABLED */
2105 if (list != NULL) {
2106 switch (list->type) {
2107 case XPATH_UNDEFINED:
2108 xmlGenericError(xmlGenericErrorContext,
2109 "%s: no such node\n", arg);
2110 break;
2111 case XPATH_NODESET:
2112 if (list->nodesetval->nodeNr == 1) {
2113 ctxt->node = list->nodesetval->nodeTab[0];
2114 } else
2115 xmlGenericError(xmlGenericErrorContext,
2116 "%s is a %d Node Set\n",
2117 arg,
2118 list->nodesetval->nodeNr);
2119 break;
2120 case XPATH_BOOLEAN:
2121 xmlGenericError(xmlGenericErrorContext,
2122 "%s is a Boolean\n", arg);
2123 break;
2124 case XPATH_NUMBER:
2125 xmlGenericError(xmlGenericErrorContext,
2126 "%s is a number\n", arg);
2127 break;
2128 case XPATH_STRING:
2129 xmlGenericError(xmlGenericErrorContext,
2130 "%s is a string\n", arg);
2131 break;
2132 case XPATH_POINT:
2133 xmlGenericError(xmlGenericErrorContext,
2134 "%s is a point\n", arg);
2135 break;
2136 case XPATH_RANGE:
2137 xmlGenericError(xmlGenericErrorContext,
2138 "%s is a range\n", arg);
2139 break;
2140 case XPATH_LOCATIONSET:
2141 xmlGenericError(xmlGenericErrorContext,
2142 "%s is a range\n", arg);
2143 break;
2144 case XPATH_USERS:
2145 xmlGenericError(xmlGenericErrorContext,
2146 "%s is user-defined\n", arg);
2147 break;
2148 case XPATH_XSLT_TREE:
2149 xmlGenericError(xmlGenericErrorContext,
2150 "%s is an XSLT value tree\n",
2151 arg);
2152 break;
2153 }
2154#ifdef LIBXML_XPATH_ENABLED
2155 xmlXPathFreeObject(list);
2156#endif
2157 } else {
2158 xmlGenericError(xmlGenericErrorContext,
2159 "%s: no such node\n", arg);
2160 }
2161 ctxt->pctxt->node = NULL;
2162 }
2163 } else if (!strcmp(command, "cat")) {
2164 if (arg[0] == 0) {
2165 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2166 } else {
2167 ctxt->pctxt->node = ctxt->node;
2168#ifdef LIBXML_XPATH_ENABLED
2169 ctxt->pctxt->node = ctxt->node;
2170 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2171#else
2172 list = NULL;
2173#endif /* LIBXML_XPATH_ENABLED */
2174 if (list != NULL) {
2175 switch (list->type) {
2176 case XPATH_UNDEFINED:
2177 xmlGenericError(xmlGenericErrorContext,
2178 "%s: no such node\n", arg);
2179 break;
2180 case XPATH_NODESET:{
2181 int indx;
2182
2183 for (indx = 0;
2184 indx < list->nodesetval->nodeNr;
2185 indx++) {
2186 if (i > 0)
2187 printf(" -------\n");
2188 xmlShellCat(ctxt, NULL,
2189 list->nodesetval->
2190 nodeTab[indx], NULL);
2191 }
2192 break;
2193 }
2194 case XPATH_BOOLEAN:
2195 xmlGenericError(xmlGenericErrorContext,
2196 "%s is a Boolean\n", arg);
2197 break;
2198 case XPATH_NUMBER:
2199 xmlGenericError(xmlGenericErrorContext,
2200 "%s is a number\n", arg);
2201 break;
2202 case XPATH_STRING:
2203 xmlGenericError(xmlGenericErrorContext,
2204 "%s is a string\n", arg);
2205 break;
2206 case XPATH_POINT:
2207 xmlGenericError(xmlGenericErrorContext,
2208 "%s is a point\n", arg);
2209 break;
2210 case XPATH_RANGE:
2211 xmlGenericError(xmlGenericErrorContext,
2212 "%s is a range\n", arg);
2213 break;
2214 case XPATH_LOCATIONSET:
2215 xmlGenericError(xmlGenericErrorContext,
2216 "%s is a range\n", arg);
2217 break;
2218 case XPATH_USERS:
2219 xmlGenericError(xmlGenericErrorContext,
2220 "%s is user-defined\n", arg);
2221 break;
2222 case XPATH_XSLT_TREE:
2223 xmlGenericError(xmlGenericErrorContext,
2224 "%s is an XSLT value tree\n",
2225 arg);
2226 break;
2227 }
2228#ifdef LIBXML_XPATH_ENABLED
2229 xmlXPathFreeObject(list);
2230#endif
2231 } else {
2232 xmlGenericError(xmlGenericErrorContext,
2233 "%s: no such node\n", arg);
2234 }
2235 ctxt->pctxt->node = NULL;
2236 }
2237 } else {
2238 xmlGenericError(xmlGenericErrorContext,
2239 "Unknown command %s\n", command);
2240 }
2241 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002242 }
2243#ifdef LIBXML_XPATH_ENABLED
2244 xmlXPathFreeContext(ctxt->pctxt);
2245#endif /* LIBXML_XPATH_ENABLED */
2246 if (ctxt->loaded) {
2247 xmlFreeDoc(ctxt->doc);
2248 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002249 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002250 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002251 xmlFree(ctxt);
2252 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002253 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002254}
2255
2256#endif /* LIBXML_DEBUG_ENABLED */