File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / debugXML.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:22:19 2013 UTC (10 years, 11 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_8_0p0, v2_8_0, HEAD
2.8.0

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

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