File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / debugXML.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 19:53:29 2014 UTC (10 years ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_9_1p0, v2_9_1, HEAD
libxml2 2.9.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>