Annotation of XML/debugXML.c, revision 1.20
1.1 daniel 1: /*
2: * debugXML.c : This is a set of routines used for debugging the tree
3: * produced by the XML parser.
4: *
1.2 daniel 5: * See Copyright for the status of this software.
6: *
1.1 daniel 7: * Daniel Veillard <Daniel.Veillard@w3.org>
8: */
9:
1.11 daniel 10: #ifdef WIN32
11: #include "win32config.h"
12: #else
13: #include "config.h"
14: #endif
1.1 daniel 15: #include <stdio.h>
1.12 daniel 16: #ifdef HAVE_STDLIB_H
17: #include <stdlib.h>
18: #endif
1.14 daniel 19: #ifdef HAVE_STRING_H
20: #include <string.h>
21: #endif
1.12 daniel 22: #include "xmlmemory.h"
1.1 daniel 23: #include "tree.h"
24: #include "parser.h"
1.18 daniel 25: #include "valid.h"
1.1 daniel 26: #include "debugXML.h"
1.12 daniel 27: #include "HTMLtree.h"
28: #include "HTMLparser.h"
1.1 daniel 29:
30: #define IS_BLANK(c) \
31: (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
32:
1.6 daniel 33: void xmlDebugDumpString(FILE *output, const xmlChar *str) {
1.1 daniel 34: int i;
35: for (i = 0;i < 40;i++)
36: if (str[i] == 0) return;
37: else if (IS_BLANK(str[i])) fputc(' ', output);
38: else fputc(str[i], output);
39: fprintf(output, "...");
40: }
41:
1.18 daniel 42: void xmlDebugDumpDtd(FILE *output, xmlDtdPtr dtd, int depth) {
43: int i;
44: char shift[100];
45:
46: for (i = 0;((i < depth) && (i < 25));i++)
47: shift[2 * i] = shift[2 * i + 1] = ' ';
48: shift[2 * i] = shift[2 * i + 1] = 0;
49:
50: fprintf(output, shift);
51:
52: if (dtd->type != XML_DTD_NODE) {
53: fprintf(output, "PBM: not a DTD\n");
54: return;
55: }
56: if (dtd->name != NULL)
57: fprintf(output, "DTD(%s)", dtd->name);
58: else
59: fprintf(output, "DTD");
60: if (dtd->ExternalID != NULL)
61: fprintf(output, ", PUBLIC %s", dtd->ExternalID);
62: if (dtd->SystemID != NULL)
63: fprintf(output, ", SYSTEM %s", dtd->SystemID);
64: fprintf(output, "\n");
65: /*
66: * Do a bit of checking
67: */
68: if (dtd->parent == NULL)
69: fprintf(output, "PBM: Dtd has no parent\n");
70: if (dtd->doc == NULL)
71: fprintf(output, "PBM: Dtd has no doc\n");
72: if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
73: fprintf(output, "PBM: Dtd doc differs from parent's one\n");
74: if (dtd->prev == NULL) {
75: if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
76: fprintf(output, "PBM: Dtd has no prev and not first of list\n");
77: } else {
78: if (dtd->prev->next != (xmlNodePtr) dtd)
79: fprintf(output, "PBM: Dtd prev->next : back link wrong\n");
80: }
81: if (dtd->next == NULL) {
82: if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
83: fprintf(output, "PBM: Dtd has no next and not last of list\n");
84: } else {
85: if (dtd->next->prev != (xmlNodePtr) dtd)
86: fprintf(output, "PBM: Dtd next->prev : forward link wrong\n");
87: }
88: }
89:
90: void xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
91: int i;
92: char shift[100];
93:
94: for (i = 0;((i < depth) && (i < 25));i++)
95: shift[2 * i] = shift[2 * i + 1] = ' ';
96: shift[2 * i] = shift[2 * i + 1] = 0;
97:
98: fprintf(output, shift);
99:
100: if (attr->type != XML_ATTRIBUTE_DECL) {
101: fprintf(output, "PBM: not a Attr\n");
102: return;
103: }
104: if (attr->name != NULL)
105: fprintf(output, "ATTRDECL(%s)", attr->name);
106: else
107: fprintf(output, "PBM ATTRDECL noname!!!");
108: if (attr->elem != NULL)
109: fprintf(output, " for %s", attr->elem);
110: else
111: fprintf(output, " PBM noelem!!!");
112: switch (attr->atype) {
113: case XML_ATTRIBUTE_CDATA:
114: fprintf(output, " CDATA");
115: break;
116: case XML_ATTRIBUTE_ID:
117: fprintf(output, " ID");
118: break;
119: case XML_ATTRIBUTE_IDREF:
120: fprintf(output, " IDREF");
121: break;
122: case XML_ATTRIBUTE_IDREFS:
123: fprintf(output, " IDREFS");
124: break;
125: case XML_ATTRIBUTE_ENTITY:
126: fprintf(output, " ENTITY");
127: break;
128: case XML_ATTRIBUTE_ENTITIES:
129: fprintf(output, " ENTITIES");
130: break;
131: case XML_ATTRIBUTE_NMTOKEN:
132: fprintf(output, " NMTOKEN");
133: break;
134: case XML_ATTRIBUTE_NMTOKENS:
135: fprintf(output, " NMTOKENS");
136: break;
137: case XML_ATTRIBUTE_ENUMERATION:
138: fprintf(output, " ENUMERATION");
139: break;
140: case XML_ATTRIBUTE_NOTATION:
141: fprintf(output, " NOTATION ");
142: break;
143: }
144: if (attr->tree != NULL) {
145: int i;
146: xmlEnumerationPtr cur = attr->tree;
147:
148: for (i = 0;i < 5; i++) {
149: if (i != 0)
150: fprintf(output, "|%s", cur->name);
151: else
152: fprintf(output, " (%s", cur->name);
153: cur = cur->next;
154: if (cur == NULL) break;
155: }
156: if (cur == NULL)
157: fprintf(output, ")");
158: else
159: fprintf(output, "...)");
160: }
161: switch (attr->def) {
162: case XML_ATTRIBUTE_NONE:
163: break;
164: case XML_ATTRIBUTE_REQUIRED:
165: fprintf(output, " REQUIRED");
166: break;
167: case XML_ATTRIBUTE_IMPLIED:
168: fprintf(output, " IMPLIED");
169: break;
170: case XML_ATTRIBUTE_FIXED:
171: fprintf(output, " FIXED");
172: break;
173: }
174: if (attr->defaultValue != NULL) {
175: fprintf(output, "\"");
176: xmlDebugDumpString(output, attr->defaultValue);
177: fprintf(output, "\"");
178: }
179: printf("\n");
180:
181: /*
182: * Do a bit of checking
183: */
184: if (attr->parent == NULL)
185: fprintf(output, "PBM: Attr has no parent\n");
186: if (attr->doc == NULL)
187: fprintf(output, "PBM: Attr has no doc\n");
188: if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
189: fprintf(output, "PBM: Attr doc differs from parent's one\n");
190: if (attr->prev == NULL) {
191: if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
192: fprintf(output, "PBM: Attr has no prev and not first of list\n");
193: } else {
194: if (attr->prev->next != (xmlNodePtr) attr)
195: fprintf(output, "PBM: Attr prev->next : back link wrong\n");
196: }
197: if (attr->next == NULL) {
198: if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
199: fprintf(output, "PBM: Attr has no next and not last of list\n");
200: } else {
201: if (attr->next->prev != (xmlNodePtr) attr)
202: fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
203: }
204: }
205:
206: void xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
207: int i;
208: char shift[100];
209:
210: for (i = 0;((i < depth) && (i < 25));i++)
211: shift[2 * i] = shift[2 * i + 1] = ' ';
212: shift[2 * i] = shift[2 * i + 1] = 0;
213:
214: fprintf(output, shift);
215:
216: if (elem->type != XML_ELEMENT_DECL) {
217: fprintf(output, "PBM: not a Elem\n");
218: return;
219: }
220: if (elem->name != NULL)
221: fprintf(output, "ELEMDECL(%s)", elem->name);
222: else
223: fprintf(output, "PBM ELEMDECL noname!!!");
224: switch (elem->etype) {
225: case XML_ELEMENT_TYPE_EMPTY:
226: fprintf(output, ", EMPTY");
227: break;
228: case XML_ELEMENT_TYPE_ANY:
229: fprintf(output, ", ANY");
230: break;
231: case XML_ELEMENT_TYPE_MIXED:
232: fprintf(output, ", MIXED ");
233: break;
234: case XML_ELEMENT_TYPE_ELEMENT:
235: fprintf(output, ", MIXED ");
236: break;
237: }
238: if (elem->content != NULL) {
239: char buf[1001];
240:
241: buf[0] = 0;
242: xmlSprintfElementContent(buf, elem->content, 1);
243: buf[1000] = 0;
244: fprintf(output, "%s", buf);
245: }
246: printf("\n");
247:
248: /*
249: * Do a bit of checking
250: */
251: if (elem->parent == NULL)
252: fprintf(output, "PBM: Elem has no parent\n");
253: if (elem->doc == NULL)
254: fprintf(output, "PBM: Elem has no doc\n");
255: if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
256: fprintf(output, "PBM: Elem doc differs from parent's one\n");
257: if (elem->prev == NULL) {
258: if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
259: fprintf(output, "PBM: Elem has no prev and not first of list\n");
260: } else {
261: if (elem->prev->next != (xmlNodePtr) elem)
262: fprintf(output, "PBM: Elem prev->next : back link wrong\n");
263: }
264: if (elem->next == NULL) {
265: if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
266: fprintf(output, "PBM: Elem has no next and not last of list\n");
267: } else {
268: if (elem->next->prev != (xmlNodePtr) elem)
269: fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
270: }
271: }
272:
1.20 ! daniel 273: void xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
! 274: int i;
! 275: char shift[100];
! 276:
! 277: for (i = 0;((i < depth) && (i < 25));i++)
! 278: shift[2 * i] = shift[2 * i + 1] = ' ';
! 279: shift[2 * i] = shift[2 * i + 1] = 0;
! 280:
! 281: fprintf(output, shift);
! 282:
! 283: if (ent->type != XML_ENTITY_DECL) {
! 284: fprintf(output, "PBM: not a Entity decl\n");
! 285: return;
! 286: }
! 287: if (ent->name != NULL)
! 288: fprintf(output, "ENTITYDECL(%s)", ent->name);
! 289: else
! 290: fprintf(output, "PBM ENTITYDECL noname!!!");
! 291: switch (ent->etype) {
! 292: case XML_INTERNAL_GENERAL_ENTITY:
! 293: fprintf(output, ", internal\n");
! 294: break;
! 295: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
! 296: fprintf(output, ", external parsed\n");
! 297: break;
! 298: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
! 299: fprintf(output, ", unparsed\n");
! 300: break;
! 301: case XML_INTERNAL_PARAMETER_ENTITY:
! 302: fprintf(output, ", parameter\n");
! 303: break;
! 304: case XML_EXTERNAL_PARAMETER_ENTITY:
! 305: fprintf(output, ", external parameter\n");
! 306: break;
! 307: case XML_INTERNAL_PREDEFINED_ENTITY:
! 308: fprintf(output, ", predefined\n");
! 309: break;
! 310: }
! 311: if (ent->ExternalID) {
! 312: fprintf(output, shift);
! 313: fprintf(output, "ExternalID=%s\n", ent->ExternalID);
! 314: }
! 315: if (ent->SystemID) {
! 316: fprintf(output, shift);
! 317: fprintf(output, "SystemID=%s\n", ent->SystemID);
! 318: }
! 319: if (ent->content) {
! 320: fprintf(output, shift);
! 321: fprintf(output, "content=");
! 322: xmlDebugDumpString(output, ent->content);
! 323: fprintf(output, "\n");
! 324: }
! 325:
! 326: /*
! 327: * Do a bit of checking
! 328: */
! 329: if (ent->parent == NULL)
! 330: fprintf(output, "PBM: Ent has no parent\n");
! 331: if (ent->doc == NULL)
! 332: fprintf(output, "PBM: Ent has no doc\n");
! 333: if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
! 334: fprintf(output, "PBM: Ent doc differs from parent's one\n");
! 335: if (ent->prev == NULL) {
! 336: if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
! 337: fprintf(output, "PBM: Ent has no prev and not first of list\n");
! 338: } else {
! 339: if (ent->prev->next != (xmlNodePtr) ent)
! 340: fprintf(output, "PBM: Ent prev->next : back link wrong\n");
! 341: }
! 342: if (ent->next == NULL) {
! 343: if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
! 344: fprintf(output, "PBM: Ent has no next and not last of list\n");
! 345: } else {
! 346: if (ent->next->prev != (xmlNodePtr) ent)
! 347: fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
! 348: }
! 349: }
! 350:
1.1 daniel 351: void xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
352: int i;
353: char shift[100];
354:
355: for (i = 0;((i < depth) && (i < 25));i++)
356: shift[2 * i] = shift[2 * i + 1] = ' ';
357: shift[2 * i] = shift[2 * i + 1] = 0;
358:
359: fprintf(output, shift);
360: if (ns->type == XML_GLOBAL_NAMESPACE)
361: fprintf(output, "old ");
1.10 daniel 362: if (ns->prefix != NULL)
363: fprintf(output, "namespace %s href=", ns->prefix);
364: else
1.12 daniel 365: fprintf(output, "default namespace href=");
1.10 daniel 366:
1.1 daniel 367: xmlDebugDumpString(output, ns->href);
368: fprintf(output, "\n");
369: }
370:
371: void xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
372: while (ns != NULL) {
373: xmlDebugDumpNamespace(output, ns, depth);
374: ns = ns->next;
375: }
376: }
377:
378: void xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
379: int i;
380: char shift[100];
381:
382: for (i = 0;((i < depth) && (i < 25));i++)
383: shift[2 * i] = shift[2 * i + 1] = ' ';
384: shift[2 * i] = shift[2 * i + 1] = 0;
385:
386: fprintf(output, shift);
1.19 daniel 387: switch (ent->etype) {
1.1 daniel 388: case XML_INTERNAL_GENERAL_ENTITY:
389: fprintf(output, "INTERNAL_GENERAL_ENTITY ");
390: break;
391: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
392: fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
393: break;
394: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
395: fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
396: break;
397: case XML_INTERNAL_PARAMETER_ENTITY:
398: fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
399: break;
400: case XML_EXTERNAL_PARAMETER_ENTITY:
401: fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
402: break;
403: default:
1.19 daniel 404: fprintf(output, "ENTITY_%d ! ", ent->etype);
1.1 daniel 405: }
406: fprintf(output, "%s\n", ent->name);
407: if (ent->ExternalID) {
408: fprintf(output, shift);
409: fprintf(output, "ExternalID=%s\n", ent->ExternalID);
410: }
411: if (ent->SystemID) {
412: fprintf(output, shift);
413: fprintf(output, "SystemID=%s\n", ent->SystemID);
414: }
415: if (ent->content) {
416: fprintf(output, shift);
417: fprintf(output, "content=");
418: xmlDebugDumpString(output, ent->content);
419: fprintf(output, "\n");
420: }
421: }
422:
423: void xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
424: int i;
425: char shift[100];
426:
427: for (i = 0;((i < depth) && (i < 25));i++)
428: shift[2 * i] = shift[2 * i + 1] = ' ';
429: shift[2 * i] = shift[2 * i + 1] = 0;
430:
431: fprintf(output, shift);
1.18 daniel 432:
1.1 daniel 433: fprintf(output, "ATTRIBUTE %s\n", attr->name);
1.16 daniel 434: if (attr->children != NULL)
435: xmlDebugDumpNodeList(output, attr->children, depth + 1);
1.18 daniel 436:
437: /*
438: * Do a bit of checking
439: */
440: if (attr->parent == NULL)
441: fprintf(output, "PBM: Attr has no parent\n");
442: if (attr->doc == NULL)
443: fprintf(output, "PBM: Attr has no doc\n");
444: if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
445: fprintf(output, "PBM: Attr doc differs from parent's one\n");
446: if (attr->prev == NULL) {
447: if ((attr->parent != NULL) && (attr->parent->properties != attr))
448: fprintf(output, "PBM: Attr has no prev and not first of list\n");
449: } else {
450: if (attr->prev->next != attr)
451: fprintf(output, "PBM: Attr prev->next : back link wrong\n");
452: }
453: if (attr->next != NULL) {
454: if (attr->next->prev != attr)
455: fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
456: }
1.1 daniel 457: }
458:
459: void xmlDebugDumpAttrList(FILE *output, xmlAttrPtr attr, int depth) {
460: while (attr != NULL) {
461: xmlDebugDumpAttr(output, attr, depth);
462: attr = attr->next;
463: }
464: }
465:
1.3 daniel 466: void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) {
1.1 daniel 467: int i;
468: char shift[100];
469:
470: for (i = 0;((i < depth) && (i < 25));i++)
471: shift[2 * i] = shift[2 * i + 1] = ' ';
472: shift[2 * i] = shift[2 * i + 1] = 0;
473:
474: fprintf(output, shift);
475: switch (node->type) {
476: case XML_ELEMENT_NODE:
477: fprintf(output, "ELEMENT ");
478: if (node->ns != NULL)
479: fprintf(output, "%s:%s\n", node->ns->prefix, node->name);
480: else
481: fprintf(output, "%s\n", node->name);
482: break;
483: case XML_ATTRIBUTE_NODE:
484: fprintf(output, "Error, ATTRIBUTE found here\n");
485: break;
486: case XML_TEXT_NODE:
487: fprintf(output, "TEXT\n");
488: break;
489: case XML_CDATA_SECTION_NODE:
490: fprintf(output, "CDATA_SECTION\n");
491: break;
492: case XML_ENTITY_REF_NODE:
1.15 daniel 493: fprintf(output, "ENTITY_REF(%s)\n", node->name);
1.1 daniel 494: break;
495: case XML_ENTITY_NODE:
496: fprintf(output, "ENTITY\n");
497: break;
498: case XML_PI_NODE:
1.4 daniel 499: fprintf(output, "PI %s\n", node->name);
1.1 daniel 500: break;
501: case XML_COMMENT_NODE:
502: fprintf(output, "COMMENT\n");
503: break;
504: case XML_DOCUMENT_NODE:
1.7 daniel 505: case XML_HTML_DOCUMENT_NODE:
1.1 daniel 506: fprintf(output, "Error, DOCUMENT found here\n");
507: break;
508: case XML_DOCUMENT_TYPE_NODE:
509: fprintf(output, "DOCUMENT_TYPE\n");
510: break;
511: case XML_DOCUMENT_FRAG_NODE:
512: fprintf(output, "DOCUMENT_FRAG\n");
513: break;
514: case XML_NOTATION_NODE:
515: fprintf(output, "NOTATION\n");
516: break;
1.18 daniel 517: case XML_DTD_NODE:
518: xmlDebugDumpDtd(output, (xmlDtdPtr) node, depth - 1);
519: return;
520: case XML_ELEMENT_DECL:
521: xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth - 2);
522: return;
523: case XML_ATTRIBUTE_DECL:
524: xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth - 2);
525: return;
1.20 ! daniel 526: case XML_ENTITY_DECL:
! 527: xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth - 2);
! 528: return;
1.1 daniel 529: default:
530: fprintf(output, "NODE_%d\n", node->type);
531: }
532: if (node->doc == NULL) {
533: fprintf(output, shift);
534: fprintf(output, "doc == NULL !!!\n");
535: }
536: if (node->nsDef != NULL)
537: xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
538: if (node->properties != NULL)
539: xmlDebugDumpAttrList(output, node->properties, depth + 1);
540: if (node->type != XML_ENTITY_REF_NODE) {
541: if (node->content != NULL) {
542: fprintf(output, shift);
543: fprintf(output, "content=");
1.8 daniel 544: #ifndef XML_USE_BUFFER_CONTENT
1.1 daniel 545: xmlDebugDumpString(output, node->content);
1.8 daniel 546: #else
547: xmlDebugDumpString(output, xmlBufferContent(node->content));
548: #endif
1.1 daniel 549: fprintf(output, "\n");
550: }
551: } else {
552: xmlEntityPtr ent;
553: ent = xmlGetDocEntity(node->doc, node->name);
554: if (ent != NULL)
555: xmlDebugDumpEntity(output, ent, depth + 1);
1.18 daniel 556: }
557: /*
558: * Do a bit of checking
559: */
560: if (node->parent == NULL)
561: fprintf(output, "PBM: Node has no parent\n");
562: if (node->doc == NULL)
563: fprintf(output, "PBM: Node has no doc\n");
564: if ((node->parent != NULL) && (node->doc != node->parent->doc))
565: fprintf(output, "PBM: Node doc differs from parent's one\n");
566: if (node->prev == NULL) {
567: if ((node->parent != NULL) && (node->parent->children != node))
568: fprintf(output, "PBM: Node has no prev and not first of list\n");
569: } else {
570: if (node->prev->next != node)
571: fprintf(output, "PBM: Node prev->next : back link wrong\n");
572: }
573: if (node->next == NULL) {
574: if ((node->parent != NULL) && (node->parent->last != node))
575: fprintf(output, "PBM: Node has no next and not last of list\n");
576: } else {
577: if (node->next->prev != node)
578: fprintf(output, "PBM: Node next->prev : forward link wrong\n");
1.1 daniel 579: }
1.3 daniel 580: }
581:
582: void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth) {
583: xmlDebugDumpOneNode(output, node, depth);
1.16 daniel 584: if (node->children != NULL)
585: xmlDebugDumpNodeList(output, node->children, depth + 1);
1.1 daniel 586: }
587:
588: void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth) {
589: while (node != NULL) {
590: xmlDebugDumpNode(output, node, depth);
591: node = node->next;
592: }
593: }
594:
595:
1.12 daniel 596: void xmlDebugDumpDocumentHead(FILE *output, xmlDocPtr doc) {
1.1 daniel 597: if (output == NULL) output = stdout;
598: if (doc == NULL) {
599: fprintf(output, "DOCUMENT == NULL !\n");
600: return;
601: }
602:
603: switch (doc->type) {
604: case XML_ELEMENT_NODE:
605: fprintf(output, "Error, ELEMENT found here ");
606: break;
607: case XML_ATTRIBUTE_NODE:
608: fprintf(output, "Error, ATTRIBUTE found here\n");
609: break;
610: case XML_TEXT_NODE:
611: fprintf(output, "Error, TEXT\n");
612: break;
613: case XML_CDATA_SECTION_NODE:
614: fprintf(output, "Error, CDATA_SECTION\n");
615: break;
616: case XML_ENTITY_REF_NODE:
617: fprintf(output, "Error, ENTITY_REF\n");
618: break;
619: case XML_ENTITY_NODE:
620: fprintf(output, "Error, ENTITY\n");
621: break;
622: case XML_PI_NODE:
623: fprintf(output, "Error, PI\n");
624: break;
625: case XML_COMMENT_NODE:
626: fprintf(output, "Error, COMMENT\n");
627: break;
628: case XML_DOCUMENT_NODE:
629: fprintf(output, "DOCUMENT\n");
1.7 daniel 630: break;
631: case XML_HTML_DOCUMENT_NODE:
632: fprintf(output, "HTML DOCUMENT\n");
1.1 daniel 633: break;
634: case XML_DOCUMENT_TYPE_NODE:
635: fprintf(output, "Error, DOCUMENT_TYPE\n");
636: break;
637: case XML_DOCUMENT_FRAG_NODE:
638: fprintf(output, "Error, DOCUMENT_FRAG\n");
639: break;
640: case XML_NOTATION_NODE:
641: fprintf(output, "Error, NOTATION\n");
642: break;
643: default:
644: fprintf(output, "NODE_%d\n", doc->type);
645: }
646: if (doc->name != NULL) {
647: fprintf(output, "name=");
1.5 daniel 648: xmlDebugDumpString(output, BAD_CAST doc->name);
1.1 daniel 649: fprintf(output, "\n");
650: }
651: if (doc->version != NULL) {
652: fprintf(output, "version=");
653: xmlDebugDumpString(output, doc->version);
654: fprintf(output, "\n");
655: }
656: if (doc->encoding != NULL) {
657: fprintf(output, "encoding=");
658: xmlDebugDumpString(output, doc->encoding);
659: fprintf(output, "\n");
660: }
661: if (doc->standalone)
662: fprintf(output, "standalone=true\n");
663: if (doc->oldNs != NULL)
664: xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
1.12 daniel 665: }
666:
667: void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
668: if (output == NULL) output = stdout;
669: if (doc == NULL) {
670: fprintf(output, "DOCUMENT == NULL !\n");
671: return;
672: }
673: xmlDebugDumpDocumentHead(output, doc);
674: if (((doc->type == XML_DOCUMENT_NODE) ||
675: (doc->type == XML_HTML_DOCUMENT_NODE)) &&
1.16 daniel 676: (doc->children != NULL))
677: xmlDebugDumpNodeList(output, doc->children, 1);
1.12 daniel 678: }
1.9 daniel 679:
680: void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
681: int i;
682: xmlEntityPtr cur;
683:
684: if (output == NULL) output = stdout;
685: if (doc == NULL) {
686: fprintf(output, "DOCUMENT == NULL !\n");
687: return;
688: }
689:
690: switch (doc->type) {
691: case XML_ELEMENT_NODE:
692: fprintf(output, "Error, ELEMENT found here ");
693: break;
694: case XML_ATTRIBUTE_NODE:
695: fprintf(output, "Error, ATTRIBUTE found here\n");
696: break;
697: case XML_TEXT_NODE:
698: fprintf(output, "Error, TEXT\n");
699: break;
700: case XML_CDATA_SECTION_NODE:
701: fprintf(output, "Error, CDATA_SECTION\n");
702: break;
703: case XML_ENTITY_REF_NODE:
704: fprintf(output, "Error, ENTITY_REF\n");
705: break;
706: case XML_ENTITY_NODE:
707: fprintf(output, "Error, ENTITY\n");
708: break;
709: case XML_PI_NODE:
710: fprintf(output, "Error, PI\n");
711: break;
712: case XML_COMMENT_NODE:
713: fprintf(output, "Error, COMMENT\n");
714: break;
715: case XML_DOCUMENT_NODE:
716: fprintf(output, "DOCUMENT\n");
717: break;
718: case XML_HTML_DOCUMENT_NODE:
719: fprintf(output, "HTML DOCUMENT\n");
720: break;
721: case XML_DOCUMENT_TYPE_NODE:
722: fprintf(output, "Error, DOCUMENT_TYPE\n");
723: break;
724: case XML_DOCUMENT_FRAG_NODE:
725: fprintf(output, "Error, DOCUMENT_FRAG\n");
726: break;
727: case XML_NOTATION_NODE:
728: fprintf(output, "Error, NOTATION\n");
729: break;
730: default:
731: fprintf(output, "NODE_%d\n", doc->type);
732: }
733: if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
734: xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
735: doc->intSubset->entities;
736: fprintf(output, "Entities in internal subset\n");
737: for (i = 0;i < table->nb_entities;i++) {
1.20 ! daniel 738: cur = table->table[i];
1.9 daniel 739: fprintf(output, "%d : %s : ", i, cur->name);
1.19 daniel 740: switch (cur->etype) {
1.9 daniel 741: case XML_INTERNAL_GENERAL_ENTITY:
742: fprintf(output, "INTERNAL GENERAL");
743: break;
744: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
745: fprintf(output, "EXTERNAL PARSED");
746: break;
747: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
748: fprintf(output, "EXTERNAL UNPARSED");
749: break;
750: case XML_INTERNAL_PARAMETER_ENTITY:
751: fprintf(output, "INTERNAL PARAMETER");
752: break;
753: case XML_EXTERNAL_PARAMETER_ENTITY:
754: fprintf(output, "EXTERNAL PARAMETER");
755: break;
756: default:
757: fprintf(output, "UNKNOWN TYPE %d",
1.19 daniel 758: cur->etype);
1.9 daniel 759: }
760: if (cur->ExternalID != NULL)
761: fprintf(output, "ID \"%s\"", cur->ExternalID);
762: if (cur->SystemID != NULL)
763: fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
764: if (cur->orig != NULL)
765: fprintf(output, "\n orig \"%s\"", cur->orig);
766: if (cur->content != NULL)
767: fprintf(output, "\n content \"%s\"", cur->content);
768: fprintf(output, "\n");
769: }
770: } else
771: fprintf(output, "No entities in internal subset\n");
772: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
773: xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
774: doc->extSubset->entities;
775: fprintf(output, "Entities in external subset\n");
776: for (i = 0;i < table->nb_entities;i++) {
1.20 ! daniel 777: cur = table->table[i];
1.9 daniel 778: fprintf(output, "%d : %s : ", i, cur->name);
1.19 daniel 779: switch (cur->etype) {
1.9 daniel 780: case XML_INTERNAL_GENERAL_ENTITY:
781: fprintf(output, "INTERNAL GENERAL");
782: break;
783: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
784: fprintf(output, "EXTERNAL PARSED");
785: break;
786: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
787: fprintf(output, "EXTERNAL UNPARSED");
788: break;
789: case XML_INTERNAL_PARAMETER_ENTITY:
790: fprintf(output, "INTERNAL PARAMETER");
791: break;
792: case XML_EXTERNAL_PARAMETER_ENTITY:
793: fprintf(output, "EXTERNAL PARAMETER");
794: break;
795: default:
796: fprintf(output, "UNKNOWN TYPE %d",
1.19 daniel 797: cur->etype);
1.9 daniel 798: }
799: if (cur->ExternalID != NULL)
800: fprintf(output, "ID \"%s\"", cur->ExternalID);
801: if (cur->SystemID != NULL)
802: fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
803: if (cur->orig != NULL)
804: fprintf(output, "\n orig \"%s\"", cur->orig);
805: if (cur->content != NULL)
806: fprintf(output, "\n content \"%s\"", cur->content);
807: fprintf(output, "\n");
808: }
809: } else
810: fprintf(output, "No entities in external subset\n");
811: }
1.12 daniel 812:
813: static int xmlLsCountNode(xmlNodePtr node) {
814: int ret = 0;
815: xmlNodePtr list = NULL;
816:
817: switch (node->type) {
818: case XML_ELEMENT_NODE:
1.16 daniel 819: list = node->children;
1.12 daniel 820: break;
821: case XML_DOCUMENT_NODE:
822: case XML_HTML_DOCUMENT_NODE:
1.16 daniel 823: list = ((xmlDocPtr) node)->children;
1.12 daniel 824: break;
825: case XML_ATTRIBUTE_NODE:
1.16 daniel 826: list = ((xmlAttrPtr) node)->children;
1.12 daniel 827: break;
828: case XML_TEXT_NODE:
829: case XML_CDATA_SECTION_NODE:
830: case XML_PI_NODE:
831: case XML_COMMENT_NODE:
832: if (node->content != NULL) {
833: #ifndef XML_USE_BUFFER_CONTENT
834: ret = xmlStrlen(node->content);
835: #else
836: ret = xmlBufferLength(node->content);
837: #endif
838: }
839: break;
840: case XML_ENTITY_REF_NODE:
841: case XML_DOCUMENT_TYPE_NODE:
842: case XML_ENTITY_NODE:
843: case XML_DOCUMENT_FRAG_NODE:
844: case XML_NOTATION_NODE:
1.16 daniel 845: case XML_DTD_NODE:
1.17 daniel 846: case XML_ELEMENT_DECL:
847: case XML_ATTRIBUTE_DECL:
1.20 ! daniel 848: case XML_ENTITY_DECL:
1.12 daniel 849: ret = 1;
850: break;
851: }
852: for (;list != NULL;ret++)
853: list = list->next;
854: return(ret);
855: }
856:
857: void xmlLsOneNode(FILE *output, xmlNodePtr node) {
858: switch (node->type) {
859: case XML_ELEMENT_NODE:
860: fprintf(output, "-");
861: break;
862: case XML_ATTRIBUTE_NODE:
863: fprintf(output, "a");
864: break;
865: case XML_TEXT_NODE:
866: fprintf(output, "t");
867: break;
868: case XML_CDATA_SECTION_NODE:
869: fprintf(output, "c");
870: break;
871: case XML_ENTITY_REF_NODE:
872: fprintf(output, "e");
873: break;
874: case XML_ENTITY_NODE:
875: fprintf(output, "E");
876: break;
877: case XML_PI_NODE:
878: fprintf(output, "p");
879: break;
880: case XML_COMMENT_NODE:
881: fprintf(output, "c");
882: break;
883: case XML_DOCUMENT_NODE:
884: fprintf(output, "d");
885: break;
886: case XML_HTML_DOCUMENT_NODE:
887: fprintf(output, "h");
888: break;
889: case XML_DOCUMENT_TYPE_NODE:
890: fprintf(output, "T");
891: break;
892: case XML_DOCUMENT_FRAG_NODE:
893: fprintf(output, "F");
894: break;
895: case XML_NOTATION_NODE:
896: fprintf(output, "N");
897: break;
898: default:
899: fprintf(output, "?");
900: }
901: if (node->properties != NULL)
902: fprintf(output, "a");
903: else
904: fprintf(output, "-");
905: if (node->nsDef != NULL)
906: fprintf(output, "n");
907: else
908: fprintf(output, "-");
909:
910: fprintf(output, " %8d ", xmlLsCountNode(node));
911:
912: switch (node->type) {
913: case XML_ELEMENT_NODE:
914: if (node->name != NULL)
915: fprintf(output, "%s", node->name);
916: break;
917: case XML_ATTRIBUTE_NODE:
918: if (node->name != NULL)
919: fprintf(output, "%s", node->name);
920: break;
921: case XML_TEXT_NODE:
922: if (node->content != NULL) {
923: #ifndef XML_USE_BUFFER_CONTENT
924: xmlDebugDumpString(output, node->content);
925: #else
926: xmlDebugDumpString(output, xmlBufferContent(node->content));
927: #endif
928: }
929: break;
930: case XML_CDATA_SECTION_NODE:
931: break;
932: case XML_ENTITY_REF_NODE:
933: if (node->name != NULL)
934: fprintf(output, "%s", node->name);
935: break;
936: case XML_ENTITY_NODE:
937: if (node->name != NULL)
938: fprintf(output, "%s", node->name);
939: break;
940: case XML_PI_NODE:
941: if (node->name != NULL)
942: fprintf(output, "%s", node->name);
943: break;
944: case XML_COMMENT_NODE:
945: break;
946: case XML_DOCUMENT_NODE:
947: break;
948: case XML_HTML_DOCUMENT_NODE:
949: break;
950: case XML_DOCUMENT_TYPE_NODE:
951: break;
952: case XML_DOCUMENT_FRAG_NODE:
953: break;
954: case XML_NOTATION_NODE:
955: break;
956: default:
957: if (node->name != NULL)
958: fprintf(output, "%s", node->name);
959: }
960: fprintf(output, "\n");
961: }
962:
963: /****************************************************************
964: * *
965: * The XML shell related functions *
966: * *
967: ****************************************************************/
968:
969: /*
970: * TODO: Improvement/cleanups for the XML shell
971: * - allow to shell out an editor on a subpart
972: * - cleanup function registrations (with help) and calling
973: * - provide registration routines
974: */
975:
976: /**
977: * xmlShellList:
978: * @ctxt: the shell context
979: * @arg: unused
980: * @node: a node
981: * @node2: unused
982: *
983: * Implements the XML shell function "ls"
984: * Does an Unix like listing of the given node (like a directory)
985: *
986: * Returns 0
987: */
988: int
989: xmlShellList(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
990: xmlNodePtr node2) {
991: xmlNodePtr cur;
992:
993: if ((node->type == XML_DOCUMENT_NODE) ||
994: (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16 daniel 995: cur = ((xmlDocPtr) node)->children;
996: } else if (node->children != NULL) {
997: cur = node->children;
1.12 daniel 998: } else {
999: xmlLsOneNode(stdout, node);
1000: return(0);
1001: }
1002: while (cur != NULL) {
1003: xmlLsOneNode(stdout, cur);
1004: cur = cur->next;
1005: }
1006: return(0);
1007: }
1008:
1009: /**
1010: * xmlShellDir:
1011: * @ctxt: the shell context
1012: * @arg: unused
1013: * @node: a node
1014: * @node2: unused
1015: *
1016: * Implements the XML shell function "dir"
1017: * dumps informations about the node (namespace, attributes, content).
1018: *
1019: * Returns 0
1020: */
1021: int
1022: xmlShellDir(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
1023: xmlNodePtr node2) {
1024: if ((node->type == XML_DOCUMENT_NODE) ||
1025: (node->type == XML_HTML_DOCUMENT_NODE)) {
1026: xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
1027: } else if (node->type == XML_ATTRIBUTE_NODE) {
1028: xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
1029: } else {
1030: xmlDebugDumpOneNode(stdout, node, 0);
1031: }
1032: return(0);
1033: }
1034:
1035: /**
1036: * xmlShellCat:
1037: * @ctxt: the shell context
1038: * @arg: unused
1039: * @node: a node
1040: * @node2: unused
1041: *
1042: * Implements the XML shell function "cat"
1043: * dumps the serialization node content (XML or HTML).
1044: *
1045: * Returns 0
1046: */
1047: int
1048: xmlShellCat(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
1049: xmlNodePtr node2) {
1.13 daniel 1050: if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1051: if (node->type == XML_HTML_DOCUMENT_NODE)
1052: htmlDocDump(stdout, (htmlDocPtr) node);
1053: else
1.14 daniel 1054: htmlNodeDumpFile(stdout, ctxt->doc, node);
1.13 daniel 1055: } else {
1056: if (node->type == XML_DOCUMENT_NODE)
1057: xmlDocDump(stdout, (xmlDocPtr) node);
1058: else
1059: xmlElemDump(stdout, ctxt->doc, node);
1060: }
1.12 daniel 1061: printf("\n");
1062: return(0);
1063: }
1064:
1065: /**
1066: * xmlShellLoad:
1067: * @ctxt: the shell context
1068: * @filename: the file name
1069: * @node: unused
1070: * @node2: unused
1071: *
1072: * Implements the XML shell function "load"
1073: * loads a new document specified by the filename
1074: *
1075: * Returns 0 or -1 if loading failed
1076: */
1077: int
1078: xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1079: xmlNodePtr node2) {
1080: xmlDocPtr doc;
1081: int html = 0;
1082:
1083: if (ctxt->doc != NULL)
1084: html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
1085:
1086: if (html) {
1087: doc = htmlParseFile(filename, NULL);
1088: } else {
1089: doc = xmlParseFile(filename);
1090: }
1091: if (doc != NULL) {
1092: if (ctxt->loaded == 1) {
1093: xmlFreeDoc(ctxt->doc);
1094: }
1095: ctxt->loaded = 1;
1096: xmlXPathFreeContext(ctxt->pctxt);
1097: xmlFree(ctxt->filename);
1098: ctxt->doc = doc;
1099: ctxt->node = (xmlNodePtr) doc;
1100: ctxt->pctxt = xmlXPathNewContext(doc);
1101: ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1102: } else
1103: return(-1);
1104: return(0);
1105: }
1106:
1107: /**
1108: * xmlShellWrite:
1109: * @ctxt: the shell context
1110: * @filename: the file name
1111: * @node: a node in the tree
1112: * @node2: unused
1113: *
1114: * Implements the XML shell function "write"
1115: * Write the current node to the filename, it saves the serailization
1116: * of the subtree under the @node specified
1117: *
1118: * Returns 0 or -1 in case of error
1119: */
1120: int
1121: xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1122: xmlNodePtr node2) {
1123: if (node == NULL)
1124: return(-1);
1125: if ((filename == NULL) || (filename[0] == 0)) {
1126: fprintf(stderr, "Write command requires a filename argument\n");
1127: return(-1);
1128: }
1129: #ifdef W_OK
1130: if (access((char *) filename, W_OK)) {
1131: fprintf(stderr, "Cannot write to %s\n", filename);
1132: return(-1);
1133: }
1134: #endif
1135: switch(node->type) {
1136: case XML_DOCUMENT_NODE:
1137: if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1138: fprintf(stderr, "Failed to write to %s\n", filename);
1139: return(-1);
1140: }
1141: break;
1142: case XML_HTML_DOCUMENT_NODE:
1143: if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1144: fprintf(stderr, "Failed to write to %s\n", filename);
1145: return(-1);
1146: }
1147: break;
1148: default: {
1149: FILE *f;
1150:
1151: f = fopen((char *) filename, "w");
1152: if (f == NULL) {
1153: fprintf(stderr, "Failed to write to %s\n", filename);
1154: return(-1);
1155: }
1156: xmlElemDump(f, ctxt->doc, node);
1157: fclose(f);
1158: }
1159: }
1160: return(0);
1161: }
1162:
1163: /**
1164: * xmlShellSave:
1165: * @ctxt: the shell context
1166: * @filename: the file name (optionnal)
1167: * @node: unused
1168: * @node2: unused
1169: *
1170: * Implements the XML shell function "save"
1171: * Write the current document to the filename, or it's original name
1172: *
1173: * Returns 0 or -1 in case of error
1174: */
1175: int
1176: xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1177: xmlNodePtr node2) {
1178: if (ctxt->doc == NULL)
1179: return(-1);
1180: if ((filename == NULL) || (filename[0] == 0))
1181: filename = ctxt->filename;
1182: #ifdef W_OK
1183: if (access((char *) filename, W_OK)) {
1184: fprintf(stderr, "Cannot save to %s\n", filename);
1185: return(-1);
1186: }
1187: #endif
1188: switch(ctxt->doc->type) {
1189: case XML_DOCUMENT_NODE:
1190: if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1191: fprintf(stderr, "Failed to save to %s\n", filename);
1192: }
1193: break;
1194: case XML_HTML_DOCUMENT_NODE:
1195: if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1196: fprintf(stderr, "Failed to save to %s\n", filename);
1197: }
1198: break;
1199: default:
1200: fprintf(stderr,
1201: "To save to subparts of a document use the 'write' command\n");
1202: return(-1);
1203:
1204: }
1205: return(0);
1206: }
1207:
1208: /**
1209: * xmlShellValidate:
1210: * @ctxt: the shell context
1211: * @dtd: the DTD URI (optionnal)
1212: * @node: unused
1213: * @node2: unused
1214: *
1215: * Implements the XML shell function "validate"
1216: * Validate the document, if a DTD path is provided, then the validation
1217: * is done against the given DTD.
1218: *
1219: * Returns 0 or -1 in case of error
1220: */
1221: int
1222: xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node,
1223: xmlNodePtr node2) {
1224: xmlValidCtxt vctxt;
1225: int res = -1;
1226:
1227: vctxt.userData = stderr;
1228: vctxt.error = (xmlValidityErrorFunc) fprintf;
1229: vctxt.warning = (xmlValidityWarningFunc) fprintf;
1230:
1231: if ((dtd == NULL) || (dtd[0] == 0)) {
1232: res = xmlValidateDocument(&vctxt, ctxt->doc);
1233: } else {
1234: xmlDtdPtr subset;
1235:
1236: subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1237: if (subset != NULL) {
1238: res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1239:
1240: xmlFreeDtd(subset);
1241: }
1242: }
1243: return(res);
1244: }
1245:
1246: /**
1247: * xmlShellDu:
1248: * @ctxt: the shell context
1249: * @arg: unused
1250: * @tree: a node defining a subtree
1251: * @node2: unused
1252: *
1253: * Implements the XML shell function "du"
1254: * show the structure of the subtree under node @tree
1255: * If @tree is null, the command works on the current node.
1256: *
1257: * Returns 0 or -1 in case of error
1258: */
1259: int
1260: xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
1261: xmlNodePtr node2) {
1262: xmlNodePtr node;
1263: int indent = 0,i;
1264:
1265: if (tree == NULL) return(-1);
1266: node = tree;
1267: while (node != NULL) {
1268: if ((node->type == XML_DOCUMENT_NODE) ||
1269: (node->type == XML_HTML_DOCUMENT_NODE)) {
1270: printf("/\n");
1271: } else if (node->type == XML_ELEMENT_NODE) {
1272: for (i = 0;i < indent;i++)
1273: printf(" ");
1274: printf("%s\n", node->name);
1275: } else {
1276: }
1277:
1278: /*
1279: * Browse the full subtree, deep first
1280: */
1281:
1282: if ((node->type == XML_DOCUMENT_NODE) ||
1283: (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16 daniel 1284: node = ((xmlDocPtr) node)->children;
1285: } else if (node->children != NULL) {
1.12 daniel 1286: /* deep first */
1.16 daniel 1287: node = node->children;
1.12 daniel 1288: indent++;
1289: } else if ((node != tree) && (node->next != NULL)) {
1290: /* then siblings */
1291: node = node->next;
1292: } else if (node != tree) {
1293: /* go up to parents->next if needed */
1294: while (node != tree) {
1295: if (node->parent != NULL) {
1296: node = node->parent;
1297: indent--;
1298: }
1299: if ((node != tree) && (node->next != NULL)) {
1300: node = node->next;
1301: break;
1302: }
1303: if (node->parent == NULL) {
1304: node = NULL;
1305: break;
1306: }
1307: if (node == tree) {
1308: node = NULL;
1309: break;
1310: }
1311: }
1312: /* exit condition */
1313: if (node == tree)
1314: node = NULL;
1315: } else
1316: node = NULL;
1317: }
1318: return(0);
1319: }
1320:
1321: /**
1322: * xmlShellPwd:
1323: * @ctxt: the shell context
1324: * @buffer: the output buffer
1325: * @tree: a node
1326: * @node2: unused
1327: *
1328: * Implements the XML shell function "pwd"
1329: * Show the full path from the root to the node, if needed building
1330: * thumblers when similar elements exists at a given ancestor level.
1331: * The output is compatible with XPath commands.
1332: *
1333: * Returns 0 or -1 in case of error
1334: */
1335: int
1336: xmlShellPwd(xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node,
1337: xmlNodePtr node2) {
1338: xmlNodePtr cur, tmp, next;
1339: char buf[500];
1340: char sep;
1341: const char *name;
1342: int occur = 0;
1343:
1344: buffer[0] = 0;
1345: if (node == NULL) return(-1);
1346: cur = node;
1347: do {
1348: name = "";
1349: sep= '?';
1350: occur = 0;
1351: if ((cur->type == XML_DOCUMENT_NODE) ||
1352: (cur->type == XML_HTML_DOCUMENT_NODE)) {
1353: sep = '/';
1354: next = NULL;
1355: } else if (cur->type == XML_ELEMENT_NODE) {
1356: sep = '/';
1357: name = (const char *)cur->name;
1358: next = cur->parent;
1359:
1360: /*
1361: * Thumbler index computation
1362: */
1363: tmp = cur->prev;
1364: while (tmp != NULL) {
1365: if (!xmlStrcmp(cur->name, tmp->name))
1366: occur++;
1367: tmp = tmp->prev;
1368: }
1369: if (occur == 0) {
1370: tmp = cur->next;
1371: while (tmp != NULL) {
1372: if (!xmlStrcmp(cur->name, tmp->name))
1373: occur++;
1374: tmp = tmp->next;
1375: }
1376: if (occur != 0) occur = 1;
1377: } else
1378: occur++;
1379: } else if (cur->type == XML_ATTRIBUTE_NODE) {
1380: sep = '@';
1381: name = (const char *) (((xmlAttrPtr) cur)->name);
1.16 daniel 1382: next = ((xmlAttrPtr) cur)->parent;
1.12 daniel 1383: } else {
1384: next = cur->parent;
1385: }
1386: if (occur == 0)
1387: sprintf(buf, "%c%s%s", sep, name, buffer);
1388: else
1389: sprintf(buf, "%c%s[%d]%s", sep, name, occur, buffer);
1390: strcpy(buffer, buf);
1391: cur = next;
1392: } while (cur != NULL);
1393: return(0);
1394: }
1395:
1396: /**
1397: * xmlShell
1398: * @doc: the initial document
1399: * @filename: the output buffer
1400: * @input: the line reading function
1401: * @output: the output FILE*
1402: *
1403: * Implements the XML shell
1404: * This allow to load, validate, view, modify and save a document
1405: * using a environment similar to a UNIX commandline.
1406: */
1407: void
1408: xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
1409: FILE *output) {
1410: char prompt[500] = "/ > ";
1411: char *cmdline = NULL;
1412: int nbargs;
1413: char command[100];
1414: char arg[400];
1415: xmlShellCtxtPtr ctxt;
1416: xmlXPathObjectPtr list;
1417:
1418: if (doc == NULL)
1419: return;
1420: if (filename == NULL)
1421: return;
1422: if (input == NULL)
1423: return;
1424: if (output == NULL)
1425: return;
1426: ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
1427: if (ctxt == NULL)
1428: return;
1429: ctxt->loaded = 0;
1430: ctxt->doc = doc;
1431: ctxt->input = input;
1432: ctxt->output = output;
1433: ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1434: ctxt->node = (xmlNodePtr) ctxt->doc;
1435:
1436: ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1437: if (ctxt->pctxt == NULL) {
1438: xmlFree(ctxt);
1439: return;
1440: }
1441: while (1) {
1442: if (ctxt->node == (xmlNodePtr) ctxt->doc)
1443: sprintf(prompt, "%s > ", "/");
1444: else if (ctxt->node->name)
1445: sprintf(prompt, "%s > ", ctxt->node->name);
1446: else
1447: sprintf(prompt, "? > ");
1448:
1449: cmdline = ctxt->input(prompt);
1450: if (cmdline == NULL) break;
1451:
1452: command[0] = 0;
1453: arg[0] = 0;
1454: nbargs = sscanf(cmdline, "%s %s", command, arg);
1455:
1456: if (command[0] == 0) continue;
1457: if (!strcmp(command, "exit"))
1458: break;
1459: if (!strcmp(command, "quit"))
1460: break;
1461: if (!strcmp(command, "bye"))
1462: break;
1463: if (!strcmp(command, "validate")) {
1464: xmlShellValidate(ctxt, arg, NULL, NULL);
1465: } else if (!strcmp(command, "load")) {
1466: xmlShellLoad(ctxt, arg, NULL, NULL);
1467: } else if (!strcmp(command, "save")) {
1468: xmlShellSave(ctxt, arg, NULL, NULL);
1469: } else if (!strcmp(command, "write")) {
1470: xmlShellWrite(ctxt, arg, NULL, NULL);
1471: } else if (!strcmp(command, "free")) {
1472: if (arg[0] == 0) {
1473: xmlMemShow(stdout, 0);
1474: } else {
1475: int len = 0;
1476: sscanf(arg, "%d", &len);
1477: xmlMemShow(stdout, len);
1478: }
1479: } else if (!strcmp(command, "pwd")) {
1480: char dir[500];
1481: if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
1482: printf("%s\n", dir);
1483: } else if (!strcmp(command, "du")) {
1484: xmlShellDu(ctxt, NULL, ctxt->node, NULL);
1485: } else if ((!strcmp(command, "ls")) ||
1486: (!strcmp(command, "dir"))) {
1487: int dir = (!strcmp(command, "dir"));
1488: if (arg[0] == 0) {
1489: if (dir)
1490: xmlShellDir(ctxt, NULL, ctxt->node, NULL);
1491: else
1492: xmlShellList(ctxt, NULL, ctxt->node, NULL);
1493: } else {
1494: ctxt->pctxt->node = ctxt->node;
1495: if (ctxt->pctxt->nodelist != NULL)
1496: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1497: ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
1498: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1499: if (list != NULL) {
1500: switch (list->type) {
1501: case XPATH_UNDEFINED:
1502: fprintf(stderr, "%s: no such node\n", arg);
1503: break;
1504: case XPATH_NODESET: {
1505: int i;
1506:
1507: for (i = 0;i < list->nodesetval->nodeNr;i++) {
1508: if (dir)
1509: xmlShellDir(ctxt, NULL,
1510: list->nodesetval->nodeTab[i], NULL);
1511: else
1512: xmlShellList(ctxt, NULL,
1513: list->nodesetval->nodeTab[i], NULL);
1514: }
1515: break;
1516: }
1517: case XPATH_BOOLEAN:
1518: fprintf(stderr, "%s is a Boolean\n", arg);
1519: break;
1520: case XPATH_NUMBER:
1521: fprintf(stderr, "%s is a number\n", arg);
1522: break;
1523: case XPATH_STRING:
1524: fprintf(stderr, "%s is a string\n", arg);
1525: break;
1526: }
1527: xmlXPathFreeNodeSetList(list);
1528: } else {
1529: fprintf(stderr, "%s: no such node\n", arg);
1530: }
1531: if (ctxt->pctxt->nodelist != NULL)
1532: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1533: ctxt->pctxt->nodelist = NULL;
1534: }
1535: } else if (!strcmp(command, "cd")) {
1536: if (arg[0] == 0) {
1537: ctxt->node = (xmlNodePtr) ctxt->doc;
1538: } else {
1539: ctxt->pctxt->node = ctxt->node;
1540: if (ctxt->pctxt->nodelist != NULL)
1541: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1542: ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
1543: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1544: if (list != NULL) {
1545: switch (list->type) {
1546: case XPATH_UNDEFINED:
1547: fprintf(stderr, "%s: no such node\n", arg);
1548: break;
1549: case XPATH_NODESET:
1550: if (list->nodesetval->nodeNr == 1) {
1551: ctxt->node = list->nodesetval->nodeTab[0];
1552: } else
1553: fprintf(stderr, "%s is a %d Node Set\n",
1554: arg, list->nodesetval->nodeNr);
1555: break;
1556: case XPATH_BOOLEAN:
1557: fprintf(stderr, "%s is a Boolean\n", arg);
1558: break;
1559: case XPATH_NUMBER:
1560: fprintf(stderr, "%s is a number\n", arg);
1561: break;
1562: case XPATH_STRING:
1563: fprintf(stderr, "%s is a string\n", arg);
1564: break;
1565: }
1566: xmlXPathFreeNodeSetList(list);
1567: } else {
1568: fprintf(stderr, "%s: no such node\n", arg);
1569: }
1570: if (ctxt->pctxt->nodelist != NULL)
1571: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1572: ctxt->pctxt->nodelist = NULL;
1573: }
1574: } else if (!strcmp(command, "cat")) {
1575: if (arg[0] == 0) {
1576: xmlShellCat(ctxt, NULL, ctxt->node, NULL);
1577: } else {
1578: ctxt->pctxt->node = ctxt->node;
1579: if (ctxt->pctxt->nodelist != NULL)
1580: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1581: ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
1582: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1583: if (list != NULL) {
1584: switch (list->type) {
1585: case XPATH_UNDEFINED:
1586: fprintf(stderr, "%s: no such node\n", arg);
1587: break;
1588: case XPATH_NODESET: {
1589: int i;
1590:
1591: for (i = 0;i < list->nodesetval->nodeNr;i++) {
1592: if (i > 0) printf(" -------\n");
1593: xmlShellCat(ctxt, NULL,
1594: list->nodesetval->nodeTab[i], NULL);
1595: }
1596: break;
1597: }
1598: case XPATH_BOOLEAN:
1599: fprintf(stderr, "%s is a Boolean\n", arg);
1600: break;
1601: case XPATH_NUMBER:
1602: fprintf(stderr, "%s is a number\n", arg);
1603: break;
1604: case XPATH_STRING:
1605: fprintf(stderr, "%s is a string\n", arg);
1606: break;
1607: }
1608: xmlXPathFreeNodeSetList(list);
1609: } else {
1610: fprintf(stderr, "%s: no such node\n", arg);
1611: }
1612: if (ctxt->pctxt->nodelist != NULL)
1613: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1614: ctxt->pctxt->nodelist = NULL;
1615: }
1616: } else {
1617: fprintf(stderr, "Unknown command %s\n", command);
1618: }
1619: free(cmdline); /* not xmlFree here ! */
1620: }
1621: xmlXPathFreeContext(ctxt->pctxt);
1622: if (ctxt->loaded) {
1623: xmlFreeDoc(ctxt->doc);
1624: }
1625: xmlFree(ctxt);
1626: if (cmdline != NULL)
1627: free(cmdline); /* not xmlFree here ! */
1628: }
1629:
Webmaster