Annotation of embedaddon/libxml2/debugXML.c, revision 1.1.1.3
1.1 misho 1: /*
2: * debugXML.c : This is a set of routines used for debugging the tree
3: * produced by the XML parser.
4: *
5: * See Copyright for the status of this software.
6: *
7: * Daniel Veillard <daniel@veillard.com>
8: */
9:
10: #define IN_LIBXML
11: #include "libxml.h"
12: #ifdef LIBXML_DEBUG_ENABLED
13:
14: #include <string.h>
15: #ifdef HAVE_STDLIB_H
16: #include <stdlib.h>
17: #endif
18: #ifdef HAVE_STRING_H
19: #include <string.h>
20: #endif
21: #include <libxml/xmlmemory.h>
22: #include <libxml/tree.h>
23: #include <libxml/parser.h>
24: #include <libxml/parserInternals.h>
25: #include <libxml/valid.h>
26: #include <libxml/debugXML.h>
27: #include <libxml/HTMLtree.h>
28: #include <libxml/HTMLparser.h>
29: #include <libxml/xmlerror.h>
30: #include <libxml/globals.h>
31: #include <libxml/xpathInternals.h>
32: #include <libxml/uri.h>
33: #ifdef LIBXML_SCHEMAS_ENABLED
34: #include <libxml/relaxng.h>
35: #endif
36:
37: #define DUMP_TEXT_TYPE 1
38:
39: typedef struct _xmlDebugCtxt xmlDebugCtxt;
40: typedef xmlDebugCtxt *xmlDebugCtxtPtr;
41: struct _xmlDebugCtxt {
42: FILE *output; /* the output file */
43: char shift[101]; /* used for indenting */
44: int depth; /* current depth */
45: xmlDocPtr doc; /* current document */
46: xmlNodePtr node; /* current node */
47: xmlDictPtr dict; /* the doc dictionnary */
48: int check; /* do just checkings */
49: int errors; /* number of errors found */
50: int nodict; /* if the document has no dictionnary */
51: int options; /* options */
52: };
53:
54: static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
55:
56: static void
57: xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt)
58: {
59: int i;
60:
61: ctxt->depth = 0;
62: ctxt->check = 0;
63: ctxt->errors = 0;
64: ctxt->output = stdout;
65: ctxt->doc = NULL;
66: ctxt->node = NULL;
67: ctxt->dict = NULL;
68: ctxt->nodict = 0;
69: ctxt->options = 0;
70: for (i = 0; i < 100; i++)
71: ctxt->shift[i] = ' ';
72: ctxt->shift[100] = 0;
73: }
74:
75: static void
76: xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
77: {
78: /* remove the ATTRIBUTE_UNUSED when this is added */
79: }
80:
81: /**
82: * xmlNsCheckScope:
83: * @node: the node
84: * @ns: the namespace node
85: *
86: * Check that a given namespace is in scope on a node.
87: *
1.1.1.3 ! misho 88: * Returns 1 if in scope, -1 in case of argument error,
1.1 misho 89: * -2 if the namespace is not in scope, and -3 if not on
90: * an ancestor node.
91: */
92: static int
93: xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
94: {
95: xmlNsPtr cur;
96:
97: if ((node == NULL) || (ns == NULL))
98: return(-1);
99:
100: if ((node->type != XML_ELEMENT_NODE) &&
101: (node->type != XML_ATTRIBUTE_NODE) &&
102: (node->type != XML_DOCUMENT_NODE) &&
103: (node->type != XML_TEXT_NODE) &&
104: (node->type != XML_HTML_DOCUMENT_NODE) &&
105: (node->type != XML_XINCLUDE_START))
106: return(-2);
107:
108: while ((node != NULL) &&
109: ((node->type == XML_ELEMENT_NODE) ||
110: (node->type == XML_ATTRIBUTE_NODE) ||
111: (node->type == XML_TEXT_NODE) ||
112: (node->type == XML_XINCLUDE_START))) {
113: if ((node->type == XML_ELEMENT_NODE) ||
114: (node->type == XML_XINCLUDE_START)) {
115: cur = node->nsDef;
116: while (cur != NULL) {
117: if (cur == ns)
118: return(1);
119: if (xmlStrEqual(cur->prefix, ns->prefix))
120: return(-2);
121: cur = cur->next;
122: }
123: }
124: node = node->parent;
125: }
126: /* the xml namespace may be declared on the document node */
127: if ((node != NULL) &&
128: ((node->type == XML_DOCUMENT_NODE) ||
129: (node->type == XML_HTML_DOCUMENT_NODE))) {
130: xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
131: if (oldNs == ns)
132: return(1);
133: }
134: return(-3);
135: }
136:
137: static void
138: xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
139: {
140: if (ctxt->check)
141: return;
142: if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
143: if (ctxt->depth < 50)
144: fprintf(ctxt->output, "%s", &ctxt->shift[100 - 2 * ctxt->depth]);
145: else
146: fprintf(ctxt->output, "%s", ctxt->shift);
147: }
148: }
149:
150: /**
151: * xmlDebugErr:
152: * @ctxt: a debug context
153: * @error: the error code
154: *
155: * Handle a debug error.
156: */
157: static void
158: xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
159: {
160: ctxt->errors++;
161: __xmlRaiseError(NULL, NULL, NULL,
162: NULL, ctxt->node, XML_FROM_CHECK,
163: error, XML_ERR_ERROR, NULL, 0,
164: NULL, NULL, NULL, 0, 0,
165: "%s", msg);
166: }
167: static void
168: xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
169: {
170: ctxt->errors++;
171: __xmlRaiseError(NULL, NULL, NULL,
172: NULL, ctxt->node, XML_FROM_CHECK,
173: error, XML_ERR_ERROR, NULL, 0,
174: NULL, NULL, NULL, 0, 0,
175: msg, extra);
176: }
177: static void
178: xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
179: {
180: ctxt->errors++;
181: __xmlRaiseError(NULL, NULL, NULL,
182: NULL, ctxt->node, XML_FROM_CHECK,
183: error, XML_ERR_ERROR, NULL, 0,
184: NULL, NULL, NULL, 0, 0,
185: msg, extra);
186: }
187:
188: /**
189: * xmlCtxtNsCheckScope:
190: * @ctxt: the debugging context
191: * @node: the node
192: * @ns: the namespace node
193: *
194: * Report if a given namespace is is not in scope.
195: */
196: static void
197: xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
198: {
199: int ret;
200:
201: ret = xmlNsCheckScope(node, ns);
202: if (ret == -2) {
203: if (ns->prefix == NULL)
204: xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
205: "Reference to default namespace not in scope\n");
206: else
207: xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
208: "Reference to namespace '%s' not in scope\n",
209: (char *) ns->prefix);
210: }
211: if (ret == -3) {
212: if (ns->prefix == NULL)
213: xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
214: "Reference to default namespace not on ancestor\n");
215: else
216: xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
217: "Reference to namespace '%s' not on ancestor\n",
218: (char *) ns->prefix);
219: }
220: }
221:
222: /**
223: * xmlCtxtCheckString:
224: * @ctxt: the debug context
225: * @str: the string
226: *
227: * Do debugging on the string, currently it just checks the UTF-8 content
228: */
229: static void
230: xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
231: {
232: if (str == NULL) return;
233: if (ctxt->check) {
234: if (!xmlCheckUTF8(str)) {
235: xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
236: "String is not UTF-8 %s", (const char *) str);
237: }
238: }
239: }
240:
241: /**
242: * xmlCtxtCheckName:
243: * @ctxt: the debug context
244: * @name: the name
245: *
246: * Do debugging on the name, for example the dictionnary status and
247: * conformance to the Name production.
248: */
249: static void
250: xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name)
251: {
252: if (ctxt->check) {
253: if (name == NULL) {
254: xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
255: return;
256: }
257: if (xmlValidateName(name, 0)) {
258: xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
259: "Name is not an NCName '%s'", (const char *) name);
260: }
261: if ((ctxt->dict != NULL) &&
262: (!xmlDictOwns(ctxt->dict, name)) &&
263: ((ctxt->doc == NULL) ||
264: ((ctxt->doc->parseFlags & (XML_PARSE_SAX1 | XML_PARSE_NODICT)) == 0))) {
265: xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
266: "Name is not from the document dictionnary '%s'",
267: (const char *) name);
268: }
269: }
270: }
271:
272: static void
273: xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
274: xmlDocPtr doc;
275: xmlDictPtr dict;
276:
277: doc = node->doc;
278:
279: if (node->parent == NULL)
280: xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
281: "Node has no parent\n");
282: if (node->doc == NULL) {
283: xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
284: "Node has no doc\n");
285: dict = NULL;
286: } else {
287: dict = doc->dict;
288: if ((dict == NULL) && (ctxt->nodict == 0)) {
289: #if 0
290: /* desactivated right now as it raises too many errors */
291: if (doc->type == XML_DOCUMENT_NODE)
292: xmlDebugErr(ctxt, XML_CHECK_NO_DICT,
293: "Document has no dictionnary\n");
294: #endif
295: ctxt->nodict = 1;
296: }
297: if (ctxt->doc == NULL)
298: ctxt->doc = doc;
299:
300: if (ctxt->dict == NULL) {
301: ctxt->dict = dict;
302: }
303: }
304: if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
305: (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
306: xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
307: "Node doc differs from parent's one\n");
308: if (node->prev == NULL) {
309: if (node->type == XML_ATTRIBUTE_NODE) {
310: if ((node->parent != NULL) &&
311: (node != (xmlNodePtr) node->parent->properties))
312: xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
313: "Attr has no prev and not first of attr list\n");
1.1.1.3 ! misho 314:
1.1 misho 315: } else if ((node->parent != NULL) && (node->parent->children != node))
316: xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
317: "Node has no prev and not first of parent list\n");
318: } else {
319: if (node->prev->next != node)
320: xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
321: "Node prev->next : back link wrong\n");
322: }
323: if (node->next == NULL) {
324: if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
325: (node->parent->last != node) &&
326: (node->parent->type == XML_ELEMENT_NODE))
327: xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
328: "Node has no next and not last of parent list\n");
329: } else {
330: if (node->next->prev != node)
331: xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
332: "Node next->prev : forward link wrong\n");
333: if (node->next->parent != node->parent)
334: xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
335: "Node next->prev : forward link wrong\n");
336: }
337: if (node->type == XML_ELEMENT_NODE) {
338: xmlNsPtr ns;
339:
340: ns = node->nsDef;
341: while (ns != NULL) {
342: xmlCtxtNsCheckScope(ctxt, node, ns);
343: ns = ns->next;
344: }
345: if (node->ns != NULL)
346: xmlCtxtNsCheckScope(ctxt, node, node->ns);
347: } else if (node->type == XML_ATTRIBUTE_NODE) {
348: if (node->ns != NULL)
349: xmlCtxtNsCheckScope(ctxt, node, node->ns);
350: }
351:
352: if ((node->type != XML_ELEMENT_NODE) &&
353: (node->type != XML_ATTRIBUTE_NODE) &&
354: (node->type != XML_ELEMENT_DECL) &&
355: (node->type != XML_ATTRIBUTE_DECL) &&
356: (node->type != XML_DTD_NODE) &&
357: (node->type != XML_HTML_DOCUMENT_NODE) &&
358: (node->type != XML_DOCUMENT_NODE)) {
359: if (node->content != NULL)
360: xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
361: }
362: switch (node->type) {
363: case XML_ELEMENT_NODE:
364: case XML_ATTRIBUTE_NODE:
365: xmlCtxtCheckName(ctxt, node->name);
366: break;
367: case XML_TEXT_NODE:
368: if ((node->name == xmlStringText) ||
369: (node->name == xmlStringTextNoenc))
370: break;
371: /* some case of entity substitution can lead to this */
372: if ((ctxt->dict != NULL) &&
373: (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
374: 7)))
375: break;
376:
377: xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
378: "Text node has wrong name '%s'",
379: (const char *) node->name);
380: break;
381: case XML_COMMENT_NODE:
382: if (node->name == xmlStringComment)
383: break;
384: xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
385: "Comment node has wrong name '%s'",
386: (const char *) node->name);
387: break;
388: case XML_PI_NODE:
389: xmlCtxtCheckName(ctxt, node->name);
390: break;
391: case XML_CDATA_SECTION_NODE:
392: if (node->name == NULL)
393: break;
394: xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
395: "CData section has non NULL name '%s'",
396: (const char *) node->name);
397: break;
398: case XML_ENTITY_REF_NODE:
399: case XML_ENTITY_NODE:
400: case XML_DOCUMENT_TYPE_NODE:
401: case XML_DOCUMENT_FRAG_NODE:
402: case XML_NOTATION_NODE:
403: case XML_DTD_NODE:
404: case XML_ELEMENT_DECL:
405: case XML_ATTRIBUTE_DECL:
406: case XML_ENTITY_DECL:
407: case XML_NAMESPACE_DECL:
408: case XML_XINCLUDE_START:
409: case XML_XINCLUDE_END:
410: #ifdef LIBXML_DOCB_ENABLED
411: case XML_DOCB_DOCUMENT_NODE:
412: #endif
413: case XML_DOCUMENT_NODE:
414: case XML_HTML_DOCUMENT_NODE:
415: break;
416: }
417: }
418:
419: static void
420: xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
421: {
422: int i;
423:
424: if (ctxt->check) {
425: return;
426: }
427: /* TODO: check UTF8 content of the string */
428: if (str == NULL) {
429: fprintf(ctxt->output, "(NULL)");
430: return;
431: }
432: for (i = 0; i < 40; i++)
433: if (str[i] == 0)
434: return;
435: else if (IS_BLANK_CH(str[i]))
436: fputc(' ', ctxt->output);
437: else if (str[i] >= 0x80)
438: fprintf(ctxt->output, "#%X", str[i]);
439: else
440: fputc(str[i], ctxt->output);
441: fprintf(ctxt->output, "...");
442: }
443:
444: static void
445: xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
446: {
447: xmlCtxtDumpSpaces(ctxt);
448:
449: if (dtd == NULL) {
450: if (!ctxt->check)
451: fprintf(ctxt->output, "DTD node is NULL\n");
452: return;
453: }
454:
455: if (dtd->type != XML_DTD_NODE) {
456: xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
457: "Node is not a DTD");
458: return;
459: }
460: if (!ctxt->check) {
461: if (dtd->name != NULL)
462: fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
463: else
464: fprintf(ctxt->output, "DTD");
465: if (dtd->ExternalID != NULL)
466: fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
467: if (dtd->SystemID != NULL)
468: fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
469: fprintf(ctxt->output, "\n");
470: }
471: /*
472: * Do a bit of checking
473: */
474: xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
475: }
476:
477: static void
478: xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
479: {
480: xmlCtxtDumpSpaces(ctxt);
481:
482: if (attr == NULL) {
483: if (!ctxt->check)
484: fprintf(ctxt->output, "Attribute declaration is NULL\n");
485: return;
486: }
487: if (attr->type != XML_ATTRIBUTE_DECL) {
488: xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
489: "Node is not an attribute declaration");
490: return;
491: }
492: if (attr->name != NULL) {
493: if (!ctxt->check)
494: fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
495: } else
496: xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
497: "Node attribute declaration has no name");
498: if (attr->elem != NULL) {
499: if (!ctxt->check)
500: fprintf(ctxt->output, " for %s", (char *) attr->elem);
501: } else
502: xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
503: "Node attribute declaration has no element name");
504: if (!ctxt->check) {
505: switch (attr->atype) {
506: case XML_ATTRIBUTE_CDATA:
507: fprintf(ctxt->output, " CDATA");
508: break;
509: case XML_ATTRIBUTE_ID:
510: fprintf(ctxt->output, " ID");
511: break;
512: case XML_ATTRIBUTE_IDREF:
513: fprintf(ctxt->output, " IDREF");
514: break;
515: case XML_ATTRIBUTE_IDREFS:
516: fprintf(ctxt->output, " IDREFS");
517: break;
518: case XML_ATTRIBUTE_ENTITY:
519: fprintf(ctxt->output, " ENTITY");
520: break;
521: case XML_ATTRIBUTE_ENTITIES:
522: fprintf(ctxt->output, " ENTITIES");
523: break;
524: case XML_ATTRIBUTE_NMTOKEN:
525: fprintf(ctxt->output, " NMTOKEN");
526: break;
527: case XML_ATTRIBUTE_NMTOKENS:
528: fprintf(ctxt->output, " NMTOKENS");
529: break;
530: case XML_ATTRIBUTE_ENUMERATION:
531: fprintf(ctxt->output, " ENUMERATION");
532: break;
533: case XML_ATTRIBUTE_NOTATION:
534: fprintf(ctxt->output, " NOTATION ");
535: break;
536: }
537: if (attr->tree != NULL) {
538: int indx;
539: xmlEnumerationPtr cur = attr->tree;
540:
541: for (indx = 0; indx < 5; indx++) {
542: if (indx != 0)
543: fprintf(ctxt->output, "|%s", (char *) cur->name);
544: else
545: fprintf(ctxt->output, " (%s", (char *) cur->name);
546: cur = cur->next;
547: if (cur == NULL)
548: break;
549: }
550: if (cur == NULL)
551: fprintf(ctxt->output, ")");
552: else
553: fprintf(ctxt->output, "...)");
554: }
555: switch (attr->def) {
556: case XML_ATTRIBUTE_NONE:
557: break;
558: case XML_ATTRIBUTE_REQUIRED:
559: fprintf(ctxt->output, " REQUIRED");
560: break;
561: case XML_ATTRIBUTE_IMPLIED:
562: fprintf(ctxt->output, " IMPLIED");
563: break;
564: case XML_ATTRIBUTE_FIXED:
565: fprintf(ctxt->output, " FIXED");
566: break;
567: }
568: if (attr->defaultValue != NULL) {
569: fprintf(ctxt->output, "\"");
570: xmlCtxtDumpString(ctxt, attr->defaultValue);
571: fprintf(ctxt->output, "\"");
572: }
573: fprintf(ctxt->output, "\n");
574: }
575:
576: /*
577: * Do a bit of checking
578: */
579: xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
580: }
581:
582: static void
583: xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
584: {
585: xmlCtxtDumpSpaces(ctxt);
586:
587: if (elem == NULL) {
588: if (!ctxt->check)
589: fprintf(ctxt->output, "Element declaration is NULL\n");
590: return;
591: }
592: if (elem->type != XML_ELEMENT_DECL) {
593: xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
594: "Node is not an element declaration");
595: return;
596: }
597: if (elem->name != NULL) {
598: if (!ctxt->check) {
599: fprintf(ctxt->output, "ELEMDECL(");
600: xmlCtxtDumpString(ctxt, elem->name);
601: fprintf(ctxt->output, ")");
602: }
603: } else
604: xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
605: "Element declaration has no name");
606: if (!ctxt->check) {
607: switch (elem->etype) {
608: case XML_ELEMENT_TYPE_UNDEFINED:
609: fprintf(ctxt->output, ", UNDEFINED");
610: break;
611: case XML_ELEMENT_TYPE_EMPTY:
612: fprintf(ctxt->output, ", EMPTY");
613: break;
614: case XML_ELEMENT_TYPE_ANY:
615: fprintf(ctxt->output, ", ANY");
616: break;
617: case XML_ELEMENT_TYPE_MIXED:
618: fprintf(ctxt->output, ", MIXED ");
619: break;
620: case XML_ELEMENT_TYPE_ELEMENT:
621: fprintf(ctxt->output, ", MIXED ");
622: break;
623: }
624: if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
625: char buf[5001];
626:
627: buf[0] = 0;
628: xmlSnprintfElementContent(buf, 5000, elem->content, 1);
629: buf[5000] = 0;
630: fprintf(ctxt->output, "%s", buf);
631: }
632: fprintf(ctxt->output, "\n");
633: }
634:
635: /*
636: * Do a bit of checking
637: */
638: xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
639: }
640:
641: static void
642: xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
643: {
644: xmlCtxtDumpSpaces(ctxt);
645:
646: if (ent == NULL) {
647: if (!ctxt->check)
648: fprintf(ctxt->output, "Entity declaration is NULL\n");
649: return;
650: }
651: if (ent->type != XML_ENTITY_DECL) {
652: xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
653: "Node is not an entity declaration");
654: return;
655: }
656: if (ent->name != NULL) {
657: if (!ctxt->check) {
658: fprintf(ctxt->output, "ENTITYDECL(");
659: xmlCtxtDumpString(ctxt, ent->name);
660: fprintf(ctxt->output, ")");
661: }
662: } else
663: xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
664: "Entity declaration has no name");
665: if (!ctxt->check) {
666: switch (ent->etype) {
667: case XML_INTERNAL_GENERAL_ENTITY:
668: fprintf(ctxt->output, ", internal\n");
669: break;
670: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
671: fprintf(ctxt->output, ", external parsed\n");
672: break;
673: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
674: fprintf(ctxt->output, ", unparsed\n");
675: break;
676: case XML_INTERNAL_PARAMETER_ENTITY:
677: fprintf(ctxt->output, ", parameter\n");
678: break;
679: case XML_EXTERNAL_PARAMETER_ENTITY:
680: fprintf(ctxt->output, ", external parameter\n");
681: break;
682: case XML_INTERNAL_PREDEFINED_ENTITY:
683: fprintf(ctxt->output, ", predefined\n");
684: break;
685: }
686: if (ent->ExternalID) {
687: xmlCtxtDumpSpaces(ctxt);
688: fprintf(ctxt->output, " ExternalID=%s\n",
689: (char *) ent->ExternalID);
690: }
691: if (ent->SystemID) {
692: xmlCtxtDumpSpaces(ctxt);
693: fprintf(ctxt->output, " SystemID=%s\n",
694: (char *) ent->SystemID);
695: }
696: if (ent->URI != NULL) {
697: xmlCtxtDumpSpaces(ctxt);
698: fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
699: }
700: if (ent->content) {
701: xmlCtxtDumpSpaces(ctxt);
702: fprintf(ctxt->output, " content=");
703: xmlCtxtDumpString(ctxt, ent->content);
704: fprintf(ctxt->output, "\n");
705: }
706: }
707:
708: /*
709: * Do a bit of checking
710: */
711: xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
712: }
713:
714: static void
715: xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
716: {
717: xmlCtxtDumpSpaces(ctxt);
718:
719: if (ns == NULL) {
720: if (!ctxt->check)
721: fprintf(ctxt->output, "namespace node is NULL\n");
722: return;
723: }
724: if (ns->type != XML_NAMESPACE_DECL) {
725: xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
726: "Node is not a namespace declaration");
727: return;
728: }
729: if (ns->href == NULL) {
730: if (ns->prefix != NULL)
731: xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
732: "Incomplete namespace %s href=NULL\n",
733: (char *) ns->prefix);
734: else
735: xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
736: "Incomplete default namespace href=NULL\n");
737: } else {
738: if (!ctxt->check) {
739: if (ns->prefix != NULL)
740: fprintf(ctxt->output, "namespace %s href=",
741: (char *) ns->prefix);
742: else
743: fprintf(ctxt->output, "default namespace href=");
744:
745: xmlCtxtDumpString(ctxt, ns->href);
746: fprintf(ctxt->output, "\n");
747: }
748: }
749: }
750:
751: static void
752: xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
753: {
754: while (ns != NULL) {
755: xmlCtxtDumpNamespace(ctxt, ns);
756: ns = ns->next;
757: }
758: }
759:
760: static void
761: xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
762: {
763: xmlCtxtDumpSpaces(ctxt);
764:
765: if (ent == NULL) {
766: if (!ctxt->check)
767: fprintf(ctxt->output, "Entity is NULL\n");
768: return;
769: }
770: if (!ctxt->check) {
771: switch (ent->etype) {
772: case XML_INTERNAL_GENERAL_ENTITY:
773: fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
774: break;
775: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
776: fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
777: break;
778: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
779: fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
780: break;
781: case XML_INTERNAL_PARAMETER_ENTITY:
782: fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
783: break;
784: case XML_EXTERNAL_PARAMETER_ENTITY:
785: fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
786: break;
787: default:
788: fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
789: }
790: fprintf(ctxt->output, "%s\n", ent->name);
791: if (ent->ExternalID) {
792: xmlCtxtDumpSpaces(ctxt);
793: fprintf(ctxt->output, "ExternalID=%s\n",
794: (char *) ent->ExternalID);
795: }
796: if (ent->SystemID) {
797: xmlCtxtDumpSpaces(ctxt);
798: fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
799: }
800: if (ent->URI) {
801: xmlCtxtDumpSpaces(ctxt);
802: fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
803: }
804: if (ent->content) {
805: xmlCtxtDumpSpaces(ctxt);
806: fprintf(ctxt->output, "content=");
807: xmlCtxtDumpString(ctxt, ent->content);
808: fprintf(ctxt->output, "\n");
809: }
810: }
811: }
812:
813: /**
814: * xmlCtxtDumpAttr:
815: * @output: the FILE * for the output
816: * @attr: the attribute
817: * @depth: the indentation level.
818: *
819: * Dumps debug information for the attribute
820: */
821: static void
822: xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
823: {
824: xmlCtxtDumpSpaces(ctxt);
825:
826: if (attr == NULL) {
827: if (!ctxt->check)
828: fprintf(ctxt->output, "Attr is NULL");
829: return;
830: }
831: if (!ctxt->check) {
832: fprintf(ctxt->output, "ATTRIBUTE ");
833: xmlCtxtDumpString(ctxt, attr->name);
834: fprintf(ctxt->output, "\n");
835: if (attr->children != NULL) {
836: ctxt->depth++;
837: xmlCtxtDumpNodeList(ctxt, attr->children);
838: ctxt->depth--;
839: }
840: }
841: if (attr->name == NULL)
842: xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
843: "Attribute has no name");
844:
845: /*
846: * Do a bit of checking
847: */
848: xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
849: }
850:
851: /**
852: * xmlCtxtDumpAttrList:
853: * @output: the FILE * for the output
854: * @attr: the attribute list
855: * @depth: the indentation level.
856: *
857: * Dumps debug information for the attribute list
858: */
859: static void
860: xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
861: {
862: while (attr != NULL) {
863: xmlCtxtDumpAttr(ctxt, attr);
864: attr = attr->next;
865: }
866: }
867:
868: /**
869: * xmlCtxtDumpOneNode:
870: * @output: the FILE * for the output
871: * @node: the node
872: * @depth: the indentation level.
873: *
874: * Dumps debug information for the element node, it is not recursive
875: */
876: static void
877: xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
878: {
879: if (node == NULL) {
880: if (!ctxt->check) {
881: xmlCtxtDumpSpaces(ctxt);
882: fprintf(ctxt->output, "node is NULL\n");
883: }
884: return;
885: }
886: ctxt->node = node;
887:
888: switch (node->type) {
889: case XML_ELEMENT_NODE:
890: if (!ctxt->check) {
891: xmlCtxtDumpSpaces(ctxt);
892: fprintf(ctxt->output, "ELEMENT ");
893: if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
894: xmlCtxtDumpString(ctxt, node->ns->prefix);
895: fprintf(ctxt->output, ":");
896: }
897: xmlCtxtDumpString(ctxt, node->name);
898: fprintf(ctxt->output, "\n");
899: }
900: break;
901: case XML_ATTRIBUTE_NODE:
902: if (!ctxt->check)
903: xmlCtxtDumpSpaces(ctxt);
904: fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
905: xmlCtxtGenericNodeCheck(ctxt, node);
906: return;
907: case XML_TEXT_NODE:
908: if (!ctxt->check) {
909: xmlCtxtDumpSpaces(ctxt);
910: if (node->name == (const xmlChar *) xmlStringTextNoenc)
911: fprintf(ctxt->output, "TEXT no enc");
912: else
913: fprintf(ctxt->output, "TEXT");
914: if (ctxt->options & DUMP_TEXT_TYPE) {
915: if (node->content == (xmlChar *) &(node->properties))
916: fprintf(ctxt->output, " compact\n");
917: else if (xmlDictOwns(ctxt->dict, node->content) == 1)
918: fprintf(ctxt->output, " interned\n");
919: else
920: fprintf(ctxt->output, "\n");
921: } else
922: fprintf(ctxt->output, "\n");
923: }
924: break;
925: case XML_CDATA_SECTION_NODE:
926: if (!ctxt->check) {
927: xmlCtxtDumpSpaces(ctxt);
928: fprintf(ctxt->output, "CDATA_SECTION\n");
929: }
930: break;
931: case XML_ENTITY_REF_NODE:
932: if (!ctxt->check) {
933: xmlCtxtDumpSpaces(ctxt);
934: fprintf(ctxt->output, "ENTITY_REF(%s)\n",
935: (char *) node->name);
936: }
937: break;
938: case XML_ENTITY_NODE:
939: if (!ctxt->check) {
940: xmlCtxtDumpSpaces(ctxt);
941: fprintf(ctxt->output, "ENTITY\n");
942: }
943: break;
944: case XML_PI_NODE:
945: if (!ctxt->check) {
946: xmlCtxtDumpSpaces(ctxt);
947: fprintf(ctxt->output, "PI %s\n", (char *) node->name);
948: }
949: break;
950: case XML_COMMENT_NODE:
951: if (!ctxt->check) {
952: xmlCtxtDumpSpaces(ctxt);
953: fprintf(ctxt->output, "COMMENT\n");
954: }
955: break;
956: case XML_DOCUMENT_NODE:
957: case XML_HTML_DOCUMENT_NODE:
958: if (!ctxt->check) {
959: xmlCtxtDumpSpaces(ctxt);
960: }
961: fprintf(ctxt->output, "Error, DOCUMENT found here\n");
962: xmlCtxtGenericNodeCheck(ctxt, node);
963: return;
964: case XML_DOCUMENT_TYPE_NODE:
965: if (!ctxt->check) {
966: xmlCtxtDumpSpaces(ctxt);
967: fprintf(ctxt->output, "DOCUMENT_TYPE\n");
968: }
969: break;
970: case XML_DOCUMENT_FRAG_NODE:
971: if (!ctxt->check) {
972: xmlCtxtDumpSpaces(ctxt);
973: fprintf(ctxt->output, "DOCUMENT_FRAG\n");
974: }
975: break;
976: case XML_NOTATION_NODE:
977: if (!ctxt->check) {
978: xmlCtxtDumpSpaces(ctxt);
979: fprintf(ctxt->output, "NOTATION\n");
980: }
981: break;
982: case XML_DTD_NODE:
983: xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
984: return;
985: case XML_ELEMENT_DECL:
986: xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
987: return;
988: case XML_ATTRIBUTE_DECL:
989: xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
990: return;
991: case XML_ENTITY_DECL:
992: xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
993: return;
994: case XML_NAMESPACE_DECL:
995: xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
996: return;
997: case XML_XINCLUDE_START:
998: if (!ctxt->check) {
999: xmlCtxtDumpSpaces(ctxt);
1000: fprintf(ctxt->output, "INCLUDE START\n");
1001: }
1002: return;
1003: case XML_XINCLUDE_END:
1004: if (!ctxt->check) {
1005: xmlCtxtDumpSpaces(ctxt);
1006: fprintf(ctxt->output, "INCLUDE END\n");
1007: }
1008: return;
1009: default:
1010: if (!ctxt->check)
1011: xmlCtxtDumpSpaces(ctxt);
1012: xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1013: "Unknown node type %d\n", node->type);
1014: return;
1015: }
1016: if (node->doc == NULL) {
1017: if (!ctxt->check) {
1018: xmlCtxtDumpSpaces(ctxt);
1019: }
1020: fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
1021: }
1022: ctxt->depth++;
1023: if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
1024: xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
1025: if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
1026: xmlCtxtDumpAttrList(ctxt, node->properties);
1027: if (node->type != XML_ENTITY_REF_NODE) {
1028: if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
1029: if (!ctxt->check) {
1030: xmlCtxtDumpSpaces(ctxt);
1031: fprintf(ctxt->output, "content=");
1032: xmlCtxtDumpString(ctxt, node->content);
1033: fprintf(ctxt->output, "\n");
1034: }
1035: }
1036: } else {
1037: xmlEntityPtr ent;
1038:
1039: ent = xmlGetDocEntity(node->doc, node->name);
1040: if (ent != NULL)
1041: xmlCtxtDumpEntity(ctxt, ent);
1042: }
1043: ctxt->depth--;
1044:
1045: /*
1046: * Do a bit of checking
1047: */
1048: xmlCtxtGenericNodeCheck(ctxt, node);
1049: }
1050:
1051: /**
1052: * xmlCtxtDumpNode:
1053: * @output: the FILE * for the output
1054: * @node: the node
1055: * @depth: the indentation level.
1056: *
1057: * Dumps debug information for the element node, it is recursive
1058: */
1059: static void
1060: xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1061: {
1062: if (node == NULL) {
1063: if (!ctxt->check) {
1064: xmlCtxtDumpSpaces(ctxt);
1065: fprintf(ctxt->output, "node is NULL\n");
1066: }
1067: return;
1068: }
1069: xmlCtxtDumpOneNode(ctxt, node);
1.1.1.3 ! misho 1070: if ((node->type != XML_NAMESPACE_DECL) &&
1.1 misho 1071: (node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1072: ctxt->depth++;
1073: xmlCtxtDumpNodeList(ctxt, node->children);
1074: ctxt->depth--;
1075: }
1076: }
1077:
1078: /**
1079: * xmlCtxtDumpNodeList:
1080: * @output: the FILE * for the output
1081: * @node: the node list
1082: * @depth: the indentation level.
1083: *
1084: * Dumps debug information for the list of element node, it is recursive
1085: */
1086: static void
1087: xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1088: {
1089: while (node != NULL) {
1090: xmlCtxtDumpNode(ctxt, node);
1091: node = node->next;
1092: }
1093: }
1094:
1095: static void
1096: xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1097: {
1098: if (doc == NULL) {
1099: if (!ctxt->check)
1100: fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1101: return;
1102: }
1103: ctxt->node = (xmlNodePtr) doc;
1104:
1105: switch (doc->type) {
1106: case XML_ELEMENT_NODE:
1107: xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
1108: "Misplaced ELEMENT node\n");
1109: break;
1110: case XML_ATTRIBUTE_NODE:
1111: xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
1112: "Misplaced ATTRIBUTE node\n");
1113: break;
1114: case XML_TEXT_NODE:
1115: xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
1116: "Misplaced TEXT node\n");
1117: break;
1118: case XML_CDATA_SECTION_NODE:
1119: xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
1120: "Misplaced CDATA node\n");
1121: break;
1122: case XML_ENTITY_REF_NODE:
1123: xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
1124: "Misplaced ENTITYREF node\n");
1125: break;
1126: case XML_ENTITY_NODE:
1127: xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
1128: "Misplaced ENTITY node\n");
1129: break;
1130: case XML_PI_NODE:
1131: xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
1132: "Misplaced PI node\n");
1133: break;
1134: case XML_COMMENT_NODE:
1135: xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
1136: "Misplaced COMMENT node\n");
1137: break;
1138: case XML_DOCUMENT_NODE:
1139: if (!ctxt->check)
1140: fprintf(ctxt->output, "DOCUMENT\n");
1141: break;
1142: case XML_HTML_DOCUMENT_NODE:
1143: if (!ctxt->check)
1144: fprintf(ctxt->output, "HTML DOCUMENT\n");
1145: break;
1146: case XML_DOCUMENT_TYPE_NODE:
1147: xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
1148: "Misplaced DOCTYPE node\n");
1149: break;
1150: case XML_DOCUMENT_FRAG_NODE:
1151: xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
1152: "Misplaced FRAGMENT node\n");
1153: break;
1154: case XML_NOTATION_NODE:
1155: xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
1156: "Misplaced NOTATION node\n");
1157: break;
1158: default:
1159: xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1160: "Unknown node type %d\n", doc->type);
1161: }
1162: }
1163:
1164: /**
1165: * xmlCtxtDumpDocumentHead:
1166: * @output: the FILE * for the output
1167: * @doc: the document
1168: *
1169: * Dumps debug information cncerning the document, not recursive
1170: */
1171: static void
1172: xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1173: {
1174: if (doc == NULL) return;
1175: xmlCtxtDumpDocHead(ctxt, doc);
1176: if (!ctxt->check) {
1177: if (doc->name != NULL) {
1178: fprintf(ctxt->output, "name=");
1179: xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
1180: fprintf(ctxt->output, "\n");
1181: }
1182: if (doc->version != NULL) {
1183: fprintf(ctxt->output, "version=");
1184: xmlCtxtDumpString(ctxt, doc->version);
1185: fprintf(ctxt->output, "\n");
1186: }
1187: if (doc->encoding != NULL) {
1188: fprintf(ctxt->output, "encoding=");
1189: xmlCtxtDumpString(ctxt, doc->encoding);
1190: fprintf(ctxt->output, "\n");
1191: }
1192: if (doc->URL != NULL) {
1193: fprintf(ctxt->output, "URL=");
1194: xmlCtxtDumpString(ctxt, doc->URL);
1195: fprintf(ctxt->output, "\n");
1196: }
1197: if (doc->standalone)
1198: fprintf(ctxt->output, "standalone=true\n");
1199: }
1200: if (doc->oldNs != NULL)
1201: xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
1202: }
1203:
1204: /**
1205: * xmlCtxtDumpDocument:
1206: * @output: the FILE * for the output
1207: * @doc: the document
1208: *
1209: * Dumps debug information for the document, it's recursive
1210: */
1211: static void
1212: xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1213: {
1214: if (doc == NULL) {
1215: if (!ctxt->check)
1216: fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1217: return;
1218: }
1219: xmlCtxtDumpDocumentHead(ctxt, doc);
1220: if (((doc->type == XML_DOCUMENT_NODE) ||
1221: (doc->type == XML_HTML_DOCUMENT_NODE))
1222: && (doc->children != NULL)) {
1223: ctxt->depth++;
1224: xmlCtxtDumpNodeList(ctxt, doc->children);
1225: ctxt->depth--;
1226: }
1227: }
1228:
1229: static void
1230: xmlCtxtDumpEntityCallback(xmlEntityPtr cur, xmlDebugCtxtPtr ctxt)
1231: {
1232: if (cur == NULL) {
1233: if (!ctxt->check)
1234: fprintf(ctxt->output, "Entity is NULL");
1235: return;
1236: }
1237: if (!ctxt->check) {
1238: fprintf(ctxt->output, "%s : ", (char *) cur->name);
1239: switch (cur->etype) {
1240: case XML_INTERNAL_GENERAL_ENTITY:
1241: fprintf(ctxt->output, "INTERNAL GENERAL, ");
1242: break;
1243: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1244: fprintf(ctxt->output, "EXTERNAL PARSED, ");
1245: break;
1246: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1247: fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
1248: break;
1249: case XML_INTERNAL_PARAMETER_ENTITY:
1250: fprintf(ctxt->output, "INTERNAL PARAMETER, ");
1251: break;
1252: case XML_EXTERNAL_PARAMETER_ENTITY:
1253: fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
1254: break;
1255: default:
1256: xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
1257: "Unknown entity type %d\n", cur->etype);
1258: }
1259: if (cur->ExternalID != NULL)
1260: fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
1261: if (cur->SystemID != NULL)
1262: fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
1263: if (cur->orig != NULL)
1264: fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
1265: if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
1266: fprintf(ctxt->output, "\n content \"%s\"",
1267: (char *) cur->content);
1268: fprintf(ctxt->output, "\n");
1269: }
1270: }
1271:
1272: /**
1273: * xmlCtxtDumpEntities:
1274: * @output: the FILE * for the output
1275: * @doc: the document
1276: *
1277: * Dumps debug information for all the entities in use by the document
1278: */
1279: static void
1280: xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1281: {
1282: if (doc == NULL) return;
1283: xmlCtxtDumpDocHead(ctxt, doc);
1284: if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1285: xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1286: doc->intSubset->entities;
1287:
1288: if (!ctxt->check)
1289: fprintf(ctxt->output, "Entities in internal subset\n");
1290: xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
1291: ctxt);
1292: } else
1293: fprintf(ctxt->output, "No entities in internal subset\n");
1294: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1295: xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1296: doc->extSubset->entities;
1297:
1298: if (!ctxt->check)
1299: fprintf(ctxt->output, "Entities in external subset\n");
1300: xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
1301: ctxt);
1302: } else if (!ctxt->check)
1303: fprintf(ctxt->output, "No entities in external subset\n");
1304: }
1305:
1306: /**
1307: * xmlCtxtDumpDTD:
1308: * @output: the FILE * for the output
1309: * @dtd: the DTD
1310: *
1311: * Dumps debug information for the DTD
1312: */
1313: static void
1314: xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
1315: {
1316: if (dtd == NULL) {
1317: if (!ctxt->check)
1318: fprintf(ctxt->output, "DTD is NULL\n");
1319: return;
1320: }
1321: xmlCtxtDumpDtdNode(ctxt, dtd);
1322: if (dtd->children == NULL)
1323: fprintf(ctxt->output, " DTD is empty\n");
1324: else {
1325: ctxt->depth++;
1326: xmlCtxtDumpNodeList(ctxt, dtd->children);
1327: ctxt->depth--;
1328: }
1329: }
1330:
1331: /************************************************************************
1332: * *
1333: * Public entry points for dump *
1334: * *
1335: ************************************************************************/
1336:
1337: /**
1338: * xmlDebugDumpString:
1339: * @output: the FILE * for the output
1340: * @str: the string
1341: *
1342: * Dumps informations about the string, shorten it if necessary
1343: */
1344: void
1345: xmlDebugDumpString(FILE * output, const xmlChar * str)
1346: {
1347: int i;
1348:
1349: if (output == NULL)
1350: output = stdout;
1351: if (str == NULL) {
1352: fprintf(output, "(NULL)");
1353: return;
1354: }
1355: for (i = 0; i < 40; i++)
1356: if (str[i] == 0)
1357: return;
1358: else if (IS_BLANK_CH(str[i]))
1359: fputc(' ', output);
1360: else if (str[i] >= 0x80)
1361: fprintf(output, "#%X", str[i]);
1362: else
1363: fputc(str[i], output);
1364: fprintf(output, "...");
1365: }
1366:
1367: /**
1368: * xmlDebugDumpAttr:
1369: * @output: the FILE * for the output
1370: * @attr: the attribute
1371: * @depth: the indentation level.
1372: *
1373: * Dumps debug information for the attribute
1374: */
1375: void
1376: xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
1377: xmlDebugCtxt ctxt;
1378:
1379: if (output == NULL) return;
1380: xmlCtxtDumpInitCtxt(&ctxt);
1381: ctxt.output = output;
1382: ctxt.depth = depth;
1383: xmlCtxtDumpAttr(&ctxt, attr);
1384: xmlCtxtDumpCleanCtxt(&ctxt);
1385: }
1386:
1387:
1388: /**
1389: * xmlDebugDumpEntities:
1390: * @output: the FILE * for the output
1391: * @doc: the document
1392: *
1393: * Dumps debug information for all the entities in use by the document
1394: */
1395: void
1396: xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1397: {
1398: xmlDebugCtxt ctxt;
1399:
1400: if (output == NULL) return;
1401: xmlCtxtDumpInitCtxt(&ctxt);
1402: ctxt.output = output;
1403: xmlCtxtDumpEntities(&ctxt, doc);
1404: xmlCtxtDumpCleanCtxt(&ctxt);
1405: }
1406:
1407: /**
1408: * xmlDebugDumpAttrList:
1409: * @output: the FILE * for the output
1410: * @attr: the attribute list
1411: * @depth: the indentation level.
1412: *
1413: * Dumps debug information for the attribute list
1414: */
1415: void
1416: xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
1417: {
1418: xmlDebugCtxt ctxt;
1419:
1420: if (output == NULL) return;
1421: xmlCtxtDumpInitCtxt(&ctxt);
1422: ctxt.output = output;
1423: ctxt.depth = depth;
1424: xmlCtxtDumpAttrList(&ctxt, attr);
1425: xmlCtxtDumpCleanCtxt(&ctxt);
1426: }
1427:
1428: /**
1429: * xmlDebugDumpOneNode:
1430: * @output: the FILE * for the output
1431: * @node: the node
1432: * @depth: the indentation level.
1433: *
1434: * Dumps debug information for the element node, it is not recursive
1435: */
1436: void
1437: xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
1438: {
1439: xmlDebugCtxt ctxt;
1440:
1441: if (output == NULL) return;
1442: xmlCtxtDumpInitCtxt(&ctxt);
1443: ctxt.output = output;
1444: ctxt.depth = depth;
1445: xmlCtxtDumpOneNode(&ctxt, node);
1446: xmlCtxtDumpCleanCtxt(&ctxt);
1447: }
1448:
1449: /**
1450: * xmlDebugDumpNode:
1451: * @output: the FILE * for the output
1452: * @node: the node
1453: * @depth: the indentation level.
1454: *
1455: * Dumps debug information for the element node, it is recursive
1456: */
1457: void
1458: xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
1459: {
1460: xmlDebugCtxt ctxt;
1461:
1462: if (output == NULL)
1463: output = stdout;
1464: xmlCtxtDumpInitCtxt(&ctxt);
1465: ctxt.output = output;
1466: ctxt.depth = depth;
1467: xmlCtxtDumpNode(&ctxt, node);
1468: xmlCtxtDumpCleanCtxt(&ctxt);
1469: }
1470:
1471: /**
1472: * xmlDebugDumpNodeList:
1473: * @output: the FILE * for the output
1474: * @node: the node list
1475: * @depth: the indentation level.
1476: *
1477: * Dumps debug information for the list of element node, it is recursive
1478: */
1479: void
1480: xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
1481: {
1482: xmlDebugCtxt ctxt;
1483:
1484: if (output == NULL)
1485: output = stdout;
1486: xmlCtxtDumpInitCtxt(&ctxt);
1487: ctxt.output = output;
1488: ctxt.depth = depth;
1489: xmlCtxtDumpNodeList(&ctxt, node);
1490: xmlCtxtDumpCleanCtxt(&ctxt);
1491: }
1492:
1493: /**
1494: * xmlDebugDumpDocumentHead:
1495: * @output: the FILE * for the output
1496: * @doc: the document
1497: *
1498: * Dumps debug information cncerning the document, not recursive
1499: */
1500: void
1501: xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
1502: {
1503: xmlDebugCtxt ctxt;
1504:
1505: if (output == NULL)
1506: output = stdout;
1507: xmlCtxtDumpInitCtxt(&ctxt);
1508: ctxt.options |= DUMP_TEXT_TYPE;
1509: ctxt.output = output;
1510: xmlCtxtDumpDocumentHead(&ctxt, doc);
1511: xmlCtxtDumpCleanCtxt(&ctxt);
1512: }
1513:
1514: /**
1515: * xmlDebugDumpDocument:
1516: * @output: the FILE * for the output
1517: * @doc: the document
1518: *
1519: * Dumps debug information for the document, it's recursive
1520: */
1521: void
1522: xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
1523: {
1524: xmlDebugCtxt ctxt;
1525:
1526: if (output == NULL)
1527: output = stdout;
1528: xmlCtxtDumpInitCtxt(&ctxt);
1529: ctxt.options |= DUMP_TEXT_TYPE;
1530: ctxt.output = output;
1531: xmlCtxtDumpDocument(&ctxt, doc);
1532: xmlCtxtDumpCleanCtxt(&ctxt);
1533: }
1534:
1535: /**
1536: * xmlDebugDumpDTD:
1537: * @output: the FILE * for the output
1538: * @dtd: the DTD
1539: *
1540: * Dumps debug information for the DTD
1541: */
1542: void
1543: xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
1544: {
1545: xmlDebugCtxt ctxt;
1546:
1547: if (output == NULL)
1548: output = stdout;
1549: xmlCtxtDumpInitCtxt(&ctxt);
1550: ctxt.options |= DUMP_TEXT_TYPE;
1551: ctxt.output = output;
1552: xmlCtxtDumpDTD(&ctxt, dtd);
1553: xmlCtxtDumpCleanCtxt(&ctxt);
1554: }
1555:
1556: /************************************************************************
1557: * *
1558: * Public entry points for checkings *
1559: * *
1560: ************************************************************************/
1561:
1562: /**
1563: * xmlDebugCheckDocument:
1564: * @output: the FILE * for the output
1565: * @doc: the document
1566: *
1567: * Check the document for potential content problems, and output
1568: * the errors to @output
1569: *
1570: * Returns the number of errors found
1571: */
1572: int
1573: xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
1574: {
1575: xmlDebugCtxt ctxt;
1576:
1577: if (output == NULL)
1578: output = stdout;
1579: xmlCtxtDumpInitCtxt(&ctxt);
1580: ctxt.output = output;
1581: ctxt.check = 1;
1582: xmlCtxtDumpDocument(&ctxt, doc);
1583: xmlCtxtDumpCleanCtxt(&ctxt);
1584: return(ctxt.errors);
1585: }
1586:
1587: /************************************************************************
1588: * *
1589: * Helpers for Shell *
1590: * *
1591: ************************************************************************/
1592:
1593: /**
1594: * xmlLsCountNode:
1595: * @node: the node to count
1596: *
1597: * Count the children of @node.
1598: *
1599: * Returns the number of children of @node.
1600: */
1601: int
1602: xmlLsCountNode(xmlNodePtr node) {
1603: int ret = 0;
1604: xmlNodePtr list = NULL;
1.1.1.3 ! misho 1605:
1.1 misho 1606: if (node == NULL)
1607: return(0);
1608:
1609: switch (node->type) {
1610: case XML_ELEMENT_NODE:
1611: list = node->children;
1612: break;
1613: case XML_DOCUMENT_NODE:
1614: case XML_HTML_DOCUMENT_NODE:
1615: #ifdef LIBXML_DOCB_ENABLED
1616: case XML_DOCB_DOCUMENT_NODE:
1617: #endif
1618: list = ((xmlDocPtr) node)->children;
1619: break;
1620: case XML_ATTRIBUTE_NODE:
1621: list = ((xmlAttrPtr) node)->children;
1622: break;
1623: case XML_TEXT_NODE:
1624: case XML_CDATA_SECTION_NODE:
1625: case XML_PI_NODE:
1626: case XML_COMMENT_NODE:
1627: if (node->content != NULL) {
1628: ret = xmlStrlen(node->content);
1629: }
1630: break;
1631: case XML_ENTITY_REF_NODE:
1632: case XML_DOCUMENT_TYPE_NODE:
1633: case XML_ENTITY_NODE:
1634: case XML_DOCUMENT_FRAG_NODE:
1635: case XML_NOTATION_NODE:
1636: case XML_DTD_NODE:
1637: case XML_ELEMENT_DECL:
1638: case XML_ATTRIBUTE_DECL:
1639: case XML_ENTITY_DECL:
1640: case XML_NAMESPACE_DECL:
1641: case XML_XINCLUDE_START:
1642: case XML_XINCLUDE_END:
1643: ret = 1;
1644: break;
1645: }
1.1.1.3 ! misho 1646: for (;list != NULL;ret++)
1.1 misho 1647: list = list->next;
1648: return(ret);
1649: }
1650:
1651: /**
1652: * xmlLsOneNode:
1653: * @output: the FILE * for the output
1654: * @node: the node to dump
1655: *
1656: * Dump to @output the type and name of @node.
1657: */
1658: void
1659: xmlLsOneNode(FILE *output, xmlNodePtr node) {
1660: if (output == NULL) return;
1661: if (node == NULL) {
1662: fprintf(output, "NULL\n");
1663: return;
1664: }
1665: switch (node->type) {
1666: case XML_ELEMENT_NODE:
1667: fprintf(output, "-");
1668: break;
1669: case XML_ATTRIBUTE_NODE:
1670: fprintf(output, "a");
1671: break;
1672: case XML_TEXT_NODE:
1673: fprintf(output, "t");
1674: break;
1675: case XML_CDATA_SECTION_NODE:
1676: fprintf(output, "C");
1677: break;
1678: case XML_ENTITY_REF_NODE:
1679: fprintf(output, "e");
1680: break;
1681: case XML_ENTITY_NODE:
1682: fprintf(output, "E");
1683: break;
1684: case XML_PI_NODE:
1685: fprintf(output, "p");
1686: break;
1687: case XML_COMMENT_NODE:
1688: fprintf(output, "c");
1689: break;
1690: case XML_DOCUMENT_NODE:
1691: fprintf(output, "d");
1692: break;
1693: case XML_HTML_DOCUMENT_NODE:
1694: fprintf(output, "h");
1695: break;
1696: case XML_DOCUMENT_TYPE_NODE:
1697: fprintf(output, "T");
1698: break;
1699: case XML_DOCUMENT_FRAG_NODE:
1700: fprintf(output, "F");
1701: break;
1702: case XML_NOTATION_NODE:
1703: fprintf(output, "N");
1704: break;
1705: case XML_NAMESPACE_DECL:
1706: fprintf(output, "n");
1707: break;
1708: default:
1709: fprintf(output, "?");
1710: }
1711: if (node->type != XML_NAMESPACE_DECL) {
1712: if (node->properties != NULL)
1713: fprintf(output, "a");
1.1.1.3 ! misho 1714: else
1.1 misho 1715: fprintf(output, "-");
1.1.1.3 ! misho 1716: if (node->nsDef != NULL)
1.1 misho 1717: fprintf(output, "n");
1.1.1.3 ! misho 1718: else
1.1 misho 1719: fprintf(output, "-");
1720: }
1721:
1722: fprintf(output, " %8d ", xmlLsCountNode(node));
1723:
1724: switch (node->type) {
1725: case XML_ELEMENT_NODE:
1.1.1.2 misho 1726: if (node->name != NULL) {
1727: if ((node->ns != NULL) && (node->ns->prefix != NULL))
1728: fprintf(output, "%s:", node->ns->prefix);
1.1 misho 1729: fprintf(output, "%s", (const char *) node->name);
1.1.1.2 misho 1730: }
1.1 misho 1731: break;
1732: case XML_ATTRIBUTE_NODE:
1733: if (node->name != NULL)
1734: fprintf(output, "%s", (const char *) node->name);
1735: break;
1736: case XML_TEXT_NODE:
1737: if (node->content != NULL) {
1738: xmlDebugDumpString(output, node->content);
1739: }
1740: break;
1741: case XML_CDATA_SECTION_NODE:
1742: break;
1743: case XML_ENTITY_REF_NODE:
1744: if (node->name != NULL)
1745: fprintf(output, "%s", (const char *) node->name);
1746: break;
1747: case XML_ENTITY_NODE:
1748: if (node->name != NULL)
1749: fprintf(output, "%s", (const char *) node->name);
1750: break;
1751: case XML_PI_NODE:
1752: if (node->name != NULL)
1753: fprintf(output, "%s", (const char *) node->name);
1754: break;
1755: case XML_COMMENT_NODE:
1756: break;
1757: case XML_DOCUMENT_NODE:
1758: break;
1759: case XML_HTML_DOCUMENT_NODE:
1760: break;
1761: case XML_DOCUMENT_TYPE_NODE:
1762: break;
1763: case XML_DOCUMENT_FRAG_NODE:
1764: break;
1765: case XML_NOTATION_NODE:
1766: break;
1767: case XML_NAMESPACE_DECL: {
1768: xmlNsPtr ns = (xmlNsPtr) node;
1769:
1770: if (ns->prefix == NULL)
1771: fprintf(output, "default -> %s", (char *)ns->href);
1772: else
1773: fprintf(output, "%s -> %s", (char *)ns->prefix,
1774: (char *)ns->href);
1775: break;
1776: }
1777: default:
1778: if (node->name != NULL)
1779: fprintf(output, "%s", (const char *) node->name);
1780: }
1781: fprintf(output, "\n");
1782: }
1783:
1784: /**
1785: * xmlBoolToText:
1786: * @boolval: a bool to turn into text
1787: *
1.1.1.3 ! misho 1788: * Convenient way to turn bool into text
1.1 misho 1789: *
1790: * Returns a pointer to either "True" or "False"
1791: */
1792: const char *
1793: xmlBoolToText(int boolval)
1794: {
1795: if (boolval)
1796: return("True");
1797: else
1798: return("False");
1799: }
1800:
1801: #ifdef LIBXML_XPATH_ENABLED
1802: /****************************************************************
1803: * *
1.1.1.3 ! misho 1804: * The XML shell related functions *
1.1 misho 1805: * *
1806: ****************************************************************/
1807:
1808:
1809:
1810: /*
1811: * TODO: Improvement/cleanups for the XML shell
1812: * - allow to shell out an editor on a subpart
1813: * - cleanup function registrations (with help) and calling
1814: * - provide registration routines
1815: */
1816:
1817: /**
1818: * xmlShellPrintXPathError:
1819: * @errorType: valid xpath error id
1820: * @arg: the argument that cause xpath to fail
1821: *
1822: * Print the xpath error to libxml default error channel
1823: */
1824: void
1825: xmlShellPrintXPathError(int errorType, const char *arg)
1826: {
1827: const char *default_arg = "Result";
1828:
1829: if (!arg)
1830: arg = default_arg;
1831:
1832: switch (errorType) {
1833: case XPATH_UNDEFINED:
1834: xmlGenericError(xmlGenericErrorContext,
1835: "%s: no such node\n", arg);
1836: break;
1837:
1838: case XPATH_BOOLEAN:
1839: xmlGenericError(xmlGenericErrorContext,
1840: "%s is a Boolean\n", arg);
1841: break;
1842: case XPATH_NUMBER:
1843: xmlGenericError(xmlGenericErrorContext,
1844: "%s is a number\n", arg);
1845: break;
1846: case XPATH_STRING:
1847: xmlGenericError(xmlGenericErrorContext,
1848: "%s is a string\n", arg);
1849: break;
1850: case XPATH_POINT:
1851: xmlGenericError(xmlGenericErrorContext,
1852: "%s is a point\n", arg);
1853: break;
1854: case XPATH_RANGE:
1855: xmlGenericError(xmlGenericErrorContext,
1856: "%s is a range\n", arg);
1857: break;
1858: case XPATH_LOCATIONSET:
1859: xmlGenericError(xmlGenericErrorContext,
1860: "%s is a range\n", arg);
1861: break;
1862: case XPATH_USERS:
1863: xmlGenericError(xmlGenericErrorContext,
1864: "%s is user-defined\n", arg);
1865: break;
1866: case XPATH_XSLT_TREE:
1867: xmlGenericError(xmlGenericErrorContext,
1868: "%s is an XSLT value tree\n", arg);
1869: break;
1870: }
1871: #if 0
1872: xmlGenericError(xmlGenericErrorContext,
1873: "Try casting the result string function (xpath builtin)\n",
1874: arg);
1875: #endif
1876: }
1877:
1878:
1879: #ifdef LIBXML_OUTPUT_ENABLED
1880: /**
1881: * xmlShellPrintNodeCtxt:
1882: * @ctxt : a non-null shell context
1883: * @node : a non-null node to print to the output FILE
1884: *
1885: * Print node to the output FILE
1886: */
1887: static void
1888: xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1889: {
1890: FILE *fp;
1891:
1892: if (!node)
1893: return;
1894: if (ctxt == NULL)
1895: fp = stdout;
1896: else
1897: fp = ctxt->output;
1898:
1899: if (node->type == XML_DOCUMENT_NODE)
1900: xmlDocDump(fp, (xmlDocPtr) node);
1901: else if (node->type == XML_ATTRIBUTE_NODE)
1902: xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
1903: else
1904: xmlElemDump(fp, node->doc, node);
1905:
1906: fprintf(fp, "\n");
1907: }
1908:
1909: /**
1910: * xmlShellPrintNode:
1911: * @node : a non-null node to print to the output FILE
1912: *
1913: * Print node to the output FILE
1914: */
1915: void
1916: xmlShellPrintNode(xmlNodePtr node)
1917: {
1918: xmlShellPrintNodeCtxt(NULL, node);
1919: }
1920: #endif /* LIBXML_OUTPUT_ENABLED */
1921:
1922: /**
1923: * xmlShellPrintXPathResultCtxt:
1924: * @ctxt: a valid shell context
1925: * @list: a valid result generated by an xpath evaluation
1926: *
1927: * Prints result to the output FILE
1928: */
1929: static void
1930: xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
1931: {
1932: if (!ctxt)
1933: return;
1934:
1935: if (list != NULL) {
1936: switch (list->type) {
1937: case XPATH_NODESET:{
1938: #ifdef LIBXML_OUTPUT_ENABLED
1939: int indx;
1940:
1941: if (list->nodesetval) {
1942: for (indx = 0; indx < list->nodesetval->nodeNr;
1943: indx++) {
1944: xmlShellPrintNodeCtxt(ctxt,
1945: list->nodesetval->nodeTab[indx]);
1946: }
1947: } else {
1948: xmlGenericError(xmlGenericErrorContext,
1949: "Empty node set\n");
1950: }
1951: break;
1952: #else
1953: xmlGenericError(xmlGenericErrorContext,
1954: "Node set\n");
1955: #endif /* LIBXML_OUTPUT_ENABLED */
1956: }
1957: case XPATH_BOOLEAN:
1958: xmlGenericError(xmlGenericErrorContext,
1959: "Is a Boolean:%s\n",
1960: xmlBoolToText(list->boolval));
1961: break;
1962: case XPATH_NUMBER:
1963: xmlGenericError(xmlGenericErrorContext,
1964: "Is a number:%0g\n", list->floatval);
1965: break;
1966: case XPATH_STRING:
1967: xmlGenericError(xmlGenericErrorContext,
1968: "Is a string:%s\n", list->stringval);
1969: break;
1970:
1971: default:
1972: xmlShellPrintXPathError(list->type, NULL);
1973: }
1974: }
1975: }
1976:
1977: /**
1978: * xmlShellPrintXPathResult:
1979: * @list: a valid result generated by an xpath evaluation
1980: *
1981: * Prints result to the output FILE
1982: */
1983: void
1984: xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1985: {
1986: xmlShellPrintXPathResultCtxt(NULL, list);
1987: }
1988:
1989: /**
1990: * xmlShellList:
1991: * @ctxt: the shell context
1992: * @arg: unused
1993: * @node: a node
1994: * @node2: unused
1995: *
1996: * Implements the XML shell function "ls"
1997: * Does an Unix like listing of the given node (like a directory)
1998: *
1999: * Returns 0
2000: */
2001: int
2002: xmlShellList(xmlShellCtxtPtr ctxt,
2003: char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2004: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2005: {
2006: xmlNodePtr cur;
2007: if (!ctxt)
2008: return (0);
2009: if (node == NULL) {
2010: fprintf(ctxt->output, "NULL\n");
2011: return (0);
2012: }
2013: if ((node->type == XML_DOCUMENT_NODE) ||
2014: (node->type == XML_HTML_DOCUMENT_NODE)) {
2015: cur = ((xmlDocPtr) node)->children;
2016: } else if (node->type == XML_NAMESPACE_DECL) {
2017: xmlLsOneNode(ctxt->output, node);
2018: return (0);
2019: } else if (node->children != NULL) {
2020: cur = node->children;
2021: } else {
2022: xmlLsOneNode(ctxt->output, node);
2023: return (0);
2024: }
2025: while (cur != NULL) {
2026: xmlLsOneNode(ctxt->output, cur);
2027: cur = cur->next;
2028: }
2029: return (0);
2030: }
2031:
2032: /**
2033: * xmlShellBase:
2034: * @ctxt: the shell context
2035: * @arg: unused
2036: * @node: a node
2037: * @node2: unused
2038: *
2039: * Implements the XML shell function "base"
2040: * dumps the current XML base of the node
2041: *
2042: * Returns 0
2043: */
2044: int
2045: xmlShellBase(xmlShellCtxtPtr ctxt,
2046: char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2047: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2048: {
2049: xmlChar *base;
2050: if (!ctxt)
2051: return 0;
2052: if (node == NULL) {
2053: fprintf(ctxt->output, "NULL\n");
2054: return (0);
1.1.1.3 ! misho 2055: }
1.1 misho 2056:
2057: base = xmlNodeGetBase(node->doc, node);
2058:
2059: if (base == NULL) {
2060: fprintf(ctxt->output, " No base found !!!\n");
2061: } else {
2062: fprintf(ctxt->output, "%s\n", base);
2063: xmlFree(base);
2064: }
2065: return (0);
2066: }
2067:
2068: #ifdef LIBXML_TREE_ENABLED
2069: /**
2070: * xmlShellSetBase:
2071: * @ctxt: the shell context
2072: * @arg: the new base
2073: * @node: a node
2074: * @node2: unused
2075: *
2076: * Implements the XML shell function "setbase"
2077: * change the current XML base of the node
2078: *
2079: * Returns 0
2080: */
2081: static int
2082: xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2083: char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2084: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2085: {
2086: xmlNodeSetBase(node, (xmlChar*) arg);
2087: return (0);
2088: }
2089: #endif
2090:
2091: #ifdef LIBXML_XPATH_ENABLED
2092: /**
2093: * xmlShellRegisterNamespace:
2094: * @ctxt: the shell context
2095: * @arg: a string in prefix=nsuri format
2096: * @node: unused
2097: * @node2: unused
2098: *
2099: * Implements the XML shell function "setns"
2100: * register/unregister a prefix=namespace pair
2101: * on the XPath context
2102: *
2103: * Returns 0 on success and a negative value otherwise.
2104: */
2105: static int
2106: xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
2107: xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2108: {
2109: xmlChar* nsListDup;
2110: xmlChar* prefix;
2111: xmlChar* href;
2112: xmlChar* next;
2113:
2114: nsListDup = xmlStrdup((xmlChar *) arg);
2115: next = nsListDup;
2116: while(next != NULL) {
2117: /* skip spaces */
2118: /*while((*next) == ' ') next++;*/
2119: if((*next) == '\0') break;
2120:
2121: /* find prefix */
2122: prefix = next;
2123: next = (xmlChar*)xmlStrchr(next, '=');
2124: if(next == NULL) {
2125: fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
2126: xmlFree(nsListDup);
2127: return(-1);
2128: }
2129: *(next++) = '\0';
2130:
2131: /* find href */
2132: href = next;
2133: next = (xmlChar*)xmlStrchr(next, ' ');
2134: if(next != NULL) {
2135: *(next++) = '\0';
2136: }
2137:
2138: /* do register namespace */
2139: if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
2140: fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
2141: xmlFree(nsListDup);
2142: return(-1);
2143: }
2144: }
2145:
2146: xmlFree(nsListDup);
2147: return(0);
2148: }
2149: /**
2150: * xmlShellRegisterRootNamespaces:
2151: * @ctxt: the shell context
2152: * @arg: unused
2153: * @node: the root element
2154: * @node2: unused
2155: *
2156: * Implements the XML shell function "setrootns"
2157: * which registers all namespaces declarations found on the root element.
2158: *
2159: * Returns 0 on success and a negative value otherwise.
2160: */
2161: static int
2162: xmlShellRegisterRootNamespaces(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2163: xmlNodePtr root, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2164: {
2165: xmlNsPtr ns;
2166:
2167: if ((root == NULL) || (root->type != XML_ELEMENT_NODE) ||
2168: (root->nsDef == NULL) || (ctxt == NULL) || (ctxt->pctxt == NULL))
2169: return(-1);
2170: ns = root->nsDef;
2171: while (ns != NULL) {
2172: if (ns->prefix == NULL)
2173: xmlXPathRegisterNs(ctxt->pctxt, BAD_CAST "defaultns", ns->href);
2174: else
2175: xmlXPathRegisterNs(ctxt->pctxt, ns->prefix, ns->href);
2176: ns = ns->next;
2177: }
2178: return(0);
2179: }
2180: #endif
2181:
2182: /**
2183: * xmlShellGrep:
2184: * @ctxt: the shell context
2185: * @arg: the string or regular expression to find
2186: * @node: a node
2187: * @node2: unused
2188: *
2189: * Implements the XML shell function "grep"
2190: * dumps informations about the node (namespace, attributes, content).
2191: *
2192: * Returns 0
2193: */
2194: static int
2195: xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2196: char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2197: {
2198: if (!ctxt)
2199: return (0);
2200: if (node == NULL)
2201: return (0);
2202: if (arg == NULL)
2203: return (0);
2204: #ifdef LIBXML_REGEXP_ENABLED
2205: if ((xmlStrchr((xmlChar *) arg, '?')) ||
2206: (xmlStrchr((xmlChar *) arg, '*')) ||
2207: (xmlStrchr((xmlChar *) arg, '.')) ||
2208: (xmlStrchr((xmlChar *) arg, '['))) {
2209: }
2210: #endif
2211: while (node != NULL) {
2212: if (node->type == XML_COMMENT_NODE) {
2213: if (xmlStrstr(node->content, (xmlChar *) arg)) {
2214:
2215: fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
2216: xmlShellList(ctxt, NULL, node, NULL);
2217: }
2218: } else if (node->type == XML_TEXT_NODE) {
2219: if (xmlStrstr(node->content, (xmlChar *) arg)) {
2220:
2221: fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
2222: xmlShellList(ctxt, NULL, node->parent, NULL);
2223: }
2224: }
2225:
2226: /*
2227: * Browse the full subtree, deep first
2228: */
2229:
2230: if ((node->type == XML_DOCUMENT_NODE) ||
2231: (node->type == XML_HTML_DOCUMENT_NODE)) {
2232: node = ((xmlDocPtr) node)->children;
2233: } else if ((node->children != NULL)
2234: && (node->type != XML_ENTITY_REF_NODE)) {
2235: /* deep first */
2236: node = node->children;
2237: } else if (node->next != NULL) {
2238: /* then siblings */
2239: node = node->next;
2240: } else {
2241: /* go up to parents->next if needed */
2242: while (node != NULL) {
2243: if (node->parent != NULL) {
2244: node = node->parent;
2245: }
2246: if (node->next != NULL) {
2247: node = node->next;
2248: break;
2249: }
2250: if (node->parent == NULL) {
2251: node = NULL;
2252: break;
2253: }
2254: }
2255: }
2256: }
2257: return (0);
2258: }
2259:
2260: /**
2261: * xmlShellDir:
2262: * @ctxt: the shell context
2263: * @arg: unused
2264: * @node: a node
2265: * @node2: unused
2266: *
2267: * Implements the XML shell function "dir"
2268: * dumps informations about the node (namespace, attributes, content).
2269: *
2270: * Returns 0
2271: */
2272: int
2273: xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2274: char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2275: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2276: {
2277: if (!ctxt)
2278: return (0);
2279: if (node == NULL) {
2280: fprintf(ctxt->output, "NULL\n");
2281: return (0);
1.1.1.3 ! misho 2282: }
1.1 misho 2283: if ((node->type == XML_DOCUMENT_NODE) ||
2284: (node->type == XML_HTML_DOCUMENT_NODE)) {
2285: xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
2286: } else if (node->type == XML_ATTRIBUTE_NODE) {
2287: xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
2288: } else {
2289: xmlDebugDumpOneNode(ctxt->output, node, 0);
2290: }
2291: return (0);
2292: }
2293:
2294: /**
2295: * xmlShellSetContent:
2296: * @ctxt: the shell context
2297: * @value: the content as a string
2298: * @node: a node
2299: * @node2: unused
2300: *
2301: * Implements the XML shell function "dir"
2302: * dumps informations about the node (namespace, attributes, content).
2303: *
2304: * Returns 0
2305: */
2306: static int
2307: xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2308: char *value, xmlNodePtr node,
2309: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2310: {
2311: xmlNodePtr results;
2312: xmlParserErrors ret;
2313:
2314: if (!ctxt)
2315: return (0);
2316: if (node == NULL) {
2317: fprintf(ctxt->output, "NULL\n");
2318: return (0);
2319: }
2320: if (value == NULL) {
2321: fprintf(ctxt->output, "NULL\n");
2322: return (0);
2323: }
2324:
2325: ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
2326: if (ret == XML_ERR_OK) {
2327: if (node->children != NULL) {
2328: xmlFreeNodeList(node->children);
2329: node->children = NULL;
2330: node->last = NULL;
2331: }
2332: xmlAddChildList(node, results);
2333: } else {
2334: fprintf(ctxt->output, "failed to parse content\n");
2335: }
2336: return (0);
2337: }
2338:
2339: #ifdef LIBXML_SCHEMAS_ENABLED
2340: /**
2341: * xmlShellRNGValidate:
2342: * @ctxt: the shell context
2343: * @schemas: the path to the Relax-NG schemas
2344: * @node: a node
2345: * @node2: unused
2346: *
2347: * Implements the XML shell function "relaxng"
2348: * validating the instance against a Relax-NG schemas
2349: *
2350: * Returns 0
2351: */
2352: static int
2353: xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
2354: xmlNodePtr node ATTRIBUTE_UNUSED,
2355: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2356: {
2357: xmlRelaxNGPtr relaxngschemas;
2358: xmlRelaxNGParserCtxtPtr ctxt;
2359: xmlRelaxNGValidCtxtPtr vctxt;
2360: int ret;
2361:
2362: ctxt = xmlRelaxNGNewParserCtxt(schemas);
2363: xmlRelaxNGSetParserErrors(ctxt,
2364: (xmlRelaxNGValidityErrorFunc) fprintf,
2365: (xmlRelaxNGValidityWarningFunc) fprintf,
2366: stderr);
2367: relaxngschemas = xmlRelaxNGParse(ctxt);
2368: xmlRelaxNGFreeParserCtxt(ctxt);
2369: if (relaxngschemas == NULL) {
2370: xmlGenericError(xmlGenericErrorContext,
2371: "Relax-NG schema %s failed to compile\n", schemas);
2372: return(-1);
2373: }
2374: vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2375: xmlRelaxNGSetValidErrors(vctxt,
2376: (xmlRelaxNGValidityErrorFunc) fprintf,
2377: (xmlRelaxNGValidityWarningFunc) fprintf,
2378: stderr);
2379: ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
2380: if (ret == 0) {
2381: fprintf(stderr, "%s validates\n", sctxt->filename);
2382: } else if (ret > 0) {
2383: fprintf(stderr, "%s fails to validate\n", sctxt->filename);
2384: } else {
2385: fprintf(stderr, "%s validation generated an internal error\n",
2386: sctxt->filename);
2387: }
2388: xmlRelaxNGFreeValidCtxt(vctxt);
2389: if (relaxngschemas != NULL)
2390: xmlRelaxNGFree(relaxngschemas);
2391: return(0);
2392: }
2393: #endif
2394:
2395: #ifdef LIBXML_OUTPUT_ENABLED
2396: /**
2397: * xmlShellCat:
2398: * @ctxt: the shell context
2399: * @arg: unused
2400: * @node: a node
2401: * @node2: unused
2402: *
2403: * Implements the XML shell function "cat"
2404: * dumps the serialization node content (XML or HTML).
2405: *
2406: * Returns 0
2407: */
2408: int
2409: xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2410: xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2411: {
2412: if (!ctxt)
2413: return (0);
2414: if (node == NULL) {
2415: fprintf(ctxt->output, "NULL\n");
2416: return (0);
1.1.1.3 ! misho 2417: }
1.1 misho 2418: if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
2419: #ifdef LIBXML_HTML_ENABLED
2420: if (node->type == XML_HTML_DOCUMENT_NODE)
2421: htmlDocDump(ctxt->output, (htmlDocPtr) node);
2422: else
2423: htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
2424: #else
2425: if (node->type == XML_DOCUMENT_NODE)
2426: xmlDocDump(ctxt->output, (xmlDocPtr) node);
2427: else
2428: xmlElemDump(ctxt->output, ctxt->doc, node);
2429: #endif /* LIBXML_HTML_ENABLED */
2430: } else {
2431: if (node->type == XML_DOCUMENT_NODE)
2432: xmlDocDump(ctxt->output, (xmlDocPtr) node);
2433: else
2434: xmlElemDump(ctxt->output, ctxt->doc, node);
2435: }
2436: fprintf(ctxt->output, "\n");
2437: return (0);
2438: }
2439: #endif /* LIBXML_OUTPUT_ENABLED */
2440:
2441: /**
2442: * xmlShellLoad:
2443: * @ctxt: the shell context
2444: * @filename: the file name
2445: * @node: unused
2446: * @node2: unused
2447: *
2448: * Implements the XML shell function "load"
2449: * loads a new document specified by the filename
2450: *
2451: * Returns 0 or -1 if loading failed
2452: */
2453: int
2454: xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
2455: xmlNodePtr node ATTRIBUTE_UNUSED,
2456: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2457: {
2458: xmlDocPtr doc;
2459: int html = 0;
2460:
2461: if ((ctxt == NULL) || (filename == NULL)) return(-1);
2462: if (ctxt->doc != NULL)
2463: html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
2464:
2465: if (html) {
2466: #ifdef LIBXML_HTML_ENABLED
2467: doc = htmlParseFile(filename, NULL);
2468: #else
2469: fprintf(ctxt->output, "HTML support not compiled in\n");
2470: doc = NULL;
2471: #endif /* LIBXML_HTML_ENABLED */
2472: } else {
2473: doc = xmlReadFile(filename,NULL,0);
2474: }
2475: if (doc != NULL) {
2476: if (ctxt->loaded == 1) {
2477: xmlFreeDoc(ctxt->doc);
2478: }
2479: ctxt->loaded = 1;
2480: #ifdef LIBXML_XPATH_ENABLED
2481: xmlXPathFreeContext(ctxt->pctxt);
2482: #endif /* LIBXML_XPATH_ENABLED */
2483: xmlFree(ctxt->filename);
2484: ctxt->doc = doc;
2485: ctxt->node = (xmlNodePtr) doc;
2486: #ifdef LIBXML_XPATH_ENABLED
2487: ctxt->pctxt = xmlXPathNewContext(doc);
2488: #endif /* LIBXML_XPATH_ENABLED */
2489: ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
2490: } else
2491: return (-1);
2492: return (0);
2493: }
2494:
2495: #ifdef LIBXML_OUTPUT_ENABLED
2496: /**
2497: * xmlShellWrite:
2498: * @ctxt: the shell context
2499: * @filename: the file name
2500: * @node: a node in the tree
2501: * @node2: unused
2502: *
2503: * Implements the XML shell function "write"
2504: * Write the current node to the filename, it saves the serialization
2505: * of the subtree under the @node specified
2506: *
2507: * Returns 0 or -1 in case of error
2508: */
2509: int
2510: xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
2511: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2512: {
2513: if (node == NULL)
2514: return (-1);
2515: if ((filename == NULL) || (filename[0] == 0)) {
2516: return (-1);
2517: }
2518: #ifdef W_OK
2519: if (access((char *) filename, W_OK)) {
2520: xmlGenericError(xmlGenericErrorContext,
2521: "Cannot write to %s\n", filename);
2522: return (-1);
2523: }
2524: #endif
2525: switch (node->type) {
2526: case XML_DOCUMENT_NODE:
2527: if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2528: xmlGenericError(xmlGenericErrorContext,
2529: "Failed to write to %s\n", filename);
2530: return (-1);
2531: }
2532: break;
2533: case XML_HTML_DOCUMENT_NODE:
2534: #ifdef LIBXML_HTML_ENABLED
2535: if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2536: xmlGenericError(xmlGenericErrorContext,
2537: "Failed to write to %s\n", filename);
2538: return (-1);
2539: }
2540: #else
2541: if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2542: xmlGenericError(xmlGenericErrorContext,
2543: "Failed to write to %s\n", filename);
2544: return (-1);
2545: }
2546: #endif /* LIBXML_HTML_ENABLED */
2547: break;
2548: default:{
2549: FILE *f;
2550:
2551: f = fopen((char *) filename, "w");
2552: if (f == NULL) {
2553: xmlGenericError(xmlGenericErrorContext,
2554: "Failed to write to %s\n", filename);
2555: return (-1);
2556: }
2557: xmlElemDump(f, ctxt->doc, node);
2558: fclose(f);
2559: }
2560: }
2561: return (0);
2562: }
2563:
2564: /**
2565: * xmlShellSave:
2566: * @ctxt: the shell context
2567: * @filename: the file name (optional)
2568: * @node: unused
2569: * @node2: unused
2570: *
2571: * Implements the XML shell function "save"
2572: * Write the current document to the filename, or it's original name
2573: *
2574: * Returns 0 or -1 in case of error
2575: */
2576: int
2577: xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
2578: xmlNodePtr node ATTRIBUTE_UNUSED,
2579: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2580: {
2581: if ((ctxt == NULL) || (ctxt->doc == NULL))
2582: return (-1);
2583: if ((filename == NULL) || (filename[0] == 0))
2584: filename = ctxt->filename;
2585: if (filename == NULL)
2586: return (-1);
2587: #ifdef W_OK
2588: if (access((char *) filename, W_OK)) {
2589: xmlGenericError(xmlGenericErrorContext,
2590: "Cannot save to %s\n", filename);
2591: return (-1);
2592: }
2593: #endif
2594: switch (ctxt->doc->type) {
2595: case XML_DOCUMENT_NODE:
2596: if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2597: xmlGenericError(xmlGenericErrorContext,
2598: "Failed to save to %s\n", filename);
2599: }
2600: break;
2601: case XML_HTML_DOCUMENT_NODE:
2602: #ifdef LIBXML_HTML_ENABLED
2603: if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2604: xmlGenericError(xmlGenericErrorContext,
2605: "Failed to save to %s\n", filename);
2606: }
2607: #else
2608: if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2609: xmlGenericError(xmlGenericErrorContext,
2610: "Failed to save to %s\n", filename);
2611: }
2612: #endif /* LIBXML_HTML_ENABLED */
2613: break;
2614: default:
2615: xmlGenericError(xmlGenericErrorContext,
2616: "To save to subparts of a document use the 'write' command\n");
2617: return (-1);
2618:
2619: }
2620: return (0);
2621: }
2622: #endif /* LIBXML_OUTPUT_ENABLED */
2623:
2624: #ifdef LIBXML_VALID_ENABLED
2625: /**
2626: * xmlShellValidate:
2627: * @ctxt: the shell context
2628: * @dtd: the DTD URI (optional)
2629: * @node: unused
2630: * @node2: unused
2631: *
2632: * Implements the XML shell function "validate"
2633: * Validate the document, if a DTD path is provided, then the validation
2634: * is done against the given DTD.
2635: *
2636: * Returns 0 or -1 in case of error
2637: */
2638: int
2639: xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
2640: xmlNodePtr node ATTRIBUTE_UNUSED,
2641: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2642: {
2643: xmlValidCtxt vctxt;
2644: int res = -1;
2645:
2646: if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1);
2647: vctxt.userData = stderr;
2648: vctxt.error = (xmlValidityErrorFunc) fprintf;
2649: vctxt.warning = (xmlValidityWarningFunc) fprintf;
2650:
2651: if ((dtd == NULL) || (dtd[0] == 0)) {
2652: res = xmlValidateDocument(&vctxt, ctxt->doc);
2653: } else {
2654: xmlDtdPtr subset;
2655:
2656: subset = xmlParseDTD(NULL, (xmlChar *) dtd);
2657: if (subset != NULL) {
2658: res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
2659:
2660: xmlFreeDtd(subset);
2661: }
2662: }
2663: return (res);
2664: }
2665: #endif /* LIBXML_VALID_ENABLED */
2666:
2667: /**
2668: * xmlShellDu:
2669: * @ctxt: the shell context
2670: * @arg: unused
2671: * @tree: a node defining a subtree
2672: * @node2: unused
2673: *
2674: * Implements the XML shell function "du"
2675: * show the structure of the subtree under node @tree
2676: * If @tree is null, the command works on the current node.
2677: *
2678: * Returns 0 or -1 in case of error
2679: */
2680: int
2681: xmlShellDu(xmlShellCtxtPtr ctxt,
2682: char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
2683: xmlNodePtr node2 ATTRIBUTE_UNUSED)
2684: {
2685: xmlNodePtr node;
2686: int indent = 0, i;
2687:
2688: if (!ctxt)
2689: return (-1);
2690:
2691: if (tree == NULL)
2692: return (-1);
2693: node = tree;
2694: while (node != NULL) {
2695: if ((node->type == XML_DOCUMENT_NODE) ||
2696: (node->type == XML_HTML_DOCUMENT_NODE)) {
2697: fprintf(ctxt->output, "/\n");
2698: } else if (node->type == XML_ELEMENT_NODE) {
2699: for (i = 0; i < indent; i++)
2700: fprintf(ctxt->output, " ");
1.1.1.2 misho 2701: if ((node->ns) && (node->ns->prefix))
2702: fprintf(ctxt->output, "%s:", node->ns->prefix);
1.1 misho 2703: fprintf(ctxt->output, "%s\n", node->name);
2704: } else {
2705: }
2706:
2707: /*
2708: * Browse the full subtree, deep first
2709: */
2710:
2711: if ((node->type == XML_DOCUMENT_NODE) ||
2712: (node->type == XML_HTML_DOCUMENT_NODE)) {
2713: node = ((xmlDocPtr) node)->children;
2714: } else if ((node->children != NULL)
2715: && (node->type != XML_ENTITY_REF_NODE)) {
2716: /* deep first */
2717: node = node->children;
2718: indent++;
2719: } else if ((node != tree) && (node->next != NULL)) {
2720: /* then siblings */
2721: node = node->next;
2722: } else if (node != tree) {
2723: /* go up to parents->next if needed */
2724: while (node != tree) {
2725: if (node->parent != NULL) {
2726: node = node->parent;
2727: indent--;
2728: }
2729: if ((node != tree) && (node->next != NULL)) {
2730: node = node->next;
2731: break;
2732: }
2733: if (node->parent == NULL) {
2734: node = NULL;
2735: break;
2736: }
2737: if (node == tree) {
2738: node = NULL;
2739: break;
2740: }
2741: }
2742: /* exit condition */
2743: if (node == tree)
2744: node = NULL;
2745: } else
2746: node = NULL;
2747: }
2748: return (0);
2749: }
2750:
2751: /**
2752: * xmlShellPwd:
2753: * @ctxt: the shell context
2754: * @buffer: the output buffer
1.1.1.3 ! misho 2755: * @node: a node
1.1 misho 2756: * @node2: unused
2757: *
2758: * Implements the XML shell function "pwd"
2759: * Show the full path from the root to the node, if needed building
2760: * thumblers when similar elements exists at a given ancestor level.
2761: * The output is compatible with XPath commands.
2762: *
2763: * Returns 0 or -1 in case of error
2764: */
2765: int
2766: xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2767: xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2768: {
2769: xmlChar *path;
2770:
2771: if ((node == NULL) || (buffer == NULL))
2772: return (-1);
2773:
2774: path = xmlGetNodePath(node);
2775: if (path == NULL)
2776: return (-1);
2777:
2778: /*
2779: * This test prevents buffer overflow, because this routine
2780: * is only called by xmlShell, in which the second argument is
2781: * 500 chars long.
2782: * It is a dirty hack before a cleaner solution is found.
2783: * Documentation should mention that the second argument must
2784: * be at least 500 chars long, and could be stripped if too long.
2785: */
2786: snprintf(buffer, 499, "%s", path);
2787: buffer[499] = '0';
2788: xmlFree(path);
2789:
2790: return (0);
2791: }
2792:
2793: /**
2794: * xmlShell:
2795: * @doc: the initial document
2796: * @filename: the output buffer
2797: * @input: the line reading function
2798: * @output: the output FILE*, defaults to stdout if NULL
2799: *
1.1.1.3 ! misho 2800: * Implements the XML shell
1.1 misho 2801: * This allow to load, validate, view, modify and save a document
2802: * using a environment similar to a UNIX commandline.
2803: */
2804: void
2805: xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
2806: FILE * output)
2807: {
2808: char prompt[500] = "/ > ";
2809: char *cmdline = NULL, *cur;
2810: char command[100];
2811: char arg[400];
2812: int i;
2813: xmlShellCtxtPtr ctxt;
2814: xmlXPathObjectPtr list;
2815:
2816: if (doc == NULL)
2817: return;
2818: if (filename == NULL)
2819: return;
2820: if (input == NULL)
2821: return;
2822: if (output == NULL)
2823: output = stdout;
2824: ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
2825: if (ctxt == NULL)
2826: return;
2827: ctxt->loaded = 0;
2828: ctxt->doc = doc;
2829: ctxt->input = input;
2830: ctxt->output = output;
2831: ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
2832: ctxt->node = (xmlNodePtr) ctxt->doc;
2833:
2834: #ifdef LIBXML_XPATH_ENABLED
2835: ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2836: if (ctxt->pctxt == NULL) {
2837: xmlFree(ctxt);
2838: return;
2839: }
2840: #endif /* LIBXML_XPATH_ENABLED */
2841: while (1) {
2842: if (ctxt->node == (xmlNodePtr) ctxt->doc)
2843: snprintf(prompt, sizeof(prompt), "%s > ", "/");
1.1.1.2 misho 2844: else if ((ctxt->node != NULL) && (ctxt->node->name) &&
2845: (ctxt->node->ns) && (ctxt->node->ns->prefix))
2846: snprintf(prompt, sizeof(prompt), "%s:%s > ",
2847: (ctxt->node->ns->prefix), ctxt->node->name);
1.1 misho 2848: else if ((ctxt->node != NULL) && (ctxt->node->name))
2849: snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
2850: else
2851: snprintf(prompt, sizeof(prompt), "? > ");
2852: prompt[sizeof(prompt) - 1] = 0;
2853:
2854: /*
2855: * Get a new command line
2856: */
2857: cmdline = ctxt->input(prompt);
2858: if (cmdline == NULL)
2859: break;
2860:
2861: /*
2862: * Parse the command itself
2863: */
2864: cur = cmdline;
2865: while ((*cur == ' ') || (*cur == '\t'))
2866: cur++;
2867: i = 0;
2868: while ((*cur != ' ') && (*cur != '\t') &&
2869: (*cur != '\n') && (*cur != '\r')) {
2870: if (*cur == 0)
2871: break;
2872: command[i++] = *cur++;
2873: }
2874: command[i] = 0;
2875: if (i == 0)
2876: continue;
2877:
2878: /*
2879: * Parse the argument
2880: */
2881: while ((*cur == ' ') || (*cur == '\t'))
2882: cur++;
2883: i = 0;
2884: while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2885: if (*cur == 0)
2886: break;
2887: arg[i++] = *cur++;
2888: }
2889: arg[i] = 0;
2890:
2891: /*
2892: * start interpreting the command
2893: */
2894: if (!strcmp(command, "exit"))
2895: break;
2896: if (!strcmp(command, "quit"))
2897: break;
2898: if (!strcmp(command, "bye"))
2899: break;
2900: if (!strcmp(command, "help")) {
2901: fprintf(ctxt->output, "\tbase display XML base of the node\n");
2902: fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2903: fprintf(ctxt->output, "\tbye leave shell\n");
2904: fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2905: fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2906: fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2907: fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2908: fprintf(ctxt->output, "\texit leave shell\n");
2909: fprintf(ctxt->output, "\thelp display this help\n");
2910: fprintf(ctxt->output, "\tfree display memory usage\n");
2911: fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2912: fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
2913: fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n");
2914: #ifdef LIBXML_XPATH_ENABLED
2915: fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
2916: fprintf(ctxt->output, "\tsetns nsreg register a namespace to a prefix in the XPath evaluation context\n");
2917: fprintf(ctxt->output, "\t format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
2918: fprintf(ctxt->output, "\tsetrootns register all namespace found on the root element\n");
2919: fprintf(ctxt->output, "\t the default namespace if any uses 'defaultns' prefix\n");
2920: #endif /* LIBXML_XPATH_ENABLED */
2921: fprintf(ctxt->output, "\tpwd display current working directory\n");
1.1.1.2 misho 2922: fprintf(ctxt->output, "\twhereis display absolute path of [path] or current working directory\n");
1.1 misho 2923: fprintf(ctxt->output, "\tquit leave shell\n");
2924: #ifdef LIBXML_OUTPUT_ENABLED
2925: fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
2926: fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
2927: #endif /* LIBXML_OUTPUT_ENABLED */
2928: #ifdef LIBXML_VALID_ENABLED
2929: fprintf(ctxt->output, "\tvalidate check the document for errors\n");
2930: #endif /* LIBXML_VALID_ENABLED */
2931: #ifdef LIBXML_SCHEMAS_ENABLED
2932: fprintf(ctxt->output, "\trelaxng rng validate the document agaisnt the Relax-NG schemas\n");
2933: #endif
2934: fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
2935: #ifdef LIBXML_VALID_ENABLED
2936: } else if (!strcmp(command, "validate")) {
2937: xmlShellValidate(ctxt, arg, NULL, NULL);
2938: #endif /* LIBXML_VALID_ENABLED */
2939: } else if (!strcmp(command, "load")) {
2940: xmlShellLoad(ctxt, arg, NULL, NULL);
2941: #ifdef LIBXML_SCHEMAS_ENABLED
2942: } else if (!strcmp(command, "relaxng")) {
2943: xmlShellRNGValidate(ctxt, arg, NULL, NULL);
2944: #endif
2945: #ifdef LIBXML_OUTPUT_ENABLED
2946: } else if (!strcmp(command, "save")) {
2947: xmlShellSave(ctxt, arg, NULL, NULL);
2948: } else if (!strcmp(command, "write")) {
2949: if ((arg == NULL) || (arg[0] == 0))
2950: xmlGenericError(xmlGenericErrorContext,
2951: "Write command requires a filename argument\n");
2952: else
2953: xmlShellWrite(ctxt, arg, ctxt->node, NULL);
2954: #endif /* LIBXML_OUTPUT_ENABLED */
2955: } else if (!strcmp(command, "grep")) {
2956: xmlShellGrep(ctxt, arg, ctxt->node, NULL);
2957: } else if (!strcmp(command, "free")) {
2958: if (arg[0] == 0) {
2959: xmlMemShow(ctxt->output, 0);
2960: } else {
2961: int len = 0;
2962:
2963: sscanf(arg, "%d", &len);
2964: xmlMemShow(ctxt->output, len);
2965: }
2966: } else if (!strcmp(command, "pwd")) {
2967: char dir[500];
2968:
2969: if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
2970: fprintf(ctxt->output, "%s\n", dir);
2971: } else if (!strcmp(command, "du")) {
1.1.1.2 misho 2972: if (arg[0] == 0) {
2973: xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2974: } else {
2975: ctxt->pctxt->node = ctxt->node;
2976: #ifdef LIBXML_XPATH_ENABLED
2977: ctxt->pctxt->node = ctxt->node;
2978: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2979: #else
2980: list = NULL;
2981: #endif /* LIBXML_XPATH_ENABLED */
2982: if (list != NULL) {
2983: switch (list->type) {
2984: case XPATH_UNDEFINED:
2985: xmlGenericError(xmlGenericErrorContext,
2986: "%s: no such node\n", arg);
2987: break;
2988: case XPATH_NODESET:{
2989: int indx;
2990:
2991: if (list->nodesetval == NULL)
2992: break;
2993:
2994: for (indx = 0;
2995: indx < list->nodesetval->nodeNr;
2996: indx++)
2997: xmlShellDu(ctxt, NULL,
2998: list->nodesetval->
2999: nodeTab[indx], NULL);
3000: break;
3001: }
3002: case XPATH_BOOLEAN:
3003: xmlGenericError(xmlGenericErrorContext,
3004: "%s is a Boolean\n", arg);
3005: break;
3006: case XPATH_NUMBER:
3007: xmlGenericError(xmlGenericErrorContext,
3008: "%s is a number\n", arg);
3009: break;
3010: case XPATH_STRING:
3011: xmlGenericError(xmlGenericErrorContext,
3012: "%s is a string\n", arg);
3013: break;
3014: case XPATH_POINT:
3015: xmlGenericError(xmlGenericErrorContext,
3016: "%s is a point\n", arg);
3017: break;
3018: case XPATH_RANGE:
3019: xmlGenericError(xmlGenericErrorContext,
3020: "%s is a range\n", arg);
3021: break;
3022: case XPATH_LOCATIONSET:
3023: xmlGenericError(xmlGenericErrorContext,
3024: "%s is a range\n", arg);
3025: break;
3026: case XPATH_USERS:
3027: xmlGenericError(xmlGenericErrorContext,
3028: "%s is user-defined\n", arg);
3029: break;
3030: case XPATH_XSLT_TREE:
3031: xmlGenericError(xmlGenericErrorContext,
3032: "%s is an XSLT value tree\n",
3033: arg);
3034: break;
3035: }
3036: #ifdef LIBXML_XPATH_ENABLED
3037: xmlXPathFreeObject(list);
3038: #endif
3039: } else {
3040: xmlGenericError(xmlGenericErrorContext,
3041: "%s: no such node\n", arg);
3042: }
3043: ctxt->pctxt->node = NULL;
3044: }
1.1 misho 3045: } else if (!strcmp(command, "base")) {
3046: xmlShellBase(ctxt, NULL, ctxt->node, NULL);
3047: } else if (!strcmp(command, "set")) {
3048: xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
3049: #ifdef LIBXML_XPATH_ENABLED
3050: } else if (!strcmp(command, "setns")) {
3051: if (arg[0] == 0) {
3052: xmlGenericError(xmlGenericErrorContext,
3053: "setns: prefix=[nsuri] required\n");
3054: } else {
3055: xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
3056: }
3057: } else if (!strcmp(command, "setrootns")) {
3058: xmlNodePtr root;
3059:
3060: root = xmlDocGetRootElement(ctxt->doc);
3061: xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL);
3062: } else if (!strcmp(command, "xpath")) {
3063: if (arg[0] == 0) {
3064: xmlGenericError(xmlGenericErrorContext,
3065: "xpath: expression required\n");
3066: } else {
3067: ctxt->pctxt->node = ctxt->node;
3068: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3069: xmlXPathDebugDumpObject(ctxt->output, list, 0);
3070: xmlXPathFreeObject(list);
3071: }
3072: #endif /* LIBXML_XPATH_ENABLED */
3073: #ifdef LIBXML_TREE_ENABLED
3074: } else if (!strcmp(command, "setbase")) {
3075: xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
3076: #endif
3077: } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
3078: int dir = (!strcmp(command, "dir"));
3079:
3080: if (arg[0] == 0) {
3081: if (dir)
3082: xmlShellDir(ctxt, NULL, ctxt->node, NULL);
3083: else
3084: xmlShellList(ctxt, NULL, ctxt->node, NULL);
3085: } else {
3086: ctxt->pctxt->node = ctxt->node;
3087: #ifdef LIBXML_XPATH_ENABLED
3088: ctxt->pctxt->node = ctxt->node;
3089: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3090: #else
3091: list = NULL;
3092: #endif /* LIBXML_XPATH_ENABLED */
3093: if (list != NULL) {
3094: switch (list->type) {
3095: case XPATH_UNDEFINED:
3096: xmlGenericError(xmlGenericErrorContext,
3097: "%s: no such node\n", arg);
3098: break;
3099: case XPATH_NODESET:{
3100: int indx;
3101:
3102: if (list->nodesetval == NULL)
3103: break;
3104:
3105: for (indx = 0;
3106: indx < list->nodesetval->nodeNr;
3107: indx++) {
3108: if (dir)
3109: xmlShellDir(ctxt, NULL,
3110: list->nodesetval->
3111: nodeTab[indx], NULL);
3112: else
3113: xmlShellList(ctxt, NULL,
3114: list->nodesetval->
3115: nodeTab[indx], NULL);
3116: }
3117: break;
3118: }
3119: case XPATH_BOOLEAN:
3120: xmlGenericError(xmlGenericErrorContext,
3121: "%s is a Boolean\n", arg);
3122: break;
3123: case XPATH_NUMBER:
3124: xmlGenericError(xmlGenericErrorContext,
3125: "%s is a number\n", arg);
3126: break;
3127: case XPATH_STRING:
3128: xmlGenericError(xmlGenericErrorContext,
3129: "%s is a string\n", arg);
3130: break;
3131: case XPATH_POINT:
3132: xmlGenericError(xmlGenericErrorContext,
3133: "%s is a point\n", arg);
3134: break;
3135: case XPATH_RANGE:
3136: xmlGenericError(xmlGenericErrorContext,
3137: "%s is a range\n", arg);
3138: break;
3139: case XPATH_LOCATIONSET:
3140: xmlGenericError(xmlGenericErrorContext,
3141: "%s is a range\n", arg);
3142: break;
3143: case XPATH_USERS:
3144: xmlGenericError(xmlGenericErrorContext,
3145: "%s is user-defined\n", arg);
3146: break;
3147: case XPATH_XSLT_TREE:
3148: xmlGenericError(xmlGenericErrorContext,
3149: "%s is an XSLT value tree\n",
3150: arg);
3151: break;
3152: }
3153: #ifdef LIBXML_XPATH_ENABLED
3154: xmlXPathFreeObject(list);
3155: #endif
3156: } else {
3157: xmlGenericError(xmlGenericErrorContext,
3158: "%s: no such node\n", arg);
3159: }
3160: ctxt->pctxt->node = NULL;
3161: }
1.1.1.2 misho 3162: } else if (!strcmp(command, "whereis")) {
3163: char dir[500];
3164:
3165: if (arg[0] == 0) {
3166: if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
3167: fprintf(ctxt->output, "%s\n", dir);
3168: } else {
3169: ctxt->pctxt->node = ctxt->node;
3170: #ifdef LIBXML_XPATH_ENABLED
3171: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3172: #else
3173: list = NULL;
3174: #endif /* LIBXML_XPATH_ENABLED */
3175: if (list != NULL) {
3176: switch (list->type) {
3177: case XPATH_UNDEFINED:
3178: xmlGenericError(xmlGenericErrorContext,
3179: "%s: no such node\n", arg);
3180: break;
3181: case XPATH_NODESET:{
3182: int indx;
3183:
3184: if (list->nodesetval == NULL)
3185: break;
3186:
3187: for (indx = 0;
3188: indx < list->nodesetval->nodeNr;
3189: indx++) {
3190: if (!xmlShellPwd(ctxt, dir, list->nodesetval->
3191: nodeTab[indx], NULL))
3192: fprintf(ctxt->output, "%s\n", dir);
3193: }
3194: break;
3195: }
3196: case XPATH_BOOLEAN:
3197: xmlGenericError(xmlGenericErrorContext,
3198: "%s is a Boolean\n", arg);
3199: break;
3200: case XPATH_NUMBER:
3201: xmlGenericError(xmlGenericErrorContext,
3202: "%s is a number\n", arg);
3203: break;
3204: case XPATH_STRING:
3205: xmlGenericError(xmlGenericErrorContext,
3206: "%s is a string\n", arg);
3207: break;
3208: case XPATH_POINT:
3209: xmlGenericError(xmlGenericErrorContext,
3210: "%s is a point\n", arg);
3211: break;
3212: case XPATH_RANGE:
3213: xmlGenericError(xmlGenericErrorContext,
3214: "%s is a range\n", arg);
3215: break;
3216: case XPATH_LOCATIONSET:
3217: xmlGenericError(xmlGenericErrorContext,
3218: "%s is a range\n", arg);
3219: break;
3220: case XPATH_USERS:
3221: xmlGenericError(xmlGenericErrorContext,
3222: "%s is user-defined\n", arg);
3223: break;
3224: case XPATH_XSLT_TREE:
3225: xmlGenericError(xmlGenericErrorContext,
3226: "%s is an XSLT value tree\n",
3227: arg);
3228: break;
3229: }
3230: #ifdef LIBXML_XPATH_ENABLED
3231: xmlXPathFreeObject(list);
3232: #endif
3233: } else {
3234: xmlGenericError(xmlGenericErrorContext,
3235: "%s: no such node\n", arg);
3236: }
3237: ctxt->pctxt->node = NULL;
3238: }
1.1 misho 3239: } else if (!strcmp(command, "cd")) {
3240: if (arg[0] == 0) {
3241: ctxt->node = (xmlNodePtr) ctxt->doc;
3242: } else {
3243: #ifdef LIBXML_XPATH_ENABLED
3244: ctxt->pctxt->node = ctxt->node;
3245: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3246: #else
3247: list = NULL;
3248: #endif /* LIBXML_XPATH_ENABLED */
3249: if (list != NULL) {
3250: switch (list->type) {
3251: case XPATH_UNDEFINED:
3252: xmlGenericError(xmlGenericErrorContext,
3253: "%s: no such node\n", arg);
3254: break;
3255: case XPATH_NODESET:
3256: if (list->nodesetval != NULL) {
3257: if (list->nodesetval->nodeNr == 1) {
3258: ctxt->node = list->nodesetval->nodeTab[0];
3259: if ((ctxt->node != NULL) &&
3260: (ctxt->node->type ==
3261: XML_NAMESPACE_DECL)) {
3262: xmlGenericError(xmlGenericErrorContext,
3263: "cannot cd to namespace\n");
3264: ctxt->node = NULL;
3265: }
3266: } else
3267: xmlGenericError(xmlGenericErrorContext,
3268: "%s is a %d Node Set\n",
3269: arg,
3270: list->nodesetval->nodeNr);
3271: } else
3272: xmlGenericError(xmlGenericErrorContext,
3273: "%s is an empty Node Set\n",
3274: arg);
3275: break;
3276: case XPATH_BOOLEAN:
3277: xmlGenericError(xmlGenericErrorContext,
3278: "%s is a Boolean\n", arg);
3279: break;
3280: case XPATH_NUMBER:
3281: xmlGenericError(xmlGenericErrorContext,
3282: "%s is a number\n", arg);
3283: break;
3284: case XPATH_STRING:
3285: xmlGenericError(xmlGenericErrorContext,
3286: "%s is a string\n", arg);
3287: break;
3288: case XPATH_POINT:
3289: xmlGenericError(xmlGenericErrorContext,
3290: "%s is a point\n", arg);
3291: break;
3292: case XPATH_RANGE:
3293: xmlGenericError(xmlGenericErrorContext,
3294: "%s is a range\n", arg);
3295: break;
3296: case XPATH_LOCATIONSET:
3297: xmlGenericError(xmlGenericErrorContext,
3298: "%s is a range\n", arg);
3299: break;
3300: case XPATH_USERS:
3301: xmlGenericError(xmlGenericErrorContext,
3302: "%s is user-defined\n", arg);
3303: break;
3304: case XPATH_XSLT_TREE:
3305: xmlGenericError(xmlGenericErrorContext,
3306: "%s is an XSLT value tree\n",
3307: arg);
3308: break;
3309: }
3310: #ifdef LIBXML_XPATH_ENABLED
3311: xmlXPathFreeObject(list);
3312: #endif
3313: } else {
3314: xmlGenericError(xmlGenericErrorContext,
3315: "%s: no such node\n", arg);
3316: }
3317: ctxt->pctxt->node = NULL;
3318: }
3319: #ifdef LIBXML_OUTPUT_ENABLED
3320: } else if (!strcmp(command, "cat")) {
3321: if (arg[0] == 0) {
3322: xmlShellCat(ctxt, NULL, ctxt->node, NULL);
3323: } else {
3324: ctxt->pctxt->node = ctxt->node;
3325: #ifdef LIBXML_XPATH_ENABLED
3326: ctxt->pctxt->node = ctxt->node;
3327: list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3328: #else
3329: list = NULL;
3330: #endif /* LIBXML_XPATH_ENABLED */
3331: if (list != NULL) {
3332: switch (list->type) {
3333: case XPATH_UNDEFINED:
3334: xmlGenericError(xmlGenericErrorContext,
3335: "%s: no such node\n", arg);
3336: break;
3337: case XPATH_NODESET:{
3338: int indx;
3339:
3340: if (list->nodesetval == NULL)
3341: break;
3342:
3343: for (indx = 0;
3344: indx < list->nodesetval->nodeNr;
3345: indx++) {
3346: if (i > 0)
3347: fprintf(ctxt->output, " -------\n");
3348: xmlShellCat(ctxt, NULL,
3349: list->nodesetval->
3350: nodeTab[indx], NULL);
3351: }
3352: break;
3353: }
3354: case XPATH_BOOLEAN:
3355: xmlGenericError(xmlGenericErrorContext,
3356: "%s is a Boolean\n", arg);
3357: break;
3358: case XPATH_NUMBER:
3359: xmlGenericError(xmlGenericErrorContext,
3360: "%s is a number\n", arg);
3361: break;
3362: case XPATH_STRING:
3363: xmlGenericError(xmlGenericErrorContext,
3364: "%s is a string\n", arg);
3365: break;
3366: case XPATH_POINT:
3367: xmlGenericError(xmlGenericErrorContext,
3368: "%s is a point\n", arg);
3369: break;
3370: case XPATH_RANGE:
3371: xmlGenericError(xmlGenericErrorContext,
3372: "%s is a range\n", arg);
3373: break;
3374: case XPATH_LOCATIONSET:
3375: xmlGenericError(xmlGenericErrorContext,
3376: "%s is a range\n", arg);
3377: break;
3378: case XPATH_USERS:
3379: xmlGenericError(xmlGenericErrorContext,
3380: "%s is user-defined\n", arg);
3381: break;
3382: case XPATH_XSLT_TREE:
3383: xmlGenericError(xmlGenericErrorContext,
3384: "%s is an XSLT value tree\n",
3385: arg);
3386: break;
3387: }
3388: #ifdef LIBXML_XPATH_ENABLED
3389: xmlXPathFreeObject(list);
3390: #endif
3391: } else {
3392: xmlGenericError(xmlGenericErrorContext,
3393: "%s: no such node\n", arg);
3394: }
3395: ctxt->pctxt->node = NULL;
3396: }
3397: #endif /* LIBXML_OUTPUT_ENABLED */
3398: } else {
3399: xmlGenericError(xmlGenericErrorContext,
3400: "Unknown command %s\n", command);
3401: }
3402: free(cmdline); /* not xmlFree here ! */
3403: cmdline = NULL;
3404: }
3405: #ifdef LIBXML_XPATH_ENABLED
3406: xmlXPathFreeContext(ctxt->pctxt);
3407: #endif /* LIBXML_XPATH_ENABLED */
3408: if (ctxt->loaded) {
3409: xmlFreeDoc(ctxt->doc);
3410: }
3411: if (ctxt->filename != NULL)
3412: xmlFree(ctxt->filename);
3413: xmlFree(ctxt);
3414: if (cmdline != NULL)
3415: free(cmdline); /* not xmlFree here ! */
3416: }
3417:
3418: #endif /* LIBXML_XPATH_ENABLED */
3419: #define bottom_debugXML
3420: #include "elfgcchack.h"
3421: #endif /* LIBXML_DEBUG_ENABLED */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>