Annotation of XML/debugXML.c, revision 1.25
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: }
676: if (doc->standalone)
677: fprintf(output, "standalone=true\n");
678: if (doc->oldNs != NULL)
679: xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
1.12 daniel 680: }
681:
682: void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
683: if (output == NULL) output = stdout;
684: if (doc == NULL) {
685: fprintf(output, "DOCUMENT == NULL !\n");
686: return;
687: }
688: xmlDebugDumpDocumentHead(output, doc);
689: if (((doc->type == XML_DOCUMENT_NODE) ||
690: (doc->type == XML_HTML_DOCUMENT_NODE)) &&
1.16 daniel 691: (doc->children != NULL))
692: xmlDebugDumpNodeList(output, doc->children, 1);
1.12 daniel 693: }
1.9 daniel 694:
695: void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
696: int i;
697: xmlEntityPtr cur;
698:
699: if (output == NULL) output = stdout;
700: if (doc == NULL) {
701: fprintf(output, "DOCUMENT == NULL !\n");
702: return;
703: }
704:
705: switch (doc->type) {
706: case XML_ELEMENT_NODE:
707: fprintf(output, "Error, ELEMENT found here ");
708: break;
709: case XML_ATTRIBUTE_NODE:
710: fprintf(output, "Error, ATTRIBUTE found here\n");
711: break;
712: case XML_TEXT_NODE:
713: fprintf(output, "Error, TEXT\n");
714: break;
715: case XML_CDATA_SECTION_NODE:
716: fprintf(output, "Error, CDATA_SECTION\n");
717: break;
718: case XML_ENTITY_REF_NODE:
719: fprintf(output, "Error, ENTITY_REF\n");
720: break;
721: case XML_ENTITY_NODE:
722: fprintf(output, "Error, ENTITY\n");
723: break;
724: case XML_PI_NODE:
725: fprintf(output, "Error, PI\n");
726: break;
727: case XML_COMMENT_NODE:
728: fprintf(output, "Error, COMMENT\n");
729: break;
730: case XML_DOCUMENT_NODE:
731: fprintf(output, "DOCUMENT\n");
732: break;
733: case XML_HTML_DOCUMENT_NODE:
734: fprintf(output, "HTML DOCUMENT\n");
735: break;
736: case XML_DOCUMENT_TYPE_NODE:
737: fprintf(output, "Error, DOCUMENT_TYPE\n");
738: break;
739: case XML_DOCUMENT_FRAG_NODE:
740: fprintf(output, "Error, DOCUMENT_FRAG\n");
741: break;
742: case XML_NOTATION_NODE:
743: fprintf(output, "Error, NOTATION\n");
744: break;
745: default:
746: fprintf(output, "NODE_%d\n", doc->type);
747: }
748: if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
749: xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
750: doc->intSubset->entities;
751: fprintf(output, "Entities in internal subset\n");
752: for (i = 0;i < table->nb_entities;i++) {
1.20 daniel 753: cur = table->table[i];
1.9 daniel 754: fprintf(output, "%d : %s : ", i, cur->name);
1.19 daniel 755: switch (cur->etype) {
1.9 daniel 756: case XML_INTERNAL_GENERAL_ENTITY:
1.22 daniel 757: fprintf(output, "INTERNAL GENERAL, ");
1.9 daniel 758: break;
759: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1.22 daniel 760: fprintf(output, "EXTERNAL PARSED, ");
1.9 daniel 761: break;
762: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.22 daniel 763: fprintf(output, "EXTERNAL UNPARSED, ");
1.9 daniel 764: break;
765: case XML_INTERNAL_PARAMETER_ENTITY:
1.22 daniel 766: fprintf(output, "INTERNAL PARAMETER, ");
1.9 daniel 767: break;
768: case XML_EXTERNAL_PARAMETER_ENTITY:
1.22 daniel 769: fprintf(output, "EXTERNAL PARAMETER, ");
1.9 daniel 770: break;
771: default:
772: fprintf(output, "UNKNOWN TYPE %d",
1.19 daniel 773: cur->etype);
1.9 daniel 774: }
775: if (cur->ExternalID != NULL)
776: fprintf(output, "ID \"%s\"", cur->ExternalID);
777: if (cur->SystemID != NULL)
778: fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
779: if (cur->orig != NULL)
780: fprintf(output, "\n orig \"%s\"", cur->orig);
781: if (cur->content != NULL)
782: fprintf(output, "\n content \"%s\"", cur->content);
783: fprintf(output, "\n");
784: }
785: } else
786: fprintf(output, "No entities in internal subset\n");
787: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
788: xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
789: doc->extSubset->entities;
790: fprintf(output, "Entities in external subset\n");
791: for (i = 0;i < table->nb_entities;i++) {
1.20 daniel 792: cur = table->table[i];
1.9 daniel 793: fprintf(output, "%d : %s : ", i, cur->name);
1.19 daniel 794: switch (cur->etype) {
1.9 daniel 795: case XML_INTERNAL_GENERAL_ENTITY:
1.22 daniel 796: fprintf(output, "INTERNAL GENERAL, ");
1.9 daniel 797: break;
798: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1.22 daniel 799: fprintf(output, "EXTERNAL PARSED, ");
1.9 daniel 800: break;
801: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.22 daniel 802: fprintf(output, "EXTERNAL UNPARSED, ");
1.9 daniel 803: break;
804: case XML_INTERNAL_PARAMETER_ENTITY:
1.22 daniel 805: fprintf(output, "INTERNAL PARAMETER, ");
1.9 daniel 806: break;
807: case XML_EXTERNAL_PARAMETER_ENTITY:
1.22 daniel 808: fprintf(output, "EXTERNAL PARAMETER, ");
1.9 daniel 809: break;
810: default:
811: fprintf(output, "UNKNOWN TYPE %d",
1.19 daniel 812: cur->etype);
1.9 daniel 813: }
814: if (cur->ExternalID != NULL)
815: fprintf(output, "ID \"%s\"", cur->ExternalID);
816: if (cur->SystemID != NULL)
817: fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
818: if (cur->orig != NULL)
819: fprintf(output, "\n orig \"%s\"", cur->orig);
820: if (cur->content != NULL)
821: fprintf(output, "\n content \"%s\"", cur->content);
822: fprintf(output, "\n");
823: }
824: } else
825: fprintf(output, "No entities in external subset\n");
826: }
1.12 daniel 827:
828: static int xmlLsCountNode(xmlNodePtr node) {
829: int ret = 0;
830: xmlNodePtr list = NULL;
831:
832: switch (node->type) {
833: case XML_ELEMENT_NODE:
1.16 daniel 834: list = node->children;
1.12 daniel 835: break;
836: case XML_DOCUMENT_NODE:
837: case XML_HTML_DOCUMENT_NODE:
1.16 daniel 838: list = ((xmlDocPtr) node)->children;
1.12 daniel 839: break;
840: case XML_ATTRIBUTE_NODE:
1.16 daniel 841: list = ((xmlAttrPtr) node)->children;
1.12 daniel 842: break;
843: case XML_TEXT_NODE:
844: case XML_CDATA_SECTION_NODE:
845: case XML_PI_NODE:
846: case XML_COMMENT_NODE:
847: if (node->content != NULL) {
848: #ifndef XML_USE_BUFFER_CONTENT
849: ret = xmlStrlen(node->content);
850: #else
851: ret = xmlBufferLength(node->content);
852: #endif
853: }
854: break;
855: case XML_ENTITY_REF_NODE:
856: case XML_DOCUMENT_TYPE_NODE:
857: case XML_ENTITY_NODE:
858: case XML_DOCUMENT_FRAG_NODE:
859: case XML_NOTATION_NODE:
1.16 daniel 860: case XML_DTD_NODE:
1.17 daniel 861: case XML_ELEMENT_DECL:
862: case XML_ATTRIBUTE_DECL:
1.20 daniel 863: case XML_ENTITY_DECL:
1.12 daniel 864: ret = 1;
865: break;
866: }
867: for (;list != NULL;ret++)
868: list = list->next;
869: return(ret);
870: }
871:
872: void xmlLsOneNode(FILE *output, xmlNodePtr node) {
873: switch (node->type) {
874: case XML_ELEMENT_NODE:
875: fprintf(output, "-");
876: break;
877: case XML_ATTRIBUTE_NODE:
878: fprintf(output, "a");
879: break;
880: case XML_TEXT_NODE:
881: fprintf(output, "t");
882: break;
883: case XML_CDATA_SECTION_NODE:
884: fprintf(output, "c");
885: break;
886: case XML_ENTITY_REF_NODE:
887: fprintf(output, "e");
888: break;
889: case XML_ENTITY_NODE:
890: fprintf(output, "E");
891: break;
892: case XML_PI_NODE:
893: fprintf(output, "p");
894: break;
895: case XML_COMMENT_NODE:
896: fprintf(output, "c");
897: break;
898: case XML_DOCUMENT_NODE:
899: fprintf(output, "d");
900: break;
901: case XML_HTML_DOCUMENT_NODE:
902: fprintf(output, "h");
903: break;
904: case XML_DOCUMENT_TYPE_NODE:
905: fprintf(output, "T");
906: break;
907: case XML_DOCUMENT_FRAG_NODE:
908: fprintf(output, "F");
909: break;
910: case XML_NOTATION_NODE:
911: fprintf(output, "N");
912: break;
913: default:
914: fprintf(output, "?");
915: }
916: if (node->properties != NULL)
917: fprintf(output, "a");
918: else
919: fprintf(output, "-");
920: if (node->nsDef != NULL)
921: fprintf(output, "n");
922: else
923: fprintf(output, "-");
924:
925: fprintf(output, " %8d ", xmlLsCountNode(node));
926:
927: switch (node->type) {
928: case XML_ELEMENT_NODE:
929: if (node->name != NULL)
930: fprintf(output, "%s", node->name);
931: break;
932: case XML_ATTRIBUTE_NODE:
933: if (node->name != NULL)
934: fprintf(output, "%s", node->name);
935: break;
936: case XML_TEXT_NODE:
937: if (node->content != NULL) {
938: #ifndef XML_USE_BUFFER_CONTENT
939: xmlDebugDumpString(output, node->content);
940: #else
941: xmlDebugDumpString(output, xmlBufferContent(node->content));
942: #endif
943: }
944: break;
945: case XML_CDATA_SECTION_NODE:
946: break;
947: case XML_ENTITY_REF_NODE:
948: if (node->name != NULL)
949: fprintf(output, "%s", node->name);
950: break;
951: case XML_ENTITY_NODE:
952: if (node->name != NULL)
953: fprintf(output, "%s", node->name);
954: break;
955: case XML_PI_NODE:
956: if (node->name != NULL)
957: fprintf(output, "%s", node->name);
958: break;
959: case XML_COMMENT_NODE:
960: break;
961: case XML_DOCUMENT_NODE:
962: break;
963: case XML_HTML_DOCUMENT_NODE:
964: break;
965: case XML_DOCUMENT_TYPE_NODE:
966: break;
967: case XML_DOCUMENT_FRAG_NODE:
968: break;
969: case XML_NOTATION_NODE:
970: break;
971: default:
972: if (node->name != NULL)
973: fprintf(output, "%s", node->name);
974: }
975: fprintf(output, "\n");
976: }
977:
978: /****************************************************************
979: * *
980: * The XML shell related functions *
981: * *
982: ****************************************************************/
983:
984: /*
985: * TODO: Improvement/cleanups for the XML shell
986: * - allow to shell out an editor on a subpart
987: * - cleanup function registrations (with help) and calling
988: * - provide registration routines
989: */
990:
991: /**
992: * xmlShellList:
993: * @ctxt: the shell context
994: * @arg: unused
995: * @node: a node
996: * @node2: unused
997: *
998: * Implements the XML shell function "ls"
999: * Does an Unix like listing of the given node (like a directory)
1000: *
1001: * Returns 0
1002: */
1003: int
1004: xmlShellList(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
1005: xmlNodePtr node2) {
1006: xmlNodePtr cur;
1007:
1008: if ((node->type == XML_DOCUMENT_NODE) ||
1009: (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16 daniel 1010: cur = ((xmlDocPtr) node)->children;
1011: } else if (node->children != NULL) {
1012: cur = node->children;
1.12 daniel 1013: } else {
1014: xmlLsOneNode(stdout, node);
1015: return(0);
1016: }
1017: while (cur != NULL) {
1018: xmlLsOneNode(stdout, cur);
1019: cur = cur->next;
1020: }
1021: return(0);
1022: }
1023:
1024: /**
1025: * xmlShellDir:
1026: * @ctxt: the shell context
1027: * @arg: unused
1028: * @node: a node
1029: * @node2: unused
1030: *
1031: * Implements the XML shell function "dir"
1032: * dumps informations about the node (namespace, attributes, content).
1033: *
1034: * Returns 0
1035: */
1036: int
1037: xmlShellDir(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
1038: xmlNodePtr node2) {
1039: if ((node->type == XML_DOCUMENT_NODE) ||
1040: (node->type == XML_HTML_DOCUMENT_NODE)) {
1041: xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
1042: } else if (node->type == XML_ATTRIBUTE_NODE) {
1043: xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
1044: } else {
1045: xmlDebugDumpOneNode(stdout, node, 0);
1046: }
1047: return(0);
1048: }
1049:
1050: /**
1051: * xmlShellCat:
1052: * @ctxt: the shell context
1053: * @arg: unused
1054: * @node: a node
1055: * @node2: unused
1056: *
1057: * Implements the XML shell function "cat"
1058: * dumps the serialization node content (XML or HTML).
1059: *
1060: * Returns 0
1061: */
1062: int
1063: xmlShellCat(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
1064: xmlNodePtr node2) {
1.13 daniel 1065: if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1.23 daniel 1066: #ifdef LIBXML_HTML_ENABLED
1.13 daniel 1067: if (node->type == XML_HTML_DOCUMENT_NODE)
1068: htmlDocDump(stdout, (htmlDocPtr) node);
1069: else
1.14 daniel 1070: htmlNodeDumpFile(stdout, ctxt->doc, node);
1.23 daniel 1071: #else
1072: if (node->type == XML_DOCUMENT_NODE)
1073: xmlDocDump(stdout, (xmlDocPtr) node);
1074: else
1075: xmlElemDump(stdout, ctxt->doc, node);
1076: #endif /* LIBXML_HTML_ENABLED */
1.13 daniel 1077: } else {
1078: if (node->type == XML_DOCUMENT_NODE)
1079: xmlDocDump(stdout, (xmlDocPtr) node);
1080: else
1081: xmlElemDump(stdout, ctxt->doc, node);
1082: }
1.12 daniel 1083: printf("\n");
1084: return(0);
1085: }
1086:
1087: /**
1088: * xmlShellLoad:
1089: * @ctxt: the shell context
1090: * @filename: the file name
1091: * @node: unused
1092: * @node2: unused
1093: *
1094: * Implements the XML shell function "load"
1095: * loads a new document specified by the filename
1096: *
1097: * Returns 0 or -1 if loading failed
1098: */
1099: int
1100: xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1101: xmlNodePtr node2) {
1102: xmlDocPtr doc;
1103: int html = 0;
1104:
1105: if (ctxt->doc != NULL)
1106: html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
1107:
1108: if (html) {
1.23 daniel 1109: #ifdef LIBXML_HTML_ENABLED
1.12 daniel 1110: doc = htmlParseFile(filename, NULL);
1.23 daniel 1111: #else
1112: printf("HTML support not compiled in\n");
1113: doc = NULL;
1114: #endif /* LIBXML_HTML_ENABLED */
1.12 daniel 1115: } else {
1116: doc = xmlParseFile(filename);
1117: }
1118: if (doc != NULL) {
1119: if (ctxt->loaded == 1) {
1120: xmlFreeDoc(ctxt->doc);
1121: }
1122: ctxt->loaded = 1;
1.23 daniel 1123: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1124: xmlXPathFreeContext(ctxt->pctxt);
1.23 daniel 1125: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1126: xmlFree(ctxt->filename);
1127: ctxt->doc = doc;
1128: ctxt->node = (xmlNodePtr) doc;
1.23 daniel 1129: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1130: ctxt->pctxt = xmlXPathNewContext(doc);
1.23 daniel 1131: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1132: ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1133: } else
1134: return(-1);
1135: return(0);
1136: }
1137:
1138: /**
1139: * xmlShellWrite:
1140: * @ctxt: the shell context
1141: * @filename: the file name
1142: * @node: a node in the tree
1143: * @node2: unused
1144: *
1145: * Implements the XML shell function "write"
1146: * Write the current node to the filename, it saves the serailization
1147: * of the subtree under the @node specified
1148: *
1149: * Returns 0 or -1 in case of error
1150: */
1151: int
1152: xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1153: xmlNodePtr node2) {
1154: if (node == NULL)
1155: return(-1);
1156: if ((filename == NULL) || (filename[0] == 0)) {
1157: fprintf(stderr, "Write command requires a filename argument\n");
1158: return(-1);
1159: }
1160: #ifdef W_OK
1161: if (access((char *) filename, W_OK)) {
1162: fprintf(stderr, "Cannot write to %s\n", filename);
1163: return(-1);
1164: }
1165: #endif
1166: switch(node->type) {
1167: case XML_DOCUMENT_NODE:
1168: if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1169: fprintf(stderr, "Failed to write to %s\n", filename);
1170: return(-1);
1171: }
1172: break;
1173: case XML_HTML_DOCUMENT_NODE:
1.23 daniel 1174: #ifdef LIBXML_HTML_ENABLED
1.12 daniel 1175: if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1176: fprintf(stderr, "Failed to write to %s\n", filename);
1177: return(-1);
1178: }
1.23 daniel 1179: #else
1180: if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1181: fprintf(stderr, "Failed to write to %s\n", filename);
1182: return(-1);
1183: }
1184: #endif /* LIBXML_HTML_ENABLED */
1.12 daniel 1185: break;
1186: default: {
1187: FILE *f;
1188:
1189: f = fopen((char *) filename, "w");
1190: if (f == NULL) {
1191: fprintf(stderr, "Failed to write to %s\n", filename);
1192: return(-1);
1193: }
1194: xmlElemDump(f, ctxt->doc, node);
1195: fclose(f);
1196: }
1197: }
1198: return(0);
1199: }
1200:
1201: /**
1202: * xmlShellSave:
1203: * @ctxt: the shell context
1204: * @filename: the file name (optionnal)
1205: * @node: unused
1206: * @node2: unused
1207: *
1208: * Implements the XML shell function "save"
1209: * Write the current document to the filename, or it's original name
1210: *
1211: * Returns 0 or -1 in case of error
1212: */
1213: int
1214: xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1215: xmlNodePtr node2) {
1216: if (ctxt->doc == NULL)
1217: return(-1);
1218: if ((filename == NULL) || (filename[0] == 0))
1219: filename = ctxt->filename;
1220: #ifdef W_OK
1221: if (access((char *) filename, W_OK)) {
1222: fprintf(stderr, "Cannot save to %s\n", filename);
1223: return(-1);
1224: }
1225: #endif
1226: switch(ctxt->doc->type) {
1227: case XML_DOCUMENT_NODE:
1228: if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1229: fprintf(stderr, "Failed to save to %s\n", filename);
1230: }
1231: break;
1232: case XML_HTML_DOCUMENT_NODE:
1.23 daniel 1233: #ifdef LIBXML_HTML_ENABLED
1.12 daniel 1234: if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1235: fprintf(stderr, "Failed to save to %s\n", filename);
1236: }
1.23 daniel 1237: #else
1238: if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1239: fprintf(stderr, "Failed to save to %s\n", filename);
1240: }
1241: #endif /* LIBXML_HTML_ENABLED */
1.12 daniel 1242: break;
1243: default:
1244: fprintf(stderr,
1245: "To save to subparts of a document use the 'write' command\n");
1246: return(-1);
1247:
1248: }
1249: return(0);
1250: }
1251:
1252: /**
1253: * xmlShellValidate:
1254: * @ctxt: the shell context
1255: * @dtd: the DTD URI (optionnal)
1256: * @node: unused
1257: * @node2: unused
1258: *
1259: * Implements the XML shell function "validate"
1260: * Validate the document, if a DTD path is provided, then the validation
1261: * is done against the given DTD.
1262: *
1263: * Returns 0 or -1 in case of error
1264: */
1265: int
1266: xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node,
1267: xmlNodePtr node2) {
1268: xmlValidCtxt vctxt;
1269: int res = -1;
1270:
1271: vctxt.userData = stderr;
1272: vctxt.error = (xmlValidityErrorFunc) fprintf;
1273: vctxt.warning = (xmlValidityWarningFunc) fprintf;
1274:
1275: if ((dtd == NULL) || (dtd[0] == 0)) {
1276: res = xmlValidateDocument(&vctxt, ctxt->doc);
1277: } else {
1278: xmlDtdPtr subset;
1279:
1280: subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1281: if (subset != NULL) {
1282: res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1283:
1284: xmlFreeDtd(subset);
1285: }
1286: }
1287: return(res);
1288: }
1289:
1290: /**
1291: * xmlShellDu:
1292: * @ctxt: the shell context
1293: * @arg: unused
1294: * @tree: a node defining a subtree
1295: * @node2: unused
1296: *
1297: * Implements the XML shell function "du"
1298: * show the structure of the subtree under node @tree
1299: * If @tree is null, the command works on the current node.
1300: *
1301: * Returns 0 or -1 in case of error
1302: */
1303: int
1304: xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
1305: xmlNodePtr node2) {
1306: xmlNodePtr node;
1307: int indent = 0,i;
1308:
1309: if (tree == NULL) return(-1);
1310: node = tree;
1311: while (node != NULL) {
1312: if ((node->type == XML_DOCUMENT_NODE) ||
1313: (node->type == XML_HTML_DOCUMENT_NODE)) {
1314: printf("/\n");
1315: } else if (node->type == XML_ELEMENT_NODE) {
1316: for (i = 0;i < indent;i++)
1317: printf(" ");
1318: printf("%s\n", node->name);
1319: } else {
1320: }
1321:
1322: /*
1323: * Browse the full subtree, deep first
1324: */
1325:
1326: if ((node->type == XML_DOCUMENT_NODE) ||
1327: (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16 daniel 1328: node = ((xmlDocPtr) node)->children;
1.25 ! daniel 1329: } else if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1.12 daniel 1330: /* deep first */
1.16 daniel 1331: node = node->children;
1.12 daniel 1332: indent++;
1333: } else if ((node != tree) && (node->next != NULL)) {
1334: /* then siblings */
1335: node = node->next;
1336: } else if (node != tree) {
1337: /* go up to parents->next if needed */
1338: while (node != tree) {
1339: if (node->parent != NULL) {
1340: node = node->parent;
1341: indent--;
1342: }
1343: if ((node != tree) && (node->next != NULL)) {
1344: node = node->next;
1345: break;
1346: }
1347: if (node->parent == NULL) {
1348: node = NULL;
1349: break;
1350: }
1351: if (node == tree) {
1352: node = NULL;
1353: break;
1354: }
1355: }
1356: /* exit condition */
1357: if (node == tree)
1358: node = NULL;
1359: } else
1360: node = NULL;
1361: }
1362: return(0);
1363: }
1364:
1365: /**
1366: * xmlShellPwd:
1367: * @ctxt: the shell context
1368: * @buffer: the output buffer
1369: * @tree: a node
1370: * @node2: unused
1371: *
1372: * Implements the XML shell function "pwd"
1373: * Show the full path from the root to the node, if needed building
1374: * thumblers when similar elements exists at a given ancestor level.
1375: * The output is compatible with XPath commands.
1376: *
1377: * Returns 0 or -1 in case of error
1378: */
1379: int
1380: xmlShellPwd(xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node,
1381: xmlNodePtr node2) {
1382: xmlNodePtr cur, tmp, next;
1383: char buf[500];
1384: char sep;
1385: const char *name;
1386: int occur = 0;
1387:
1388: buffer[0] = 0;
1389: if (node == NULL) return(-1);
1390: cur = node;
1391: do {
1392: name = "";
1393: sep= '?';
1394: occur = 0;
1395: if ((cur->type == XML_DOCUMENT_NODE) ||
1396: (cur->type == XML_HTML_DOCUMENT_NODE)) {
1397: sep = '/';
1398: next = NULL;
1399: } else if (cur->type == XML_ELEMENT_NODE) {
1400: sep = '/';
1401: name = (const char *)cur->name;
1402: next = cur->parent;
1403:
1404: /*
1405: * Thumbler index computation
1406: */
1407: tmp = cur->prev;
1408: while (tmp != NULL) {
1409: if (!xmlStrcmp(cur->name, tmp->name))
1410: occur++;
1411: tmp = tmp->prev;
1412: }
1413: if (occur == 0) {
1414: tmp = cur->next;
1415: while (tmp != NULL) {
1416: if (!xmlStrcmp(cur->name, tmp->name))
1417: occur++;
1418: tmp = tmp->next;
1419: }
1420: if (occur != 0) occur = 1;
1421: } else
1422: occur++;
1423: } else if (cur->type == XML_ATTRIBUTE_NODE) {
1424: sep = '@';
1425: name = (const char *) (((xmlAttrPtr) cur)->name);
1.16 daniel 1426: next = ((xmlAttrPtr) cur)->parent;
1.12 daniel 1427: } else {
1428: next = cur->parent;
1429: }
1430: if (occur == 0)
1431: sprintf(buf, "%c%s%s", sep, name, buffer);
1432: else
1433: sprintf(buf, "%c%s[%d]%s", sep, name, occur, buffer);
1434: strcpy(buffer, buf);
1435: cur = next;
1436: } while (cur != NULL);
1437: return(0);
1438: }
1439:
1440: /**
1441: * xmlShell
1442: * @doc: the initial document
1443: * @filename: the output buffer
1444: * @input: the line reading function
1445: * @output: the output FILE*
1446: *
1447: * Implements the XML shell
1448: * This allow to load, validate, view, modify and save a document
1449: * using a environment similar to a UNIX commandline.
1450: */
1451: void
1452: xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
1453: FILE *output) {
1454: char prompt[500] = "/ > ";
1455: char *cmdline = NULL;
1456: int nbargs;
1457: char command[100];
1458: char arg[400];
1459: xmlShellCtxtPtr ctxt;
1460: xmlXPathObjectPtr list;
1461:
1462: if (doc == NULL)
1463: return;
1464: if (filename == NULL)
1465: return;
1466: if (input == NULL)
1467: return;
1468: if (output == NULL)
1469: return;
1470: ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
1471: if (ctxt == NULL)
1472: return;
1473: ctxt->loaded = 0;
1474: ctxt->doc = doc;
1475: ctxt->input = input;
1476: ctxt->output = output;
1477: ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1478: ctxt->node = (xmlNodePtr) ctxt->doc;
1479:
1.23 daniel 1480: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1481: ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
1482: if (ctxt->pctxt == NULL) {
1483: xmlFree(ctxt);
1484: return;
1485: }
1.23 daniel 1486: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1487: while (1) {
1488: if (ctxt->node == (xmlNodePtr) ctxt->doc)
1489: sprintf(prompt, "%s > ", "/");
1490: else if (ctxt->node->name)
1491: sprintf(prompt, "%s > ", ctxt->node->name);
1492: else
1493: sprintf(prompt, "? > ");
1494:
1495: cmdline = ctxt->input(prompt);
1496: if (cmdline == NULL) break;
1497:
1498: command[0] = 0;
1499: arg[0] = 0;
1500: nbargs = sscanf(cmdline, "%s %s", command, arg);
1501:
1502: if (command[0] == 0) continue;
1503: if (!strcmp(command, "exit"))
1504: break;
1505: if (!strcmp(command, "quit"))
1506: break;
1507: if (!strcmp(command, "bye"))
1508: break;
1509: if (!strcmp(command, "validate")) {
1510: xmlShellValidate(ctxt, arg, NULL, NULL);
1511: } else if (!strcmp(command, "load")) {
1512: xmlShellLoad(ctxt, arg, NULL, NULL);
1513: } else if (!strcmp(command, "save")) {
1514: xmlShellSave(ctxt, arg, NULL, NULL);
1515: } else if (!strcmp(command, "write")) {
1516: xmlShellWrite(ctxt, arg, NULL, NULL);
1517: } else if (!strcmp(command, "free")) {
1518: if (arg[0] == 0) {
1519: xmlMemShow(stdout, 0);
1520: } else {
1521: int len = 0;
1522: sscanf(arg, "%d", &len);
1523: xmlMemShow(stdout, len);
1524: }
1525: } else if (!strcmp(command, "pwd")) {
1526: char dir[500];
1527: if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
1528: printf("%s\n", dir);
1529: } else if (!strcmp(command, "du")) {
1530: xmlShellDu(ctxt, NULL, ctxt->node, NULL);
1531: } else if ((!strcmp(command, "ls")) ||
1532: (!strcmp(command, "dir"))) {
1533: int dir = (!strcmp(command, "dir"));
1534: if (arg[0] == 0) {
1535: if (dir)
1536: xmlShellDir(ctxt, NULL, ctxt->node, NULL);
1537: else
1538: xmlShellList(ctxt, NULL, ctxt->node, NULL);
1539: } else {
1540: ctxt->pctxt->node = ctxt->node;
1.23 daniel 1541: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1542: if (ctxt->pctxt->nodelist != NULL)
1543: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1544: ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
1545: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23 daniel 1546: #else
1547: list = NULL;
1548: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1549: if (list != NULL) {
1550: switch (list->type) {
1551: case XPATH_UNDEFINED:
1552: fprintf(stderr, "%s: no such node\n", arg);
1553: break;
1554: case XPATH_NODESET: {
1555: int i;
1556:
1557: for (i = 0;i < list->nodesetval->nodeNr;i++) {
1558: if (dir)
1559: xmlShellDir(ctxt, NULL,
1560: list->nodesetval->nodeTab[i], NULL);
1561: else
1562: xmlShellList(ctxt, NULL,
1563: list->nodesetval->nodeTab[i], NULL);
1564: }
1565: break;
1566: }
1567: case XPATH_BOOLEAN:
1568: fprintf(stderr, "%s is a Boolean\n", arg);
1569: break;
1570: case XPATH_NUMBER:
1571: fprintf(stderr, "%s is a number\n", arg);
1572: break;
1573: case XPATH_STRING:
1574: fprintf(stderr, "%s is a string\n", arg);
1575: break;
1576: }
1577: xmlXPathFreeNodeSetList(list);
1578: } else {
1579: fprintf(stderr, "%s: no such node\n", arg);
1580: }
1.23 daniel 1581: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1582: if (ctxt->pctxt->nodelist != NULL)
1583: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1.23 daniel 1584: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1585: ctxt->pctxt->nodelist = NULL;
1586: }
1587: } else if (!strcmp(command, "cd")) {
1588: if (arg[0] == 0) {
1589: ctxt->node = (xmlNodePtr) ctxt->doc;
1590: } else {
1591: ctxt->pctxt->node = ctxt->node;
1.23 daniel 1592: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1593: if (ctxt->pctxt->nodelist != NULL)
1594: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1595: ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
1596: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23 daniel 1597: #else
1598: list = NULL;
1599: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1600: if (list != NULL) {
1601: switch (list->type) {
1602: case XPATH_UNDEFINED:
1603: fprintf(stderr, "%s: no such node\n", arg);
1604: break;
1605: case XPATH_NODESET:
1606: if (list->nodesetval->nodeNr == 1) {
1607: ctxt->node = list->nodesetval->nodeTab[0];
1608: } else
1609: fprintf(stderr, "%s is a %d Node Set\n",
1610: arg, list->nodesetval->nodeNr);
1611: break;
1612: case XPATH_BOOLEAN:
1613: fprintf(stderr, "%s is a Boolean\n", arg);
1614: break;
1615: case XPATH_NUMBER:
1616: fprintf(stderr, "%s is a number\n", arg);
1617: break;
1618: case XPATH_STRING:
1619: fprintf(stderr, "%s is a string\n", arg);
1620: break;
1621: }
1622: xmlXPathFreeNodeSetList(list);
1623: } else {
1624: fprintf(stderr, "%s: no such node\n", arg);
1625: }
1.23 daniel 1626: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1627: if (ctxt->pctxt->nodelist != NULL)
1628: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1.23 daniel 1629: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1630: ctxt->pctxt->nodelist = NULL;
1631: }
1632: } else if (!strcmp(command, "cat")) {
1633: if (arg[0] == 0) {
1634: xmlShellCat(ctxt, NULL, ctxt->node, NULL);
1635: } else {
1636: ctxt->pctxt->node = ctxt->node;
1.23 daniel 1637: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1638: if (ctxt->pctxt->nodelist != NULL)
1639: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1640: ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
1641: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23 daniel 1642: #else
1643: list = NULL;
1644: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1645: if (list != NULL) {
1646: switch (list->type) {
1647: case XPATH_UNDEFINED:
1648: fprintf(stderr, "%s: no such node\n", arg);
1649: break;
1650: case XPATH_NODESET: {
1651: int i;
1652:
1653: for (i = 0;i < list->nodesetval->nodeNr;i++) {
1654: if (i > 0) printf(" -------\n");
1655: xmlShellCat(ctxt, NULL,
1656: list->nodesetval->nodeTab[i], NULL);
1657: }
1658: break;
1659: }
1660: case XPATH_BOOLEAN:
1661: fprintf(stderr, "%s is a Boolean\n", arg);
1662: break;
1663: case XPATH_NUMBER:
1664: fprintf(stderr, "%s is a number\n", arg);
1665: break;
1666: case XPATH_STRING:
1667: fprintf(stderr, "%s is a string\n", arg);
1668: break;
1669: }
1670: xmlXPathFreeNodeSetList(list);
1671: } else {
1672: fprintf(stderr, "%s: no such node\n", arg);
1673: }
1.23 daniel 1674: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1675: if (ctxt->pctxt->nodelist != NULL)
1676: xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1.23 daniel 1677: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1678: ctxt->pctxt->nodelist = NULL;
1679: }
1680: } else {
1681: fprintf(stderr, "Unknown command %s\n", command);
1682: }
1683: free(cmdline); /* not xmlFree here ! */
1684: }
1.23 daniel 1685: #ifdef LIBXML_XPATH_ENABLED
1.12 daniel 1686: xmlXPathFreeContext(ctxt->pctxt);
1.23 daniel 1687: #endif /* LIBXML_XPATH_ENABLED */
1.12 daniel 1688: if (ctxt->loaded) {
1689: xmlFreeDoc(ctxt->doc);
1690: }
1691: xmlFree(ctxt);
1692: if (cmdline != NULL)
1693: free(cmdline); /* not xmlFree here ! */
1694: }
1695:
1.23 daniel 1696: #endif /* LIBXML_DEBUG_ENABLED */
Webmaster