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