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