Annotation of XML/debugXML.c, revision 1.28

1.1       daniel      1: /*
                      2:  * debugXML.c : This is a set of routines used for debugging the tree
                      3:  *              produced by the XML parser.
                      4:  *
1.2       daniel      5:  * See Copyright for the status of this software.
                      6:  *
1.1       daniel      7:  * Daniel Veillard <Daniel.Veillard@w3.org>
                      8:  */
                      9: 
1.11      daniel     10: #ifdef WIN32
                     11: #include "win32config.h"
                     12: #else
                     13: #include "config.h"
                     14: #endif
1.23      daniel     15: 
                     16: #include "xmlversion.h"
                     17: #ifdef LIBXML_DEBUG_ENABLED
                     18: 
1.1       daniel     19: #include <stdio.h>
1.26      veillard   20: #include <string.h>
1.12      daniel     21: #ifdef HAVE_STDLIB_H
                     22: #include <stdlib.h>
                     23: #endif
1.14      daniel     24: #ifdef HAVE_STRING_H
                     25: #include <string.h>
                     26: #endif
1.23      daniel     27: #include <libxml/xmlmemory.h>
                     28: #include <libxml/tree.h>
                     29: #include <libxml/parser.h>
                     30: #include <libxml/valid.h>
                     31: #include <libxml/debugXML.h>
                     32: #include <libxml/HTMLtree.h>
                     33: #include <libxml/HTMLparser.h>
1.1       daniel     34: 
                     35: #define IS_BLANK(c)                                                    \
                     36:   (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
                     37: 
1.6       daniel     38: void xmlDebugDumpString(FILE *output, const xmlChar *str) {
1.1       daniel     39:     int i;
                     40:     for (i = 0;i < 40;i++)
                     41:         if (str[i] == 0) return;
                     42:        else if (IS_BLANK(str[i])) fputc(' ', output);
1.27      veillard   43:        else if (str[i] >= 0x80)
                     44:             fprintf(output, "#%X", str[i]);
1.1       daniel     45:        else fputc(str[i], output);
                     46:     fprintf(output, "...");
                     47: }
                     48: 
1.18      daniel     49: void xmlDebugDumpDtd(FILE *output, xmlDtdPtr dtd, int depth) {
                     50:     int i;
                     51:     char shift[100];
                     52: 
                     53:     for (i = 0;((i < depth) && (i < 25));i++)
                     54:         shift[2 * i] = shift[2 * i + 1] = ' ';
                     55:     shift[2 * i] = shift[2 * i + 1] = 0;
                     56: 
                     57:     fprintf(output, shift);
                     58: 
                     59:     if (dtd->type != XML_DTD_NODE) {
                     60:        fprintf(output, "PBM: not a DTD\n");
                     61:        return;
                     62:     }
                     63:     if (dtd->name != NULL)
                     64:        fprintf(output, "DTD(%s)", dtd->name);
                     65:     else
                     66:        fprintf(output, "DTD");
                     67:     if (dtd->ExternalID != NULL)
                     68:        fprintf(output, ", PUBLIC %s", dtd->ExternalID);
                     69:     if (dtd->SystemID != NULL)
                     70:        fprintf(output, ", SYSTEM %s", dtd->SystemID);
                     71:     fprintf(output, "\n");
                     72:     /*
                     73:      * Do a bit of checking
                     74:      */
                     75:     if (dtd->parent == NULL)
                     76:        fprintf(output, "PBM: Dtd has no parent\n");
                     77:     if (dtd->doc == NULL)
                     78:        fprintf(output, "PBM: Dtd has no doc\n");
                     79:     if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
                     80:        fprintf(output, "PBM: Dtd doc differs from parent's one\n");
                     81:     if (dtd->prev == NULL) {
                     82:        if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
                     83:            fprintf(output, "PBM: Dtd has no prev and not first of list\n");
                     84:     } else {
                     85:        if (dtd->prev->next != (xmlNodePtr) dtd)
                     86:            fprintf(output, "PBM: Dtd prev->next : back link wrong\n");
                     87:     }
                     88:     if (dtd->next == NULL) {
                     89:        if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
                     90:            fprintf(output, "PBM: Dtd has no next and not last of list\n");
                     91:     } else {
                     92:        if (dtd->next->prev != (xmlNodePtr) dtd)
                     93:            fprintf(output, "PBM: Dtd next->prev : forward link wrong\n");
                     94:     }
                     95: }
                     96: 
                     97: void xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
                     98:     int i;
                     99:     char shift[100];
                    100: 
                    101:     for (i = 0;((i < depth) && (i < 25));i++)
                    102:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    103:     shift[2 * i] = shift[2 * i + 1] = 0;
                    104: 
                    105:     fprintf(output, shift);
                    106: 
                    107:     if (attr->type != XML_ATTRIBUTE_DECL) {
                    108:        fprintf(output, "PBM: not a Attr\n");
                    109:        return;
                    110:     }
                    111:     if (attr->name != NULL)
                    112:        fprintf(output, "ATTRDECL(%s)", attr->name);
                    113:     else
                    114:        fprintf(output, "PBM ATTRDECL noname!!!");
                    115:     if (attr->elem != NULL)
                    116:        fprintf(output, " for %s", attr->elem);
                    117:     else
                    118:        fprintf(output, " PBM noelem!!!");
                    119:     switch (attr->atype) {
                    120:         case XML_ATTRIBUTE_CDATA:
                    121:            fprintf(output, " CDATA");
                    122:            break;
                    123:         case XML_ATTRIBUTE_ID:
                    124:            fprintf(output, " ID");
                    125:            break;
                    126:         case XML_ATTRIBUTE_IDREF:
                    127:            fprintf(output, " IDREF");
                    128:            break;
                    129:         case XML_ATTRIBUTE_IDREFS:
                    130:            fprintf(output, " IDREFS");
                    131:            break;
                    132:         case XML_ATTRIBUTE_ENTITY:
                    133:            fprintf(output, " ENTITY");
                    134:            break;
                    135:         case XML_ATTRIBUTE_ENTITIES:
                    136:            fprintf(output, " ENTITIES");
                    137:            break;
                    138:         case XML_ATTRIBUTE_NMTOKEN:
                    139:            fprintf(output, " NMTOKEN");
                    140:            break;
                    141:         case XML_ATTRIBUTE_NMTOKENS:
                    142:            fprintf(output, " NMTOKENS");
                    143:            break;
                    144:         case XML_ATTRIBUTE_ENUMERATION:
                    145:            fprintf(output, " ENUMERATION");
                    146:            break;
                    147:         case XML_ATTRIBUTE_NOTATION:
                    148:            fprintf(output, " NOTATION ");
                    149:            break;
                    150:     }
                    151:     if (attr->tree != NULL) {
                    152:        int i;
                    153:        xmlEnumerationPtr cur = attr->tree;
                    154: 
                    155:        for (i = 0;i < 5; i++) {
                    156:            if (i != 0)
                    157:                fprintf(output, "|%s", cur->name);
                    158:            else
                    159:                fprintf(output, " (%s", cur->name);
                    160:            cur = cur->next;
                    161:            if (cur == NULL) break;
                    162:        }
                    163:        if (cur == NULL)
                    164:            fprintf(output, ")");
                    165:        else
                    166:            fprintf(output, "...)");
                    167:     }
                    168:     switch (attr->def) {
                    169:         case XML_ATTRIBUTE_NONE:
                    170:            break;
                    171:         case XML_ATTRIBUTE_REQUIRED:
                    172:            fprintf(output, " REQUIRED");
                    173:            break;
                    174:         case XML_ATTRIBUTE_IMPLIED:
                    175:            fprintf(output, " IMPLIED");
                    176:            break;
                    177:         case XML_ATTRIBUTE_FIXED:
                    178:            fprintf(output, " FIXED");
                    179:            break;
                    180:     }
                    181:     if (attr->defaultValue != NULL) {
                    182:        fprintf(output, "\"");
                    183:        xmlDebugDumpString(output, attr->defaultValue);
                    184:        fprintf(output, "\"");
                    185:     }
                    186:     printf("\n");
                    187: 
                    188:     /*
                    189:      * Do a bit of checking
                    190:      */
                    191:     if (attr->parent == NULL)
                    192:        fprintf(output, "PBM: Attr has no parent\n");
                    193:     if (attr->doc == NULL)
                    194:        fprintf(output, "PBM: Attr has no doc\n");
                    195:     if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
                    196:        fprintf(output, "PBM: Attr doc differs from parent's one\n");
                    197:     if (attr->prev == NULL) {
                    198:        if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
                    199:            fprintf(output, "PBM: Attr has no prev and not first of list\n");
                    200:     } else {
                    201:        if (attr->prev->next != (xmlNodePtr) attr)
                    202:            fprintf(output, "PBM: Attr prev->next : back link wrong\n");
                    203:     }
                    204:     if (attr->next == NULL) {
                    205:        if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
                    206:            fprintf(output, "PBM: Attr has no next and not last of list\n");
                    207:     } else {
                    208:        if (attr->next->prev != (xmlNodePtr) attr)
                    209:            fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
                    210:     }
                    211: }
                    212: 
                    213: void xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
                    214:     int i;
                    215:     char shift[100];
                    216: 
                    217:     for (i = 0;((i < depth) && (i < 25));i++)
                    218:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    219:     shift[2 * i] = shift[2 * i + 1] = 0;
                    220: 
                    221:     fprintf(output, shift);
                    222: 
                    223:     if (elem->type != XML_ELEMENT_DECL) {
                    224:        fprintf(output, "PBM: not a Elem\n");
                    225:        return;
                    226:     }
1.27      veillard  227:     if (elem->name != NULL) {
                    228:        fprintf(output, "ELEMDECL(");
                    229:        xmlDebugDumpString(output, elem->name);
                    230:        fprintf(output, ")");
                    231:     } else
1.18      daniel    232:        fprintf(output, "PBM ELEMDECL noname!!!");
                    233:     switch (elem->etype) {
                    234:        case XML_ELEMENT_TYPE_EMPTY: 
                    235:            fprintf(output, ", EMPTY");
                    236:            break;
                    237:        case XML_ELEMENT_TYPE_ANY: 
                    238:            fprintf(output, ", ANY");
                    239:            break;
                    240:        case XML_ELEMENT_TYPE_MIXED: 
                    241:            fprintf(output, ", MIXED ");
                    242:            break;
                    243:        case XML_ELEMENT_TYPE_ELEMENT: 
                    244:            fprintf(output, ", MIXED ");
                    245:            break;
                    246:     }
                    247:     if (elem->content != NULL) {
                    248:        char buf[1001];
                    249: 
                    250:        buf[0] = 0;
                    251:        xmlSprintfElementContent(buf, elem->content, 1);
                    252:        buf[1000] = 0;
                    253:        fprintf(output, "%s", buf);
                    254:     }
                    255:     printf("\n");
                    256: 
                    257:     /*
                    258:      * Do a bit of checking
                    259:      */
                    260:     if (elem->parent == NULL)
                    261:        fprintf(output, "PBM: Elem has no parent\n");
                    262:     if (elem->doc == NULL)
                    263:        fprintf(output, "PBM: Elem has no doc\n");
                    264:     if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
                    265:        fprintf(output, "PBM: Elem doc differs from parent's one\n");
                    266:     if (elem->prev == NULL) {
                    267:        if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
                    268:            fprintf(output, "PBM: Elem has no prev and not first of list\n");
                    269:     } else {
                    270:        if (elem->prev->next != (xmlNodePtr) elem)
                    271:            fprintf(output, "PBM: Elem prev->next : back link wrong\n");
                    272:     }
                    273:     if (elem->next == NULL) {
                    274:        if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
                    275:            fprintf(output, "PBM: Elem has no next and not last of list\n");
                    276:     } else {
                    277:        if (elem->next->prev != (xmlNodePtr) elem)
                    278:            fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
                    279:     }
                    280: }
                    281: 
1.20      daniel    282: void xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
                    283:     int i;
                    284:     char shift[100];
                    285: 
                    286:     for (i = 0;((i < depth) && (i < 25));i++)
                    287:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    288:     shift[2 * i] = shift[2 * i + 1] = 0;
                    289: 
                    290:     fprintf(output, shift);
                    291: 
                    292:     if (ent->type != XML_ENTITY_DECL) {
                    293:        fprintf(output, "PBM: not a Entity decl\n");
                    294:        return;
                    295:     }
1.27      veillard  296:     if (ent->name != NULL) {
                    297:        fprintf(output, "ENTITYDECL(");
                    298:        xmlDebugDumpString(output, ent->name);
                    299:        fprintf(output, ")");
                    300:     } else
1.20      daniel    301:        fprintf(output, "PBM ENTITYDECL noname!!!");
                    302:     switch (ent->etype) {
                    303:        case XML_INTERNAL_GENERAL_ENTITY: 
                    304:            fprintf(output, ", internal\n");
                    305:            break;
                    306:        case XML_EXTERNAL_GENERAL_PARSED_ENTITY: 
                    307:            fprintf(output, ", external parsed\n");
                    308:            break;
                    309:        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: 
                    310:            fprintf(output, ", unparsed\n");
                    311:            break;
                    312:        case XML_INTERNAL_PARAMETER_ENTITY: 
                    313:            fprintf(output, ", parameter\n");
                    314:            break;
                    315:        case XML_EXTERNAL_PARAMETER_ENTITY: 
                    316:            fprintf(output, ", external parameter\n");
                    317:            break;
                    318:        case XML_INTERNAL_PREDEFINED_ENTITY: 
                    319:            fprintf(output, ", predefined\n");
                    320:            break;
                    321:     }
                    322:     if (ent->ExternalID) {
                    323:         fprintf(output, shift);
                    324:         fprintf(output, "ExternalID=%s\n", ent->ExternalID);
                    325:     }
                    326:     if (ent->SystemID) {
                    327:         fprintf(output, shift);
                    328:         fprintf(output, "SystemID=%s\n", ent->SystemID);
                    329:     }
                    330:     if (ent->content) {
                    331:         fprintf(output, shift);
                    332:        fprintf(output, "content=");
                    333:        xmlDebugDumpString(output, ent->content);
                    334:        fprintf(output, "\n");
                    335:     }
                    336: 
                    337:     /*
                    338:      * Do a bit of checking
                    339:      */
                    340:     if (ent->parent == NULL)
                    341:        fprintf(output, "PBM: Ent has no parent\n");
                    342:     if (ent->doc == NULL)
                    343:        fprintf(output, "PBM: Ent has no doc\n");
                    344:     if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
                    345:        fprintf(output, "PBM: Ent doc differs from parent's one\n");
                    346:     if (ent->prev == NULL) {
                    347:        if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
                    348:            fprintf(output, "PBM: Ent has no prev and not first of list\n");
                    349:     } else {
                    350:        if (ent->prev->next != (xmlNodePtr) ent)
                    351:            fprintf(output, "PBM: Ent prev->next : back link wrong\n");
                    352:     }
                    353:     if (ent->next == NULL) {
                    354:        if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
                    355:            fprintf(output, "PBM: Ent has no next and not last of list\n");
                    356:     } else {
                    357:        if (ent->next->prev != (xmlNodePtr) ent)
                    358:            fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
                    359:     }
                    360: }
                    361: 
1.1       daniel    362: void xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
                    363:     int i;
                    364:     char shift[100];
                    365: 
                    366:     for (i = 0;((i < depth) && (i < 25));i++)
                    367:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    368:     shift[2 * i] = shift[2 * i + 1] = 0;
                    369: 
                    370:     fprintf(output, shift);
                    371:     if (ns->type == XML_GLOBAL_NAMESPACE)
                    372:         fprintf(output, "old ");
1.10      daniel    373:     if (ns->prefix != NULL)
                    374:        fprintf(output, "namespace %s href=", ns->prefix);
                    375:     else
1.12      daniel    376:        fprintf(output, "default namespace href=");
1.10      daniel    377: 
1.1       daniel    378:     xmlDebugDumpString(output, ns->href);
                    379:     fprintf(output, "\n");
                    380: }
                    381: 
                    382: void xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
                    383:     while (ns != NULL) {
                    384:         xmlDebugDumpNamespace(output, ns, depth);
                    385:        ns = ns->next;
                    386:     }
                    387: }
                    388: 
                    389: void xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
                    390:     int i;
                    391:     char shift[100];
                    392: 
                    393:     for (i = 0;((i < depth) && (i < 25));i++)
                    394:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    395:     shift[2 * i] = shift[2 * i + 1] = 0;
                    396: 
                    397:     fprintf(output, shift);
1.19      daniel    398:     switch (ent->etype) {
1.1       daniel    399:         case XML_INTERNAL_GENERAL_ENTITY:
                    400:            fprintf(output, "INTERNAL_GENERAL_ENTITY ");
                    401:            break;
                    402:         case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    403:            fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
                    404:            break;
                    405:         case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    406:            fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
                    407:            break;
                    408:         case XML_INTERNAL_PARAMETER_ENTITY:
                    409:            fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
                    410:            break;
                    411:         case XML_EXTERNAL_PARAMETER_ENTITY:
                    412:            fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
                    413:            break;
                    414:        default:
1.19      daniel    415:            fprintf(output, "ENTITY_%d ! ", ent->etype);
1.1       daniel    416:     }
                    417:     fprintf(output, "%s\n", ent->name);
                    418:     if (ent->ExternalID) {
                    419:         fprintf(output, shift);
                    420:         fprintf(output, "ExternalID=%s\n", ent->ExternalID);
                    421:     }
                    422:     if (ent->SystemID) {
                    423:         fprintf(output, shift);
                    424:         fprintf(output, "SystemID=%s\n", ent->SystemID);
                    425:     }
                    426:     if (ent->content) {
                    427:         fprintf(output, shift);
                    428:        fprintf(output, "content=");
                    429:        xmlDebugDumpString(output, ent->content);
                    430:        fprintf(output, "\n");
                    431:     }
                    432: }
                    433: 
                    434: void xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
                    435:     int i;
                    436:     char shift[100];
                    437: 
                    438:     for (i = 0;((i < depth) && (i < 25));i++)
                    439:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    440:     shift[2 * i] = shift[2 * i + 1] = 0;
                    441: 
                    442:     fprintf(output, shift);
1.18      daniel    443: 
1.27      veillard  444:     fprintf(output, "ATTRIBUTE ");
                    445:     xmlDebugDumpString(output, attr->name);
                    446:     fprintf(output, "\n");
1.16      daniel    447:     if (attr->children != NULL) 
                    448:         xmlDebugDumpNodeList(output, attr->children, depth + 1);
1.18      daniel    449: 
                    450:     /*
                    451:      * Do a bit of checking
                    452:      */
                    453:     if (attr->parent == NULL)
                    454:        fprintf(output, "PBM: Attr has no parent\n");
                    455:     if (attr->doc == NULL)
                    456:        fprintf(output, "PBM: Attr has no doc\n");
                    457:     if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
                    458:        fprintf(output, "PBM: Attr doc differs from parent's one\n");
                    459:     if (attr->prev == NULL) {
                    460:        if ((attr->parent != NULL) && (attr->parent->properties != attr))
                    461:            fprintf(output, "PBM: Attr has no prev and not first of list\n");
                    462:     } else {
                    463:        if (attr->prev->next != attr)
                    464:            fprintf(output, "PBM: Attr prev->next : back link wrong\n");
                    465:     }
                    466:     if (attr->next != NULL) {
                    467:        if (attr->next->prev != attr)
                    468:            fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
                    469:     }
1.1       daniel    470: }
                    471: 
                    472: void xmlDebugDumpAttrList(FILE *output, xmlAttrPtr attr, int depth) {
                    473:     while (attr != NULL) {
                    474:         xmlDebugDumpAttr(output, attr, depth);
                    475:        attr = attr->next;
                    476:     }
                    477: }
                    478: 
1.3       daniel    479: void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) {
1.1       daniel    480:     int i;
                    481:     char shift[100];
                    482: 
                    483:     for (i = 0;((i < depth) && (i < 25));i++)
                    484:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    485:     shift[2 * i] = shift[2 * i + 1] = 0;
                    486: 
                    487:     switch (node->type) {
                    488:        case XML_ELEMENT_NODE:
1.21      daniel    489:            fprintf(output, shift);
1.1       daniel    490:            fprintf(output, "ELEMENT ");
1.27      veillard  491:            if (node->ns != NULL) {
                    492:                xmlDebugDumpString(output, node->ns->prefix);
                    493:                fprintf(output, ":");
                    494:            }
                    495:            xmlDebugDumpString(output, node->name);
                    496:            fprintf(output, "\n");
1.1       daniel    497:            break;
                    498:        case XML_ATTRIBUTE_NODE:
1.21      daniel    499:            fprintf(output, shift);
1.1       daniel    500:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    501:            break;
                    502:        case XML_TEXT_NODE:
1.21      daniel    503:            fprintf(output, shift);
1.1       daniel    504:            fprintf(output, "TEXT\n");
                    505:            break;
                    506:        case XML_CDATA_SECTION_NODE:
1.21      daniel    507:            fprintf(output, shift);
1.1       daniel    508:            fprintf(output, "CDATA_SECTION\n");
                    509:            break;
                    510:        case XML_ENTITY_REF_NODE:
1.21      daniel    511:            fprintf(output, shift);
1.15      daniel    512:            fprintf(output, "ENTITY_REF(%s)\n", node->name);
1.1       daniel    513:            break;
                    514:        case XML_ENTITY_NODE:
1.21      daniel    515:            fprintf(output, shift);
1.1       daniel    516:            fprintf(output, "ENTITY\n");
                    517:            break;
                    518:        case XML_PI_NODE:
1.21      daniel    519:            fprintf(output, shift);
1.4       daniel    520:            fprintf(output, "PI %s\n", node->name);
1.1       daniel    521:            break;
                    522:        case XML_COMMENT_NODE:
1.21      daniel    523:            fprintf(output, shift);
1.1       daniel    524:            fprintf(output, "COMMENT\n");
                    525:            break;
                    526:        case XML_DOCUMENT_NODE:
1.7       daniel    527:        case XML_HTML_DOCUMENT_NODE:
1.21      daniel    528:            fprintf(output, shift);
1.1       daniel    529:            fprintf(output, "Error, DOCUMENT found here\n");
                    530:            break;
                    531:        case XML_DOCUMENT_TYPE_NODE:
1.21      daniel    532:            fprintf(output, shift);
1.1       daniel    533:            fprintf(output, "DOCUMENT_TYPE\n");
                    534:            break;
                    535:        case XML_DOCUMENT_FRAG_NODE:
1.21      daniel    536:            fprintf(output, shift);
1.1       daniel    537:            fprintf(output, "DOCUMENT_FRAG\n");
                    538:            break;
                    539:        case XML_NOTATION_NODE:
                    540:            fprintf(output, "NOTATION\n");
                    541:            break;
1.18      daniel    542:        case XML_DTD_NODE:
1.21      daniel    543:            xmlDebugDumpDtd(output, (xmlDtdPtr) node, depth);
1.18      daniel    544:            return;
                    545:        case XML_ELEMENT_DECL:
1.21      daniel    546:            xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
1.18      daniel    547:            return;
                    548:        case XML_ATTRIBUTE_DECL:
1.21      daniel    549:            xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
1.18      daniel    550:            return;
1.20      daniel    551:         case XML_ENTITY_DECL:
1.21      daniel    552:            xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
1.20      daniel    553:            return;
1.1       daniel    554:        default:
1.21      daniel    555:            fprintf(output, shift);
1.1       daniel    556:            fprintf(output, "NODE_%d\n", node->type);
                    557:     }
                    558:     if (node->doc == NULL) {
                    559:         fprintf(output, shift);
                    560:        fprintf(output, "doc == NULL !!!\n");
                    561:     }
                    562:     if (node->nsDef != NULL) 
                    563:         xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
                    564:     if (node->properties != NULL)
                    565:        xmlDebugDumpAttrList(output, node->properties, depth + 1);
                    566:     if (node->type != XML_ENTITY_REF_NODE) {
                    567:        if (node->content != NULL) {
                    568:            fprintf(output, shift);
                    569:            fprintf(output, "content=");
1.8       daniel    570: #ifndef XML_USE_BUFFER_CONTENT     
1.1       daniel    571:            xmlDebugDumpString(output, node->content);
1.8       daniel    572: #else
                    573:            xmlDebugDumpString(output, xmlBufferContent(node->content));
                    574: #endif
1.1       daniel    575:            fprintf(output, "\n");
                    576:        }
                    577:     } else {
                    578:         xmlEntityPtr ent;
                    579:        ent = xmlGetDocEntity(node->doc, node->name);
                    580:        if (ent != NULL)
                    581:            xmlDebugDumpEntity(output, ent, depth + 1);
1.18      daniel    582:     }
                    583:     /*
                    584:      * Do a bit of checking
                    585:      */
                    586:     if (node->parent == NULL)
                    587:        fprintf(output, "PBM: Node has no parent\n");
                    588:     if (node->doc == NULL)
                    589:        fprintf(output, "PBM: Node has no doc\n");
                    590:     if ((node->parent != NULL) && (node->doc != node->parent->doc))
                    591:        fprintf(output, "PBM: Node doc differs from parent's one\n");
                    592:     if (node->prev == NULL) {
                    593:        if ((node->parent != NULL) && (node->parent->children != node))
                    594:            fprintf(output, "PBM: Node has no prev and not first of list\n");
                    595:     } else {
                    596:        if (node->prev->next != node)
                    597:            fprintf(output, "PBM: Node prev->next : back link wrong\n");
                    598:     }
                    599:     if (node->next == NULL) {
                    600:        if ((node->parent != NULL) && (node->parent->last != node))
                    601:            fprintf(output, "PBM: Node has no next and not last of list\n");
                    602:     } else {
                    603:        if (node->next->prev != node)
                    604:            fprintf(output, "PBM: Node next->prev : forward link wrong\n");
1.1       daniel    605:     }
1.3       daniel    606: }
                    607: 
                    608: void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth) {
                    609:     xmlDebugDumpOneNode(output, node, depth);
1.16      daniel    610:     if (node->children != NULL)
                    611:        xmlDebugDumpNodeList(output, node->children, depth + 1);
1.1       daniel    612: }
                    613: 
                    614: void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth) {
                    615:     while (node != NULL) {
                    616:         xmlDebugDumpNode(output, node, depth);
                    617:        node = node->next;
                    618:     }
                    619: }
                    620: 
                    621: 
1.12      daniel    622: void xmlDebugDumpDocumentHead(FILE *output, xmlDocPtr doc) {
1.1       daniel    623:     if (output == NULL) output = stdout;
                    624:     if (doc == NULL) {
                    625:         fprintf(output, "DOCUMENT == NULL !\n");
                    626:        return;
                    627:     }
                    628: 
                    629:     switch (doc->type) {
                    630:        case XML_ELEMENT_NODE:
                    631:            fprintf(output, "Error, ELEMENT found here ");
                    632:            break;
                    633:        case XML_ATTRIBUTE_NODE:
                    634:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    635:            break;
                    636:        case XML_TEXT_NODE:
                    637:            fprintf(output, "Error, TEXT\n");
                    638:            break;
                    639:        case XML_CDATA_SECTION_NODE:
                    640:            fprintf(output, "Error, CDATA_SECTION\n");
                    641:            break;
                    642:        case XML_ENTITY_REF_NODE:
                    643:            fprintf(output, "Error, ENTITY_REF\n");
                    644:            break;
                    645:        case XML_ENTITY_NODE:
                    646:            fprintf(output, "Error, ENTITY\n");
                    647:            break;
                    648:        case XML_PI_NODE:
                    649:            fprintf(output, "Error, PI\n");
                    650:            break;
                    651:        case XML_COMMENT_NODE:
                    652:            fprintf(output, "Error, COMMENT\n");
                    653:            break;
                    654:        case XML_DOCUMENT_NODE:
                    655:            fprintf(output, "DOCUMENT\n");
1.7       daniel    656:            break;
                    657:        case XML_HTML_DOCUMENT_NODE:
                    658:            fprintf(output, "HTML DOCUMENT\n");
1.1       daniel    659:            break;
                    660:        case XML_DOCUMENT_TYPE_NODE:
                    661:            fprintf(output, "Error, DOCUMENT_TYPE\n");
                    662:            break;
                    663:        case XML_DOCUMENT_FRAG_NODE:
                    664:            fprintf(output, "Error, DOCUMENT_FRAG\n");
                    665:            break;
                    666:        case XML_NOTATION_NODE:
                    667:            fprintf(output, "Error, NOTATION\n");
                    668:            break;
                    669:        default:
                    670:            fprintf(output, "NODE_%d\n", doc->type);
                    671:     }
                    672:     if (doc->name != NULL) {
                    673:        fprintf(output, "name=");
1.5       daniel    674:         xmlDebugDumpString(output, BAD_CAST doc->name);
1.1       daniel    675:        fprintf(output, "\n");
                    676:     }
                    677:     if (doc->version != NULL) {
                    678:        fprintf(output, "version=");
                    679:         xmlDebugDumpString(output, doc->version);
                    680:        fprintf(output, "\n");
                    681:     }
                    682:     if (doc->encoding != NULL) {
                    683:        fprintf(output, "encoding=");
                    684:         xmlDebugDumpString(output, doc->encoding);
                    685:        fprintf(output, "\n");
                    686:     }
                    687:     if (doc->standalone)
                    688:         fprintf(output, "standalone=true\n");
                    689:     if (doc->oldNs != NULL) 
                    690:         xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
1.12      daniel    691: }
                    692: 
                    693: void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
                    694:     if (output == NULL) output = stdout;
                    695:     if (doc == NULL) {
                    696:         fprintf(output, "DOCUMENT == NULL !\n");
                    697:        return;
                    698:     }
                    699:     xmlDebugDumpDocumentHead(output, doc);
                    700:     if (((doc->type == XML_DOCUMENT_NODE) ||
                    701:          (doc->type == XML_HTML_DOCUMENT_NODE)) &&
1.16      daniel    702:         (doc->children != NULL))
                    703:         xmlDebugDumpNodeList(output, doc->children, 1);
1.12      daniel    704: }    
1.9       daniel    705: 
                    706: void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
                    707:     int i;
                    708:     xmlEntityPtr cur;
                    709: 
                    710:     if (output == NULL) output = stdout;
                    711:     if (doc == NULL) {
                    712:         fprintf(output, "DOCUMENT == NULL !\n");
                    713:        return;
                    714:     }
                    715: 
                    716:     switch (doc->type) {
                    717:        case XML_ELEMENT_NODE:
                    718:            fprintf(output, "Error, ELEMENT found here ");
                    719:            break;
                    720:        case XML_ATTRIBUTE_NODE:
                    721:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    722:            break;
                    723:        case XML_TEXT_NODE:
                    724:            fprintf(output, "Error, TEXT\n");
                    725:            break;
                    726:        case XML_CDATA_SECTION_NODE:
                    727:            fprintf(output, "Error, CDATA_SECTION\n");
                    728:            break;
                    729:        case XML_ENTITY_REF_NODE:
                    730:            fprintf(output, "Error, ENTITY_REF\n");
                    731:            break;
                    732:        case XML_ENTITY_NODE:
                    733:            fprintf(output, "Error, ENTITY\n");
                    734:            break;
                    735:        case XML_PI_NODE:
                    736:            fprintf(output, "Error, PI\n");
                    737:            break;
                    738:        case XML_COMMENT_NODE:
                    739:            fprintf(output, "Error, COMMENT\n");
                    740:            break;
                    741:        case XML_DOCUMENT_NODE:
                    742:            fprintf(output, "DOCUMENT\n");
                    743:            break;
                    744:        case XML_HTML_DOCUMENT_NODE:
                    745:            fprintf(output, "HTML DOCUMENT\n");
                    746:            break;
                    747:        case XML_DOCUMENT_TYPE_NODE:
                    748:            fprintf(output, "Error, DOCUMENT_TYPE\n");
                    749:            break;
                    750:        case XML_DOCUMENT_FRAG_NODE:
                    751:            fprintf(output, "Error, DOCUMENT_FRAG\n");
                    752:            break;
                    753:        case XML_NOTATION_NODE:
                    754:            fprintf(output, "Error, NOTATION\n");
                    755:            break;
                    756:        default:
                    757:            fprintf(output, "NODE_%d\n", doc->type);
                    758:     }
                    759:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                    760:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
                    761:                                    doc->intSubset->entities;
                    762:        fprintf(output, "Entities in internal subset\n");
1.28    ! veillard  763:        for (i = 0;i < table->max_entities;i++) {
1.20      daniel    764:            cur = table->table[i];
1.28    ! veillard  765:            while (cur != NULL) {
        !           766:                fprintf(output, "%d : %s : ", i, cur->name);
        !           767:                switch (cur->etype) {
        !           768:                    case XML_INTERNAL_GENERAL_ENTITY:
        !           769:                        fprintf(output, "INTERNAL GENERAL, ");
        !           770:                        break;
        !           771:                    case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
        !           772:                        fprintf(output, "EXTERNAL PARSED, ");
        !           773:                        break;
        !           774:                    case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
        !           775:                        fprintf(output, "EXTERNAL UNPARSED, ");
        !           776:                        break;
        !           777:                    case XML_INTERNAL_PARAMETER_ENTITY:
        !           778:                        fprintf(output, "INTERNAL PARAMETER, ");
        !           779:                        break;
        !           780:                    case XML_EXTERNAL_PARAMETER_ENTITY:
        !           781:                        fprintf(output, "EXTERNAL PARAMETER, ");
        !           782:                        break;
        !           783:                    default:
        !           784:                        fprintf(output, "UNKNOWN TYPE %d",
        !           785:                                cur->etype);
        !           786:                }
        !           787:                if (cur->ExternalID != NULL) 
        !           788:                    fprintf(output, "ID \"%s\"", cur->ExternalID);
        !           789:                if (cur->SystemID != NULL)
        !           790:                    fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
        !           791:                if (cur->orig != NULL)
        !           792:                    fprintf(output, "\n orig \"%s\"", cur->orig);
        !           793:                if (cur->content != NULL)
        !           794:                    fprintf(output, "\n content \"%s\"", cur->content);
        !           795:                fprintf(output, "\n");  
        !           796:                cur = cur->nexte;
1.9       daniel    797:            }
                    798:        }
                    799:     } else
                    800:        fprintf(output, "No entities in internal subset\n");
                    801:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    802:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
                    803:                                    doc->extSubset->entities;
                    804:        fprintf(output, "Entities in external subset\n");
1.28    ! veillard  805:        for (i = 0;i < table->max_entities;i++) {
1.20      daniel    806:            cur = table->table[i];
1.28    ! veillard  807:            while (cur != NULL) {
        !           808:                fprintf(output, "%d : %s : ", i, cur->name);
        !           809:                switch (cur->etype) {
        !           810:                    case XML_INTERNAL_GENERAL_ENTITY:
        !           811:                        fprintf(output, "INTERNAL GENERAL, ");
        !           812:                        break;
        !           813:                    case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
        !           814:                        fprintf(output, "EXTERNAL PARSED, ");
        !           815:                        break;
        !           816:                    case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
        !           817:                        fprintf(output, "EXTERNAL UNPARSED, ");
        !           818:                        break;
        !           819:                    case XML_INTERNAL_PARAMETER_ENTITY:
        !           820:                        fprintf(output, "INTERNAL PARAMETER, ");
        !           821:                        break;
        !           822:                    case XML_EXTERNAL_PARAMETER_ENTITY:
        !           823:                        fprintf(output, "EXTERNAL PARAMETER, ");
        !           824:                        break;
        !           825:                    default:
        !           826:                        fprintf(output, "UNKNOWN TYPE %d",
        !           827:                                cur->etype);
        !           828:                }
        !           829:                if (cur->ExternalID != NULL) 
        !           830:                    fprintf(output, "ID \"%s\"", cur->ExternalID);
        !           831:                if (cur->SystemID != NULL)
        !           832:                    fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
        !           833:                if (cur->orig != NULL)
        !           834:                    fprintf(output, "\n orig \"%s\"", cur->orig);
        !           835:                if (cur->content != NULL)
        !           836:                    fprintf(output, "\n content \"%s\"", cur->content);
        !           837:                fprintf(output, "\n");  
        !           838:                cur = cur->nexte;
1.9       daniel    839:            }
                    840:        }
                    841:     } else
                    842:        fprintf(output, "No entities in external subset\n");
                    843: }
1.12      daniel    844: 
                    845: static int xmlLsCountNode(xmlNodePtr node) {
                    846:     int ret = 0;
                    847:     xmlNodePtr list = NULL;
                    848: 
                    849:     switch (node->type) {
                    850:        case XML_ELEMENT_NODE:
1.16      daniel    851:            list = node->children;
1.12      daniel    852:            break;
                    853:        case XML_DOCUMENT_NODE:
                    854:        case XML_HTML_DOCUMENT_NODE:
1.16      daniel    855:            list = ((xmlDocPtr) node)->children;
1.12      daniel    856:            break;
                    857:        case XML_ATTRIBUTE_NODE:
1.16      daniel    858:            list = ((xmlAttrPtr) node)->children;
1.12      daniel    859:            break;
                    860:        case XML_TEXT_NODE:
                    861:        case XML_CDATA_SECTION_NODE:
                    862:        case XML_PI_NODE:
                    863:        case XML_COMMENT_NODE:
                    864:            if (node->content != NULL) {
                    865: #ifndef XML_USE_BUFFER_CONTENT     
                    866:                ret = xmlStrlen(node->content);
                    867: #else
                    868:                ret = xmlBufferLength(node->content);
                    869: #endif
                    870:             }
                    871:            break;
                    872:        case XML_ENTITY_REF_NODE:
                    873:        case XML_DOCUMENT_TYPE_NODE:
                    874:        case XML_ENTITY_NODE:
                    875:        case XML_DOCUMENT_FRAG_NODE:
                    876:        case XML_NOTATION_NODE:
1.16      daniel    877:        case XML_DTD_NODE:
1.17      daniel    878:         case XML_ELEMENT_DECL:
                    879:         case XML_ATTRIBUTE_DECL:
1.20      daniel    880:         case XML_ENTITY_DECL:
1.12      daniel    881:            ret = 1;
                    882:            break;
                    883:     }
                    884:     for (;list != NULL;ret++) 
                    885:         list = list->next;
                    886:     return(ret);
                    887: }
                    888: 
                    889: void xmlLsOneNode(FILE *output, xmlNodePtr node) {
                    890:     switch (node->type) {
                    891:        case XML_ELEMENT_NODE:
                    892:            fprintf(output, "-");
                    893:            break;
                    894:        case XML_ATTRIBUTE_NODE:
                    895:            fprintf(output, "a");
                    896:            break;
                    897:        case XML_TEXT_NODE:
                    898:            fprintf(output, "t");
                    899:            break;
                    900:        case XML_CDATA_SECTION_NODE:
                    901:            fprintf(output, "c");
                    902:            break;
                    903:        case XML_ENTITY_REF_NODE:
                    904:            fprintf(output, "e");
                    905:            break;
                    906:        case XML_ENTITY_NODE:
                    907:            fprintf(output, "E");
                    908:            break;
                    909:        case XML_PI_NODE:
                    910:            fprintf(output, "p");
                    911:            break;
                    912:        case XML_COMMENT_NODE:
                    913:            fprintf(output, "c");
                    914:            break;
                    915:        case XML_DOCUMENT_NODE:
                    916:            fprintf(output, "d");
                    917:            break;
                    918:        case XML_HTML_DOCUMENT_NODE:
                    919:            fprintf(output, "h");
                    920:            break;
                    921:        case XML_DOCUMENT_TYPE_NODE:
                    922:            fprintf(output, "T");
                    923:            break;
                    924:        case XML_DOCUMENT_FRAG_NODE:
                    925:            fprintf(output, "F");
                    926:            break;
                    927:        case XML_NOTATION_NODE:
                    928:            fprintf(output, "N");
                    929:            break;
                    930:        default:
                    931:            fprintf(output, "?");
                    932:     }
                    933:     if (node->properties != NULL)
                    934:        fprintf(output, "a");
                    935:     else       
                    936:        fprintf(output, "-");
                    937:     if (node->nsDef != NULL) 
                    938:        fprintf(output, "n");
                    939:     else       
                    940:        fprintf(output, "-");
                    941: 
                    942:     fprintf(output, " %8d ", xmlLsCountNode(node));
                    943: 
                    944:     switch (node->type) {
                    945:        case XML_ELEMENT_NODE:
                    946:            if (node->name != NULL)
                    947:                fprintf(output, "%s", node->name);
                    948:            break;
                    949:        case XML_ATTRIBUTE_NODE:
                    950:            if (node->name != NULL)
                    951:                fprintf(output, "%s", node->name);
                    952:            break;
                    953:        case XML_TEXT_NODE:
                    954:            if (node->content != NULL) {
                    955: #ifndef XML_USE_BUFFER_CONTENT     
                    956:                xmlDebugDumpString(output, node->content);
                    957: #else
                    958:                xmlDebugDumpString(output, xmlBufferContent(node->content));
                    959: #endif
                    960:             }
                    961:            break;
                    962:        case XML_CDATA_SECTION_NODE:
                    963:            break;
                    964:        case XML_ENTITY_REF_NODE:
                    965:            if (node->name != NULL)
                    966:                fprintf(output, "%s", node->name);
                    967:            break;
                    968:        case XML_ENTITY_NODE:
                    969:            if (node->name != NULL)
                    970:                fprintf(output, "%s", node->name);
                    971:            break;
                    972:        case XML_PI_NODE:
                    973:            if (node->name != NULL)
                    974:                fprintf(output, "%s", node->name);
                    975:            break;
                    976:        case XML_COMMENT_NODE:
                    977:            break;
                    978:        case XML_DOCUMENT_NODE:
                    979:            break;
                    980:        case XML_HTML_DOCUMENT_NODE:
                    981:            break;
                    982:        case XML_DOCUMENT_TYPE_NODE:
                    983:            break;
                    984:        case XML_DOCUMENT_FRAG_NODE:
                    985:            break;
                    986:        case XML_NOTATION_NODE:
                    987:            break;
                    988:        default:
                    989:            if (node->name != NULL)
                    990:                fprintf(output, "%s", node->name);
                    991:     }
                    992:     fprintf(output, "\n");
                    993: }
                    994: 
                    995: /****************************************************************
                    996:  *                                                             *
                    997:  *             The XML shell related functions                 *
                    998:  *                                                             *
                    999:  ****************************************************************/
                   1000: 
                   1001: /*
                   1002:  * TODO: Improvement/cleanups for the XML shell
                   1003:  *     - allow to shell out an editor on a subpart
                   1004:  *     - cleanup function registrations (with help) and calling
                   1005:  *     - provide registration routines
                   1006:  */
                   1007: 
                   1008: /**
                   1009:  * xmlShellList:
                   1010:  * @ctxt:  the shell context
                   1011:  * @arg:  unused
                   1012:  * @node:  a node
                   1013:  * @node2:  unused
                   1014:  *
                   1015:  * Implements the XML shell function "ls"
                   1016:  * Does an Unix like listing of the given node (like a directory)
                   1017:  *
                   1018:  * Returns 0
                   1019:  */
                   1020: int
                   1021: xmlShellList(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                   1022:                   xmlNodePtr node2) {
                   1023:     xmlNodePtr cur;
                   1024: 
                   1025:     if ((node->type == XML_DOCUMENT_NODE) ||
                   1026:         (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16      daniel   1027:         cur = ((xmlDocPtr) node)->children;
                   1028:     } else if (node->children != NULL) {
                   1029:         cur = node->children;
1.12      daniel   1030:     } else {
                   1031:        xmlLsOneNode(stdout, node);
                   1032:         return(0);
                   1033:     }
                   1034:     while (cur != NULL) {
                   1035:        xmlLsOneNode(stdout, cur);
                   1036:        cur = cur->next;
                   1037:     }
                   1038:     return(0);
                   1039: }
                   1040: 
                   1041: /**
                   1042:  * xmlShellDir:
                   1043:  * @ctxt:  the shell context
                   1044:  * @arg:  unused
                   1045:  * @node:  a node
                   1046:  * @node2:  unused
                   1047:  *
                   1048:  * Implements the XML shell function "dir"
                   1049:  * dumps informations about the node (namespace, attributes, content).
                   1050:  *
                   1051:  * Returns 0
                   1052:  */
                   1053: int
                   1054: xmlShellDir(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                   1055:                   xmlNodePtr node2) {
                   1056:     if ((node->type == XML_DOCUMENT_NODE) ||
                   1057:         (node->type == XML_HTML_DOCUMENT_NODE)) {
                   1058:        xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
                   1059:     } else if (node->type == XML_ATTRIBUTE_NODE) {
                   1060:        xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
                   1061:     } else {
                   1062:        xmlDebugDumpOneNode(stdout, node, 0);
                   1063:     }
                   1064:     return(0);
                   1065: }
                   1066: 
                   1067: /**
                   1068:  * xmlShellCat:
                   1069:  * @ctxt:  the shell context
                   1070:  * @arg:  unused
                   1071:  * @node:  a node
                   1072:  * @node2:  unused
                   1073:  *
                   1074:  * Implements the XML shell function "cat"
                   1075:  * dumps the serialization node content (XML or HTML).
                   1076:  *
                   1077:  * Returns 0
                   1078:  */
                   1079: int
                   1080: xmlShellCat(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                   1081:                   xmlNodePtr node2) {
1.13      daniel   1082:     if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1.23      daniel   1083: #ifdef LIBXML_HTML_ENABLED
1.13      daniel   1084:        if (node->type == XML_HTML_DOCUMENT_NODE)
                   1085:            htmlDocDump(stdout, (htmlDocPtr) node);
                   1086:        else
1.14      daniel   1087:            htmlNodeDumpFile(stdout, ctxt->doc, node);
1.23      daniel   1088: #else
                   1089:        if (node->type == XML_DOCUMENT_NODE)
                   1090:            xmlDocDump(stdout, (xmlDocPtr) node);
                   1091:        else
                   1092:            xmlElemDump(stdout, ctxt->doc, node);
                   1093: #endif /* LIBXML_HTML_ENABLED */
1.13      daniel   1094:     } else {
                   1095:        if (node->type == XML_DOCUMENT_NODE)
                   1096:            xmlDocDump(stdout, (xmlDocPtr) node);
                   1097:        else
                   1098:            xmlElemDump(stdout, ctxt->doc, node);
                   1099:     }
1.12      daniel   1100:     printf("\n");
                   1101:     return(0);
                   1102: }
                   1103: 
                   1104: /**
                   1105:  * xmlShellLoad:
                   1106:  * @ctxt:  the shell context
                   1107:  * @filename:  the file name
                   1108:  * @node:  unused
                   1109:  * @node2:  unused
                   1110:  *
                   1111:  * Implements the XML shell function "load"
                   1112:  * loads a new document specified by the filename
                   1113:  *
                   1114:  * Returns 0 or -1 if loading failed
                   1115:  */
                   1116: int
                   1117: xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   1118:              xmlNodePtr node2) {
                   1119:     xmlDocPtr doc;
                   1120:     int html = 0;
                   1121: 
                   1122:     if (ctxt->doc != NULL)
                   1123:        html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
                   1124: 
                   1125:     if (html) {
1.23      daniel   1126: #ifdef LIBXML_HTML_ENABLED
1.12      daniel   1127:        doc = htmlParseFile(filename, NULL);
1.23      daniel   1128: #else  
                   1129:        printf("HTML support not compiled in\n");
                   1130:        doc = NULL;
                   1131: #endif /* LIBXML_HTML_ENABLED */
1.12      daniel   1132:     } else {
                   1133:        doc = xmlParseFile(filename);
                   1134:     }
                   1135:     if (doc != NULL) {
                   1136:         if (ctxt->loaded == 1) {
                   1137:            xmlFreeDoc(ctxt->doc);
                   1138:        }
                   1139:        ctxt->loaded = 1;
1.23      daniel   1140: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1141:        xmlXPathFreeContext(ctxt->pctxt);
1.23      daniel   1142: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1143:        xmlFree(ctxt->filename);
                   1144:        ctxt->doc = doc;
                   1145:        ctxt->node = (xmlNodePtr) doc;   
1.23      daniel   1146: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1147:        ctxt->pctxt = xmlXPathNewContext(doc);
1.23      daniel   1148: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1149:        ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
                   1150:     } else
                   1151:         return(-1);
                   1152:     return(0);
                   1153: }
                   1154: 
                   1155: /**
                   1156:  * xmlShellWrite:
                   1157:  * @ctxt:  the shell context
                   1158:  * @filename:  the file name
                   1159:  * @node:  a node in the tree
                   1160:  * @node2:  unused
                   1161:  *
                   1162:  * Implements the XML shell function "write"
                   1163:  * Write the current node to the filename, it saves the serailization
                   1164:  * of the subtree under the @node specified
                   1165:  *
                   1166:  * Returns 0 or -1 in case of error
                   1167:  */
                   1168: int
                   1169: xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   1170:                   xmlNodePtr node2) {
                   1171:     if (node == NULL)
                   1172:         return(-1);
                   1173:     if ((filename == NULL) || (filename[0] == 0)) {
                   1174:         fprintf(stderr, "Write command requires a filename argument\n");
                   1175:        return(-1);
                   1176:     }
                   1177: #ifdef W_OK
                   1178:     if (access((char *) filename, W_OK)) {
                   1179:         fprintf(stderr, "Cannot write to %s\n", filename);
                   1180:        return(-1);
                   1181:     }
                   1182: #endif    
                   1183:     switch(node->type) {
                   1184:         case XML_DOCUMENT_NODE:
                   1185:            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
                   1186:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1187:                return(-1);
                   1188:            }
                   1189:            break;
                   1190:         case XML_HTML_DOCUMENT_NODE:
1.23      daniel   1191: #ifdef LIBXML_HTML_ENABLED
1.12      daniel   1192:            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1193:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1194:                return(-1);
                   1195:            }
1.23      daniel   1196: #else
                   1197:            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
                   1198:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1199:                return(-1);
                   1200:            }
                   1201: #endif /* LIBXML_HTML_ENABLED */
1.12      daniel   1202:            break;
                   1203:        default: {
                   1204:            FILE *f;
                   1205: 
                   1206:            f = fopen((char *) filename, "w");
                   1207:            if (f == NULL) {
                   1208:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1209:                return(-1);
                   1210:            }
                   1211:            xmlElemDump(f, ctxt->doc, node);
                   1212:            fclose(f);
                   1213:        }
                   1214:     }
                   1215:     return(0);
                   1216: }
                   1217: 
                   1218: /**
                   1219:  * xmlShellSave:
                   1220:  * @ctxt:  the shell context
                   1221:  * @filename:  the file name (optionnal)
                   1222:  * @node:  unused
                   1223:  * @node2:  unused
                   1224:  *
                   1225:  * Implements the XML shell function "save"
                   1226:  * Write the current document to the filename, or it's original name
                   1227:  *
                   1228:  * Returns 0 or -1 in case of error
                   1229:  */
                   1230: int 
                   1231: xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   1232:              xmlNodePtr node2) {
                   1233:     if (ctxt->doc == NULL)
                   1234:        return(-1);
                   1235:     if ((filename == NULL) || (filename[0] == 0))
                   1236:         filename = ctxt->filename;
                   1237: #ifdef W_OK
                   1238:     if (access((char *) filename, W_OK)) {
                   1239:         fprintf(stderr, "Cannot save to %s\n", filename);
                   1240:        return(-1);
                   1241:     }
                   1242: #endif
                   1243:     switch(ctxt->doc->type) {
                   1244:         case XML_DOCUMENT_NODE:
                   1245:            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1246:                fprintf(stderr, "Failed to save to %s\n", filename);
                   1247:            }
                   1248:            break;
                   1249:         case XML_HTML_DOCUMENT_NODE:
1.23      daniel   1250: #ifdef LIBXML_HTML_ENABLED
1.12      daniel   1251:            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1252:                fprintf(stderr, "Failed to save to %s\n", filename);
                   1253:            }
1.23      daniel   1254: #else
                   1255:            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1256:                fprintf(stderr, "Failed to save to %s\n", filename);
                   1257:            }
                   1258: #endif /* LIBXML_HTML_ENABLED */
1.12      daniel   1259:            break;
                   1260:        default:
                   1261:            fprintf(stderr, 
                   1262:              "To save to subparts of a document use the 'write' command\n");
                   1263:            return(-1);
                   1264:            
                   1265:     }
                   1266:     return(0);
                   1267: }
                   1268: 
                   1269: /**
                   1270:  * xmlShellValidate:
                   1271:  * @ctxt:  the shell context
                   1272:  * @dtd:  the DTD URI (optionnal)
                   1273:  * @node:  unused
                   1274:  * @node2:  unused
                   1275:  *
                   1276:  * Implements the XML shell function "validate"
                   1277:  * Validate the document, if a DTD path is provided, then the validation
                   1278:  * is done against the given DTD.
                   1279:  *
                   1280:  * Returns 0 or -1 in case of error
                   1281:  */
                   1282: int 
                   1283: xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node,
                   1284:                  xmlNodePtr node2) {
                   1285:     xmlValidCtxt vctxt;
                   1286:     int res = -1;
                   1287: 
                   1288:     vctxt.userData = stderr;
                   1289:     vctxt.error = (xmlValidityErrorFunc) fprintf;
                   1290:     vctxt.warning = (xmlValidityWarningFunc) fprintf;
                   1291: 
                   1292:     if ((dtd == NULL) || (dtd[0] == 0)) {
                   1293:         res = xmlValidateDocument(&vctxt, ctxt->doc);
                   1294:     } else {
                   1295:         xmlDtdPtr subset;
                   1296: 
                   1297:        subset = xmlParseDTD(NULL, (xmlChar *) dtd);
                   1298:        if (subset != NULL) {
                   1299:             res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
                   1300: 
                   1301:            xmlFreeDtd(subset);
                   1302:        }
                   1303:     }
                   1304:     return(res);
                   1305: }
                   1306: 
                   1307: /**
                   1308:  * xmlShellDu:
                   1309:  * @ctxt:  the shell context
                   1310:  * @arg:  unused
                   1311:  * @tree:  a node defining a subtree
                   1312:  * @node2:  unused
                   1313:  *
                   1314:  * Implements the XML shell function "du"
                   1315:  * show the structure of the subtree under node @tree
                   1316:  * If @tree is null, the command works on the current node.
                   1317:  *
                   1318:  * Returns 0 or -1 in case of error
                   1319:  */
                   1320: int 
                   1321: xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
                   1322:                   xmlNodePtr node2) {
                   1323:     xmlNodePtr node;
                   1324:     int indent = 0,i;
                   1325: 
                   1326:     if (tree == NULL) return(-1);
                   1327:     node = tree;
                   1328:     while (node != NULL) {
                   1329:         if ((node->type == XML_DOCUMENT_NODE) ||
                   1330:             (node->type == XML_HTML_DOCUMENT_NODE)) {
                   1331:            printf("/\n");
                   1332:        } else if (node->type == XML_ELEMENT_NODE) {
                   1333:            for (i = 0;i < indent;i++)
                   1334:                printf("  ");
                   1335:            printf("%s\n", node->name);
                   1336:        } else {
                   1337:        }
                   1338: 
                   1339:        /*
                   1340:         * Browse the full subtree, deep first
                   1341:         */
                   1342: 
                   1343:         if ((node->type == XML_DOCUMENT_NODE) ||
                   1344:             (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16      daniel   1345:            node = ((xmlDocPtr) node)->children;
1.25      daniel   1346:         } else if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1.12      daniel   1347:            /* deep first */
1.16      daniel   1348:            node = node->children;
1.12      daniel   1349:            indent++;
                   1350:        } else if ((node != tree) && (node->next != NULL)) {
                   1351:            /* then siblings */
                   1352:            node = node->next;
                   1353:        } else if (node != tree) {
                   1354:            /* go up to parents->next if needed */
                   1355:            while (node != tree) {
                   1356:                if (node->parent != NULL) {
                   1357:                    node = node->parent;
                   1358:                    indent--;
                   1359:                }
                   1360:                if ((node != tree) && (node->next != NULL)) {
                   1361:                    node = node->next;
                   1362:                    break;
                   1363:                }
                   1364:                if (node->parent == NULL) {
                   1365:                    node = NULL;
                   1366:                    break;
                   1367:                }
                   1368:                if (node == tree) {
                   1369:                    node = NULL;
                   1370:                    break;
                   1371:                }
                   1372:            }
                   1373:            /* exit condition */
                   1374:            if (node == tree) 
                   1375:                node = NULL;
                   1376:        } else
                   1377:            node = NULL;
                   1378:     }
                   1379:     return(0);
                   1380: }
                   1381: 
                   1382: /**
                   1383:  * xmlShellPwd:
                   1384:  * @ctxt:  the shell context
                   1385:  * @buffer:  the output buffer
                   1386:  * @tree:  a node 
                   1387:  * @node2:  unused
                   1388:  *
                   1389:  * Implements the XML shell function "pwd"
                   1390:  * Show the full path from the root to the node, if needed building
                   1391:  * thumblers when similar elements exists at a given ancestor level.
                   1392:  * The output is compatible with XPath commands.
                   1393:  *
                   1394:  * Returns 0 or -1 in case of error
                   1395:  */
                   1396: int 
                   1397: xmlShellPwd(xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node,
                   1398:                   xmlNodePtr node2) {
                   1399:     xmlNodePtr cur, tmp, next;
                   1400:     char buf[500];
                   1401:     char sep;
                   1402:     const char *name;
                   1403:     int occur = 0;
                   1404: 
                   1405:     buffer[0] = 0;
                   1406:     if (node == NULL) return(-1);
                   1407:     cur = node;
                   1408:     do {
                   1409:        name = "";
                   1410:        sep= '?';
                   1411:        occur = 0;
                   1412:        if ((cur->type == XML_DOCUMENT_NODE) ||
                   1413:            (cur->type == XML_HTML_DOCUMENT_NODE)) {
                   1414:            sep = '/';
                   1415:            next = NULL;
                   1416:        } else if (cur->type == XML_ELEMENT_NODE) {
                   1417:            sep = '/';
                   1418:            name = (const char *)cur->name;
                   1419:            next = cur->parent;
                   1420: 
                   1421:            /*
                   1422:             * Thumbler index computation
                   1423:             */
                   1424:            tmp = cur->prev;
                   1425:             while (tmp != NULL) {
                   1426:                if (!xmlStrcmp(cur->name, tmp->name))
                   1427:                    occur++;
                   1428:                tmp = tmp->prev;
                   1429:            }
                   1430:            if (occur == 0) {
                   1431:                tmp = cur->next;
                   1432:                while (tmp != NULL) {
                   1433:                    if (!xmlStrcmp(cur->name, tmp->name))
                   1434:                        occur++;
                   1435:                    tmp = tmp->next;
                   1436:                }
                   1437:                if (occur != 0) occur = 1;
                   1438:            } else
                   1439:                occur++;
                   1440:        } else if (cur->type == XML_ATTRIBUTE_NODE) {
                   1441:            sep = '@';
                   1442:            name = (const char *) (((xmlAttrPtr) cur)->name);
1.16      daniel   1443:            next = ((xmlAttrPtr) cur)->parent;
1.12      daniel   1444:        } else {
                   1445:            next = cur->parent;
                   1446:        }
                   1447:        if (occur == 0)
                   1448:            sprintf(buf, "%c%s%s", sep, name, buffer);
                   1449:        else
                   1450:            sprintf(buf, "%c%s[%d]%s", sep, name, occur, buffer);
                   1451:        strcpy(buffer, buf);
                   1452:         cur = next;
                   1453:     } while (cur != NULL);
                   1454:     return(0);
                   1455: }
                   1456: 
                   1457: /**
                   1458:  * xmlShell
                   1459:  * @doc:  the initial document
                   1460:  * @filename:  the output buffer
                   1461:  * @input:  the line reading function
                   1462:  * @output:  the output FILE*
                   1463:  *
                   1464:  * Implements the XML shell 
                   1465:  * This allow to load, validate, view, modify and save a document
                   1466:  * using a environment similar to a UNIX commandline.
                   1467:  */
                   1468: void
                   1469: xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                   1470:          FILE *output) {
                   1471:     char prompt[500] = "/ > ";
                   1472:     char *cmdline = NULL;
                   1473:     int nbargs;
                   1474:     char command[100];
                   1475:     char arg[400];
                   1476:     xmlShellCtxtPtr ctxt;
                   1477:     xmlXPathObjectPtr list;
                   1478: 
                   1479:     if (doc == NULL)
                   1480:         return;
                   1481:     if (filename == NULL)
                   1482:         return;
                   1483:     if (input == NULL)
                   1484:         return;
                   1485:     if (output == NULL)
                   1486:         return;
                   1487:     ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
                   1488:     if (ctxt == NULL) 
                   1489:         return;
                   1490:     ctxt->loaded = 0;
                   1491:     ctxt->doc = doc;
                   1492:     ctxt->input = input;
                   1493:     ctxt->output = output;
                   1494:     ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
                   1495:     ctxt->node = (xmlNodePtr) ctxt->doc;        
                   1496: 
1.23      daniel   1497: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1498:     ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
                   1499:     if (ctxt->pctxt == NULL) {
                   1500:        xmlFree(ctxt);
                   1501:        return;
                   1502:     }
1.23      daniel   1503: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1504:     while (1) {
                   1505:         if (ctxt->node == (xmlNodePtr) ctxt->doc)
                   1506:            sprintf(prompt, "%s > ", "/");
                   1507:        else if (ctxt->node->name)
                   1508:            sprintf(prompt, "%s > ", ctxt->node->name);
                   1509:        else
                   1510:            sprintf(prompt, "? > ");
                   1511: 
                   1512:         cmdline = ctxt->input(prompt);
                   1513:         if (cmdline == NULL) break;
                   1514: 
                   1515:        command[0] = 0;
                   1516:        arg[0] = 0;
                   1517:        nbargs = sscanf(cmdline, "%s %s", command, arg);
                   1518: 
                   1519:        if (command[0] == 0) continue;
                   1520:         if (!strcmp(command, "exit"))
                   1521:            break;
                   1522:         if (!strcmp(command, "quit"))
                   1523:            break;
                   1524:         if (!strcmp(command, "bye"))
                   1525:            break;
                   1526:        if (!strcmp(command, "validate")) {
                   1527:            xmlShellValidate(ctxt, arg, NULL, NULL);
                   1528:        } else if (!strcmp(command, "load")) {
                   1529:            xmlShellLoad(ctxt, arg, NULL, NULL);
                   1530:        } else if (!strcmp(command, "save")) {
                   1531:            xmlShellSave(ctxt, arg, NULL, NULL);
                   1532:        } else if (!strcmp(command, "write")) {
                   1533:            xmlShellWrite(ctxt, arg, NULL, NULL);
                   1534:        } else if (!strcmp(command, "free")) {
                   1535:            if (arg[0] == 0) {
                   1536:                xmlMemShow(stdout, 0);
                   1537:            } else {
                   1538:                int len = 0;
                   1539:                sscanf(arg, "%d", &len);
                   1540:                xmlMemShow(stdout, len);
                   1541:            }
                   1542:        } else if (!strcmp(command, "pwd")) {
                   1543:            char dir[500];
                   1544:            if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
                   1545:                printf("%s\n", dir);
                   1546:        } else  if (!strcmp(command, "du")) {
                   1547:            xmlShellDu(ctxt, NULL, ctxt->node, NULL);
                   1548:        } else  if ((!strcmp(command, "ls")) ||
                   1549:              (!strcmp(command, "dir"))) {
                   1550:            int dir = (!strcmp(command, "dir"));
                   1551:            if (arg[0] == 0) {
                   1552:                if (dir)
                   1553:                    xmlShellDir(ctxt, NULL, ctxt->node, NULL);
                   1554:                else
                   1555:                    xmlShellList(ctxt, NULL, ctxt->node, NULL);
                   1556:            } else {
                   1557:                ctxt->pctxt->node = ctxt->node;
1.23      daniel   1558: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1559:                if (ctxt->pctxt->nodelist != NULL)
                   1560:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1561:                ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
                   1562:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23      daniel   1563: #else
                   1564:                list = NULL;
                   1565: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1566:                if (list != NULL) {
                   1567:                    switch (list->type) {
                   1568:                        case XPATH_UNDEFINED:
                   1569:                            fprintf(stderr, "%s: no such node\n", arg);
                   1570:                            break;
                   1571:                        case XPATH_NODESET: {
                   1572:                            int i;
                   1573: 
                   1574:                            for (i = 0;i < list->nodesetval->nodeNr;i++) {
                   1575:                                if (dir)
                   1576:                                    xmlShellDir(ctxt, NULL,
                   1577:                                       list->nodesetval->nodeTab[i], NULL);
                   1578:                                else
                   1579:                                    xmlShellList(ctxt, NULL,
                   1580:                                       list->nodesetval->nodeTab[i], NULL);
                   1581:                            }
                   1582:                            break;
                   1583:                        }
                   1584:                        case XPATH_BOOLEAN:
                   1585:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1586:                            break;
                   1587:                        case XPATH_NUMBER:
                   1588:                            fprintf(stderr, "%s is a number\n", arg);
                   1589:                            break;
                   1590:                        case XPATH_STRING:
                   1591:                            fprintf(stderr, "%s is a string\n", arg);
                   1592:                            break;
                   1593:                    }
                   1594:                    xmlXPathFreeNodeSetList(list);
                   1595:                } else {
                   1596:                    fprintf(stderr, "%s: no such node\n", arg);
                   1597:                }
1.23      daniel   1598: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1599:                if (ctxt->pctxt->nodelist != NULL)
                   1600:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1.23      daniel   1601: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1602:                ctxt->pctxt->nodelist = NULL;
                   1603:            }
                   1604:        } else if (!strcmp(command, "cd")) {
                   1605:            if (arg[0] == 0) {
                   1606:                ctxt->node = (xmlNodePtr) ctxt->doc;
                   1607:            } else {
                   1608:                ctxt->pctxt->node = ctxt->node;
1.23      daniel   1609: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1610:                if (ctxt->pctxt->nodelist != NULL)
                   1611:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1612:                ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
                   1613:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23      daniel   1614: #else
                   1615:                list = NULL;
                   1616: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1617:                if (list != NULL) {
                   1618:                    switch (list->type) {
                   1619:                        case XPATH_UNDEFINED:
                   1620:                            fprintf(stderr, "%s: no such node\n", arg);
                   1621:                            break;
                   1622:                        case XPATH_NODESET:
                   1623:                            if (list->nodesetval->nodeNr == 1) {
                   1624:                                ctxt->node = list->nodesetval->nodeTab[0];
                   1625:                            } else 
                   1626:                                fprintf(stderr, "%s is a %d Node Set\n",
                   1627:                                        arg, list->nodesetval->nodeNr);
                   1628:                            break;
                   1629:                        case XPATH_BOOLEAN:
                   1630:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1631:                            break;
                   1632:                        case XPATH_NUMBER:
                   1633:                            fprintf(stderr, "%s is a number\n", arg);
                   1634:                            break;
                   1635:                        case XPATH_STRING:
                   1636:                            fprintf(stderr, "%s is a string\n", arg);
                   1637:                            break;
                   1638:                    }
                   1639:                    xmlXPathFreeNodeSetList(list);
                   1640:                } else {
                   1641:                    fprintf(stderr, "%s: no such node\n", arg);
                   1642:                }
1.23      daniel   1643: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1644:                if (ctxt->pctxt->nodelist != NULL)
                   1645:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1.23      daniel   1646: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1647:                ctxt->pctxt->nodelist = NULL;
                   1648:            }
                   1649:        } else if (!strcmp(command, "cat")) {
                   1650:            if (arg[0] == 0) {
                   1651:                xmlShellCat(ctxt, NULL, ctxt->node, NULL);
                   1652:            } else {
                   1653:                ctxt->pctxt->node = ctxt->node;
1.23      daniel   1654: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1655:                if (ctxt->pctxt->nodelist != NULL)
                   1656:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1657:                ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
                   1658:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23      daniel   1659: #else
                   1660:                list = NULL;
                   1661: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1662:                if (list != NULL) {
                   1663:                    switch (list->type) {
                   1664:                        case XPATH_UNDEFINED:
                   1665:                            fprintf(stderr, "%s: no such node\n", arg);
                   1666:                            break;
                   1667:                        case XPATH_NODESET: {
                   1668:                            int i;
                   1669: 
                   1670:                            for (i = 0;i < list->nodesetval->nodeNr;i++) {
                   1671:                                if (i > 0) printf(" -------\n");
                   1672:                                xmlShellCat(ctxt, NULL,
                   1673:                                    list->nodesetval->nodeTab[i], NULL);
                   1674:                            }
                   1675:                            break;
                   1676:                        }
                   1677:                        case XPATH_BOOLEAN:
                   1678:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1679:                            break;
                   1680:                        case XPATH_NUMBER:
                   1681:                            fprintf(stderr, "%s is a number\n", arg);
                   1682:                            break;
                   1683:                        case XPATH_STRING:
                   1684:                            fprintf(stderr, "%s is a string\n", arg);
                   1685:                            break;
                   1686:                    }
                   1687:                    xmlXPathFreeNodeSetList(list);
                   1688:                } else {
                   1689:                    fprintf(stderr, "%s: no such node\n", arg);
                   1690:                }
1.23      daniel   1691: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1692:                if (ctxt->pctxt->nodelist != NULL)
                   1693:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1.23      daniel   1694: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1695:                ctxt->pctxt->nodelist = NULL;
                   1696:            }
                   1697:        } else {
                   1698:            fprintf(stderr, "Unknown command %s\n", command);
                   1699:        }
                   1700:        free(cmdline); /* not xmlFree here ! */
                   1701:     }
1.23      daniel   1702: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1703:     xmlXPathFreeContext(ctxt->pctxt);
1.23      daniel   1704: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1705:     if (ctxt->loaded) {
                   1706:         xmlFreeDoc(ctxt->doc);
                   1707:     }
                   1708:     xmlFree(ctxt);
                   1709:     if (cmdline != NULL)
                   1710:         free(cmdline); /* not xmlFree here ! */
                   1711: }
                   1712: 
1.23      daniel   1713: #endif /* LIBXML_DEBUG_ENABLED */

Webmaster