Annotation of XML/debugXML.c, revision 1.17

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.1       daniel     15: #include <stdio.h>
1.12      daniel     16: #ifdef HAVE_STDLIB_H
                     17: #include <stdlib.h>
                     18: #endif
1.14      daniel     19: #ifdef HAVE_STRING_H
                     20: #include <string.h>
                     21: #endif
1.12      daniel     22: #include "xmlmemory.h"
1.1       daniel     23: #include "tree.h"
                     24: #include "parser.h"
                     25: #include "debugXML.h"
1.12      daniel     26: #include "HTMLtree.h"
                     27: #include "HTMLparser.h"
1.1       daniel     28: 
                     29: #define IS_BLANK(c)                                                    \
                     30:   (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
                     31: 
1.6       daniel     32: void xmlDebugDumpString(FILE *output, const xmlChar *str) {
1.1       daniel     33:     int i;
                     34:     for (i = 0;i < 40;i++)
                     35:         if (str[i] == 0) return;
                     36:        else if (IS_BLANK(str[i])) fputc(' ', output);
                     37:        else fputc(str[i], output);
                     38:     fprintf(output, "...");
                     39: }
                     40: 
                     41: void xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
                     42:     int i;
                     43:     char shift[100];
                     44: 
                     45:     for (i = 0;((i < depth) && (i < 25));i++)
                     46:         shift[2 * i] = shift[2 * i + 1] = ' ';
                     47:     shift[2 * i] = shift[2 * i + 1] = 0;
                     48: 
                     49:     fprintf(output, shift);
                     50:     if (ns->type == XML_GLOBAL_NAMESPACE)
                     51:         fprintf(output, "old ");
1.10      daniel     52:     if (ns->prefix != NULL)
                     53:        fprintf(output, "namespace %s href=", ns->prefix);
                     54:     else
1.12      daniel     55:        fprintf(output, "default namespace href=");
1.10      daniel     56: 
1.1       daniel     57:     xmlDebugDumpString(output, ns->href);
                     58:     fprintf(output, "\n");
                     59: }
                     60: 
                     61: void xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
                     62:     while (ns != NULL) {
                     63:         xmlDebugDumpNamespace(output, ns, depth);
                     64:        ns = ns->next;
                     65:     }
                     66: }
                     67: 
                     68: void xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
                     69:     int i;
                     70:     char shift[100];
                     71: 
                     72:     for (i = 0;((i < depth) && (i < 25));i++)
                     73:         shift[2 * i] = shift[2 * i + 1] = ' ';
                     74:     shift[2 * i] = shift[2 * i + 1] = 0;
                     75: 
                     76:     fprintf(output, shift);
                     77:     switch (ent->type) {
                     78:         case XML_INTERNAL_GENERAL_ENTITY:
                     79:            fprintf(output, "INTERNAL_GENERAL_ENTITY ");
                     80:            break;
                     81:         case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                     82:            fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
                     83:            break;
                     84:         case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                     85:            fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
                     86:            break;
                     87:         case XML_INTERNAL_PARAMETER_ENTITY:
                     88:            fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
                     89:            break;
                     90:         case XML_EXTERNAL_PARAMETER_ENTITY:
                     91:            fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
                     92:            break;
                     93:        default:
                     94:            fprintf(output, "ENTITY_%d ! ", ent->type);
                     95:     }
                     96:     fprintf(output, "%s\n", ent->name);
                     97:     if (ent->ExternalID) {
                     98:         fprintf(output, shift);
                     99:         fprintf(output, "ExternalID=%s\n", ent->ExternalID);
                    100:     }
                    101:     if (ent->SystemID) {
                    102:         fprintf(output, shift);
                    103:         fprintf(output, "SystemID=%s\n", ent->SystemID);
                    104:     }
                    105:     if (ent->content) {
                    106:         fprintf(output, shift);
                    107:        fprintf(output, "content=");
                    108:        xmlDebugDumpString(output, ent->content);
                    109:        fprintf(output, "\n");
                    110:     }
                    111: }
                    112: 
                    113: void xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
                    114:     int i;
                    115:     char shift[100];
                    116: 
                    117:     for (i = 0;((i < depth) && (i < 25));i++)
                    118:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    119:     shift[2 * i] = shift[2 * i + 1] = 0;
                    120: 
                    121:     fprintf(output, shift);
                    122:     fprintf(output, "ATTRIBUTE %s\n", attr->name);
1.16      daniel    123:     if (attr->children != NULL) 
                    124:         xmlDebugDumpNodeList(output, attr->children, depth + 1);
1.1       daniel    125: }
                    126: 
                    127: void xmlDebugDumpAttrList(FILE *output, xmlAttrPtr attr, int depth) {
                    128:     while (attr != NULL) {
                    129:         xmlDebugDumpAttr(output, attr, depth);
                    130:        attr = attr->next;
                    131:     }
                    132: }
                    133: 
1.3       daniel    134: void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) {
1.1       daniel    135:     int i;
                    136:     char shift[100];
                    137: 
                    138:     for (i = 0;((i < depth) && (i < 25));i++)
                    139:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    140:     shift[2 * i] = shift[2 * i + 1] = 0;
                    141: 
                    142:     fprintf(output, shift);
                    143:     switch (node->type) {
                    144:        case XML_ELEMENT_NODE:
                    145:            fprintf(output, "ELEMENT ");
                    146:            if (node->ns != NULL)
                    147:                fprintf(output, "%s:%s\n", node->ns->prefix, node->name);
                    148:            else
                    149:                fprintf(output, "%s\n", node->name);
                    150:            break;
                    151:        case XML_ATTRIBUTE_NODE:
                    152:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    153:            break;
                    154:        case XML_TEXT_NODE:
                    155:            fprintf(output, "TEXT\n");
                    156:            break;
                    157:        case XML_CDATA_SECTION_NODE:
                    158:            fprintf(output, "CDATA_SECTION\n");
                    159:            break;
                    160:        case XML_ENTITY_REF_NODE:
1.15      daniel    161:            fprintf(output, "ENTITY_REF(%s)\n", node->name);
1.1       daniel    162:            break;
                    163:        case XML_ENTITY_NODE:
                    164:            fprintf(output, "ENTITY\n");
                    165:            break;
                    166:        case XML_PI_NODE:
1.4       daniel    167:            fprintf(output, "PI %s\n", node->name);
1.1       daniel    168:            break;
                    169:        case XML_COMMENT_NODE:
                    170:            fprintf(output, "COMMENT\n");
                    171:            break;
                    172:        case XML_DOCUMENT_NODE:
1.7       daniel    173:        case XML_HTML_DOCUMENT_NODE:
1.1       daniel    174:            fprintf(output, "Error, DOCUMENT found here\n");
                    175:            break;
                    176:        case XML_DOCUMENT_TYPE_NODE:
                    177:            fprintf(output, "DOCUMENT_TYPE\n");
                    178:            break;
                    179:        case XML_DOCUMENT_FRAG_NODE:
                    180:            fprintf(output, "DOCUMENT_FRAG\n");
                    181:            break;
                    182:        case XML_NOTATION_NODE:
                    183:            fprintf(output, "NOTATION\n");
                    184:            break;
                    185:        default:
                    186:            fprintf(output, "NODE_%d\n", node->type);
                    187:     }
                    188:     if (node->doc == NULL) {
                    189:         fprintf(output, shift);
                    190:        fprintf(output, "doc == NULL !!!\n");
                    191:     }
                    192:     if (node->nsDef != NULL) 
                    193:         xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
                    194:     if (node->properties != NULL)
                    195:        xmlDebugDumpAttrList(output, node->properties, depth + 1);
                    196:     if (node->type != XML_ENTITY_REF_NODE) {
                    197:        if (node->content != NULL) {
                    198:            fprintf(output, shift);
                    199:            fprintf(output, "content=");
1.8       daniel    200: #ifndef XML_USE_BUFFER_CONTENT     
1.1       daniel    201:            xmlDebugDumpString(output, node->content);
1.8       daniel    202: #else
                    203:            xmlDebugDumpString(output, xmlBufferContent(node->content));
                    204: #endif
1.1       daniel    205:            fprintf(output, "\n");
                    206:        }
                    207:     } else {
                    208:         xmlEntityPtr ent;
                    209:        ent = xmlGetDocEntity(node->doc, node->name);
                    210:        if (ent != NULL)
                    211:            xmlDebugDumpEntity(output, ent, depth + 1);
                    212:     }
1.3       daniel    213: }
                    214: 
                    215: void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth) {
                    216:     xmlDebugDumpOneNode(output, node, depth);
1.16      daniel    217:     if (node->children != NULL)
                    218:        xmlDebugDumpNodeList(output, node->children, depth + 1);
1.1       daniel    219: }
                    220: 
                    221: void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth) {
                    222:     while (node != NULL) {
                    223:         xmlDebugDumpNode(output, node, depth);
                    224:        node = node->next;
                    225:     }
                    226: }
                    227: 
                    228: 
1.12      daniel    229: void xmlDebugDumpDocumentHead(FILE *output, xmlDocPtr doc) {
1.1       daniel    230:     if (output == NULL) output = stdout;
                    231:     if (doc == NULL) {
                    232:         fprintf(output, "DOCUMENT == NULL !\n");
                    233:        return;
                    234:     }
                    235: 
                    236:     switch (doc->type) {
                    237:        case XML_ELEMENT_NODE:
                    238:            fprintf(output, "Error, ELEMENT found here ");
                    239:            break;
                    240:        case XML_ATTRIBUTE_NODE:
                    241:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    242:            break;
                    243:        case XML_TEXT_NODE:
                    244:            fprintf(output, "Error, TEXT\n");
                    245:            break;
                    246:        case XML_CDATA_SECTION_NODE:
                    247:            fprintf(output, "Error, CDATA_SECTION\n");
                    248:            break;
                    249:        case XML_ENTITY_REF_NODE:
                    250:            fprintf(output, "Error, ENTITY_REF\n");
                    251:            break;
                    252:        case XML_ENTITY_NODE:
                    253:            fprintf(output, "Error, ENTITY\n");
                    254:            break;
                    255:        case XML_PI_NODE:
                    256:            fprintf(output, "Error, PI\n");
                    257:            break;
                    258:        case XML_COMMENT_NODE:
                    259:            fprintf(output, "Error, COMMENT\n");
                    260:            break;
                    261:        case XML_DOCUMENT_NODE:
                    262:            fprintf(output, "DOCUMENT\n");
1.7       daniel    263:            break;
                    264:        case XML_HTML_DOCUMENT_NODE:
                    265:            fprintf(output, "HTML DOCUMENT\n");
1.1       daniel    266:            break;
                    267:        case XML_DOCUMENT_TYPE_NODE:
                    268:            fprintf(output, "Error, DOCUMENT_TYPE\n");
                    269:            break;
                    270:        case XML_DOCUMENT_FRAG_NODE:
                    271:            fprintf(output, "Error, DOCUMENT_FRAG\n");
                    272:            break;
                    273:        case XML_NOTATION_NODE:
                    274:            fprintf(output, "Error, NOTATION\n");
                    275:            break;
                    276:        default:
                    277:            fprintf(output, "NODE_%d\n", doc->type);
                    278:     }
                    279:     if (doc->name != NULL) {
                    280:        fprintf(output, "name=");
1.5       daniel    281:         xmlDebugDumpString(output, BAD_CAST doc->name);
1.1       daniel    282:        fprintf(output, "\n");
                    283:     }
                    284:     if (doc->version != NULL) {
                    285:        fprintf(output, "version=");
                    286:         xmlDebugDumpString(output, doc->version);
                    287:        fprintf(output, "\n");
                    288:     }
                    289:     if (doc->encoding != NULL) {
                    290:        fprintf(output, "encoding=");
                    291:         xmlDebugDumpString(output, doc->encoding);
                    292:        fprintf(output, "\n");
                    293:     }
                    294:     if (doc->standalone)
                    295:         fprintf(output, "standalone=true\n");
                    296:     if (doc->oldNs != NULL) 
                    297:         xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
1.12      daniel    298: }
                    299: 
                    300: void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
                    301:     if (output == NULL) output = stdout;
                    302:     if (doc == NULL) {
                    303:         fprintf(output, "DOCUMENT == NULL !\n");
                    304:        return;
                    305:     }
                    306:     xmlDebugDumpDocumentHead(output, doc);
                    307:     if (((doc->type == XML_DOCUMENT_NODE) ||
                    308:          (doc->type == XML_HTML_DOCUMENT_NODE)) &&
1.16      daniel    309:         (doc->children != NULL))
                    310:         xmlDebugDumpNodeList(output, doc->children, 1);
1.12      daniel    311: }    
1.9       daniel    312: 
                    313: void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
                    314:     int i;
                    315:     xmlEntityPtr cur;
                    316: 
                    317:     if (output == NULL) output = stdout;
                    318:     if (doc == NULL) {
                    319:         fprintf(output, "DOCUMENT == NULL !\n");
                    320:        return;
                    321:     }
                    322: 
                    323:     switch (doc->type) {
                    324:        case XML_ELEMENT_NODE:
                    325:            fprintf(output, "Error, ELEMENT found here ");
                    326:            break;
                    327:        case XML_ATTRIBUTE_NODE:
                    328:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    329:            break;
                    330:        case XML_TEXT_NODE:
                    331:            fprintf(output, "Error, TEXT\n");
                    332:            break;
                    333:        case XML_CDATA_SECTION_NODE:
                    334:            fprintf(output, "Error, CDATA_SECTION\n");
                    335:            break;
                    336:        case XML_ENTITY_REF_NODE:
                    337:            fprintf(output, "Error, ENTITY_REF\n");
                    338:            break;
                    339:        case XML_ENTITY_NODE:
                    340:            fprintf(output, "Error, ENTITY\n");
                    341:            break;
                    342:        case XML_PI_NODE:
                    343:            fprintf(output, "Error, PI\n");
                    344:            break;
                    345:        case XML_COMMENT_NODE:
                    346:            fprintf(output, "Error, COMMENT\n");
                    347:            break;
                    348:        case XML_DOCUMENT_NODE:
                    349:            fprintf(output, "DOCUMENT\n");
                    350:            break;
                    351:        case XML_HTML_DOCUMENT_NODE:
                    352:            fprintf(output, "HTML DOCUMENT\n");
                    353:            break;
                    354:        case XML_DOCUMENT_TYPE_NODE:
                    355:            fprintf(output, "Error, DOCUMENT_TYPE\n");
                    356:            break;
                    357:        case XML_DOCUMENT_FRAG_NODE:
                    358:            fprintf(output, "Error, DOCUMENT_FRAG\n");
                    359:            break;
                    360:        case XML_NOTATION_NODE:
                    361:            fprintf(output, "Error, NOTATION\n");
                    362:            break;
                    363:        default:
                    364:            fprintf(output, "NODE_%d\n", doc->type);
                    365:     }
                    366:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                    367:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
                    368:                                    doc->intSubset->entities;
                    369:        fprintf(output, "Entities in internal subset\n");
                    370:        for (i = 0;i < table->nb_entities;i++) {
                    371:            cur = &table->table[i];
                    372:            fprintf(output, "%d : %s : ", i, cur->name);
                    373:            switch (cur->type) {
                    374:                case XML_INTERNAL_GENERAL_ENTITY:
                    375:                    fprintf(output, "INTERNAL GENERAL");
                    376:                    break;
                    377:                case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    378:                    fprintf(output, "EXTERNAL PARSED");
                    379:                    break;
                    380:                case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    381:                    fprintf(output, "EXTERNAL UNPARSED");
                    382:                    break;
                    383:                case XML_INTERNAL_PARAMETER_ENTITY:
                    384:                    fprintf(output, "INTERNAL PARAMETER");
                    385:                    break;
                    386:                case XML_EXTERNAL_PARAMETER_ENTITY:
                    387:                    fprintf(output, "EXTERNAL PARAMETER");
                    388:                    break;
                    389:                default:
                    390:                    fprintf(output, "UNKNOWN TYPE %d",
                    391:                            cur->type);
                    392:            }
                    393:            if (cur->ExternalID != NULL) 
                    394:                fprintf(output, "ID \"%s\"", cur->ExternalID);
                    395:            if (cur->SystemID != NULL)
                    396:                fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
                    397:            if (cur->orig != NULL)
                    398:                fprintf(output, "\n orig \"%s\"", cur->orig);
                    399:            if (cur->content != NULL)
                    400:                fprintf(output, "\n content \"%s\"", cur->content);
                    401:            fprintf(output, "\n");      
                    402:        }
                    403:     } else
                    404:        fprintf(output, "No entities in internal subset\n");
                    405:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    406:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
                    407:                                    doc->extSubset->entities;
                    408:        fprintf(output, "Entities in external subset\n");
                    409:        for (i = 0;i < table->nb_entities;i++) {
                    410:            cur = &table->table[i];
                    411:            fprintf(output, "%d : %s : ", i, cur->name);
                    412:            switch (cur->type) {
                    413:                case XML_INTERNAL_GENERAL_ENTITY:
                    414:                    fprintf(output, "INTERNAL GENERAL");
                    415:                    break;
                    416:                case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    417:                    fprintf(output, "EXTERNAL PARSED");
                    418:                    break;
                    419:                case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    420:                    fprintf(output, "EXTERNAL UNPARSED");
                    421:                    break;
                    422:                case XML_INTERNAL_PARAMETER_ENTITY:
                    423:                    fprintf(output, "INTERNAL PARAMETER");
                    424:                    break;
                    425:                case XML_EXTERNAL_PARAMETER_ENTITY:
                    426:                    fprintf(output, "EXTERNAL PARAMETER");
                    427:                    break;
                    428:                default:
                    429:                    fprintf(output, "UNKNOWN TYPE %d",
                    430:                            cur->type);
                    431:            }
                    432:            if (cur->ExternalID != NULL) 
                    433:                fprintf(output, "ID \"%s\"", cur->ExternalID);
                    434:            if (cur->SystemID != NULL)
                    435:                fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
                    436:            if (cur->orig != NULL)
                    437:                fprintf(output, "\n orig \"%s\"", cur->orig);
                    438:            if (cur->content != NULL)
                    439:                fprintf(output, "\n content \"%s\"", cur->content);
                    440:            fprintf(output, "\n");      
                    441:        }
                    442:     } else
                    443:        fprintf(output, "No entities in external subset\n");
                    444: }
1.12      daniel    445: 
                    446: static int xmlLsCountNode(xmlNodePtr node) {
                    447:     int ret = 0;
                    448:     xmlNodePtr list = NULL;
                    449: 
                    450:     switch (node->type) {
                    451:        case XML_ELEMENT_NODE:
1.16      daniel    452:            list = node->children;
1.12      daniel    453:            break;
                    454:        case XML_DOCUMENT_NODE:
                    455:        case XML_HTML_DOCUMENT_NODE:
1.16      daniel    456:            list = ((xmlDocPtr) node)->children;
1.12      daniel    457:            break;
                    458:        case XML_ATTRIBUTE_NODE:
1.16      daniel    459:            list = ((xmlAttrPtr) node)->children;
1.12      daniel    460:            break;
                    461:        case XML_TEXT_NODE:
                    462:        case XML_CDATA_SECTION_NODE:
                    463:        case XML_PI_NODE:
                    464:        case XML_COMMENT_NODE:
                    465:            if (node->content != NULL) {
                    466: #ifndef XML_USE_BUFFER_CONTENT     
                    467:                ret = xmlStrlen(node->content);
                    468: #else
                    469:                ret = xmlBufferLength(node->content);
                    470: #endif
                    471:             }
                    472:            break;
                    473:        case XML_ENTITY_REF_NODE:
                    474:        case XML_DOCUMENT_TYPE_NODE:
                    475:        case XML_ENTITY_NODE:
                    476:        case XML_DOCUMENT_FRAG_NODE:
                    477:        case XML_NOTATION_NODE:
1.16      daniel    478:        case XML_DTD_NODE:
1.17    ! daniel    479:         case XML_ELEMENT_DECL:
        !           480:         case XML_ATTRIBUTE_DECL:
1.12      daniel    481:            ret = 1;
                    482:            break;
                    483:     }
                    484:     for (;list != NULL;ret++) 
                    485:         list = list->next;
                    486:     return(ret);
                    487: }
                    488: 
                    489: void xmlLsOneNode(FILE *output, xmlNodePtr node) {
                    490:     switch (node->type) {
                    491:        case XML_ELEMENT_NODE:
                    492:            fprintf(output, "-");
                    493:            break;
                    494:        case XML_ATTRIBUTE_NODE:
                    495:            fprintf(output, "a");
                    496:            break;
                    497:        case XML_TEXT_NODE:
                    498:            fprintf(output, "t");
                    499:            break;
                    500:        case XML_CDATA_SECTION_NODE:
                    501:            fprintf(output, "c");
                    502:            break;
                    503:        case XML_ENTITY_REF_NODE:
                    504:            fprintf(output, "e");
                    505:            break;
                    506:        case XML_ENTITY_NODE:
                    507:            fprintf(output, "E");
                    508:            break;
                    509:        case XML_PI_NODE:
                    510:            fprintf(output, "p");
                    511:            break;
                    512:        case XML_COMMENT_NODE:
                    513:            fprintf(output, "c");
                    514:            break;
                    515:        case XML_DOCUMENT_NODE:
                    516:            fprintf(output, "d");
                    517:            break;
                    518:        case XML_HTML_DOCUMENT_NODE:
                    519:            fprintf(output, "h");
                    520:            break;
                    521:        case XML_DOCUMENT_TYPE_NODE:
                    522:            fprintf(output, "T");
                    523:            break;
                    524:        case XML_DOCUMENT_FRAG_NODE:
                    525:            fprintf(output, "F");
                    526:            break;
                    527:        case XML_NOTATION_NODE:
                    528:            fprintf(output, "N");
                    529:            break;
                    530:        default:
                    531:            fprintf(output, "?");
                    532:     }
                    533:     if (node->properties != NULL)
                    534:        fprintf(output, "a");
                    535:     else       
                    536:        fprintf(output, "-");
                    537:     if (node->nsDef != NULL) 
                    538:        fprintf(output, "n");
                    539:     else       
                    540:        fprintf(output, "-");
                    541: 
                    542:     fprintf(output, " %8d ", xmlLsCountNode(node));
                    543: 
                    544:     switch (node->type) {
                    545:        case XML_ELEMENT_NODE:
                    546:            if (node->name != NULL)
                    547:                fprintf(output, "%s", node->name);
                    548:            break;
                    549:        case XML_ATTRIBUTE_NODE:
                    550:            if (node->name != NULL)
                    551:                fprintf(output, "%s", node->name);
                    552:            break;
                    553:        case XML_TEXT_NODE:
                    554:            if (node->content != NULL) {
                    555: #ifndef XML_USE_BUFFER_CONTENT     
                    556:                xmlDebugDumpString(output, node->content);
                    557: #else
                    558:                xmlDebugDumpString(output, xmlBufferContent(node->content));
                    559: #endif
                    560:             }
                    561:            break;
                    562:        case XML_CDATA_SECTION_NODE:
                    563:            break;
                    564:        case XML_ENTITY_REF_NODE:
                    565:            if (node->name != NULL)
                    566:                fprintf(output, "%s", node->name);
                    567:            break;
                    568:        case XML_ENTITY_NODE:
                    569:            if (node->name != NULL)
                    570:                fprintf(output, "%s", node->name);
                    571:            break;
                    572:        case XML_PI_NODE:
                    573:            if (node->name != NULL)
                    574:                fprintf(output, "%s", node->name);
                    575:            break;
                    576:        case XML_COMMENT_NODE:
                    577:            break;
                    578:        case XML_DOCUMENT_NODE:
                    579:            break;
                    580:        case XML_HTML_DOCUMENT_NODE:
                    581:            break;
                    582:        case XML_DOCUMENT_TYPE_NODE:
                    583:            break;
                    584:        case XML_DOCUMENT_FRAG_NODE:
                    585:            break;
                    586:        case XML_NOTATION_NODE:
                    587:            break;
                    588:        default:
                    589:            if (node->name != NULL)
                    590:                fprintf(output, "%s", node->name);
                    591:     }
                    592:     fprintf(output, "\n");
                    593: }
                    594: 
                    595: /****************************************************************
                    596:  *                                                             *
                    597:  *             The XML shell related functions                 *
                    598:  *                                                             *
                    599:  ****************************************************************/
                    600: 
                    601: /*
                    602:  * TODO: Improvement/cleanups for the XML shell
                    603:  *     - allow to shell out an editor on a subpart
                    604:  *     - cleanup function registrations (with help) and calling
                    605:  *     - provide registration routines
                    606:  */
                    607: 
                    608: /**
                    609:  * xmlShellList:
                    610:  * @ctxt:  the shell context
                    611:  * @arg:  unused
                    612:  * @node:  a node
                    613:  * @node2:  unused
                    614:  *
                    615:  * Implements the XML shell function "ls"
                    616:  * Does an Unix like listing of the given node (like a directory)
                    617:  *
                    618:  * Returns 0
                    619:  */
                    620: int
                    621: xmlShellList(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                    622:                   xmlNodePtr node2) {
                    623:     xmlNodePtr cur;
                    624: 
                    625:     if ((node->type == XML_DOCUMENT_NODE) ||
                    626:         (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16      daniel    627:         cur = ((xmlDocPtr) node)->children;
                    628:     } else if (node->children != NULL) {
                    629:         cur = node->children;
1.12      daniel    630:     } else {
                    631:        xmlLsOneNode(stdout, node);
                    632:         return(0);
                    633:     }
                    634:     while (cur != NULL) {
                    635:        xmlLsOneNode(stdout, cur);
                    636:        cur = cur->next;
                    637:     }
                    638:     return(0);
                    639: }
                    640: 
                    641: /**
                    642:  * xmlShellDir:
                    643:  * @ctxt:  the shell context
                    644:  * @arg:  unused
                    645:  * @node:  a node
                    646:  * @node2:  unused
                    647:  *
                    648:  * Implements the XML shell function "dir"
                    649:  * dumps informations about the node (namespace, attributes, content).
                    650:  *
                    651:  * Returns 0
                    652:  */
                    653: int
                    654: xmlShellDir(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                    655:                   xmlNodePtr node2) {
                    656:     if ((node->type == XML_DOCUMENT_NODE) ||
                    657:         (node->type == XML_HTML_DOCUMENT_NODE)) {
                    658:        xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
                    659:     } else if (node->type == XML_ATTRIBUTE_NODE) {
                    660:        xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
                    661:     } else {
                    662:        xmlDebugDumpOneNode(stdout, node, 0);
                    663:     }
                    664:     return(0);
                    665: }
                    666: 
                    667: /**
                    668:  * xmlShellCat:
                    669:  * @ctxt:  the shell context
                    670:  * @arg:  unused
                    671:  * @node:  a node
                    672:  * @node2:  unused
                    673:  *
                    674:  * Implements the XML shell function "cat"
                    675:  * dumps the serialization node content (XML or HTML).
                    676:  *
                    677:  * Returns 0
                    678:  */
                    679: int
                    680: xmlShellCat(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                    681:                   xmlNodePtr node2) {
1.13      daniel    682:     if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
                    683:        if (node->type == XML_HTML_DOCUMENT_NODE)
                    684:            htmlDocDump(stdout, (htmlDocPtr) node);
                    685:        else
1.14      daniel    686:            htmlNodeDumpFile(stdout, ctxt->doc, node);
1.13      daniel    687:     } else {
                    688:        if (node->type == XML_DOCUMENT_NODE)
                    689:            xmlDocDump(stdout, (xmlDocPtr) node);
                    690:        else
                    691:            xmlElemDump(stdout, ctxt->doc, node);
                    692:     }
1.12      daniel    693:     printf("\n");
                    694:     return(0);
                    695: }
                    696: 
                    697: /**
                    698:  * xmlShellLoad:
                    699:  * @ctxt:  the shell context
                    700:  * @filename:  the file name
                    701:  * @node:  unused
                    702:  * @node2:  unused
                    703:  *
                    704:  * Implements the XML shell function "load"
                    705:  * loads a new document specified by the filename
                    706:  *
                    707:  * Returns 0 or -1 if loading failed
                    708:  */
                    709: int
                    710: xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                    711:              xmlNodePtr node2) {
                    712:     xmlDocPtr doc;
                    713:     int html = 0;
                    714: 
                    715:     if (ctxt->doc != NULL)
                    716:        html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
                    717: 
                    718:     if (html) {
                    719:        doc = htmlParseFile(filename, NULL);
                    720:     } else {
                    721:        doc = xmlParseFile(filename);
                    722:     }
                    723:     if (doc != NULL) {
                    724:         if (ctxt->loaded == 1) {
                    725:            xmlFreeDoc(ctxt->doc);
                    726:        }
                    727:        ctxt->loaded = 1;
                    728:        xmlXPathFreeContext(ctxt->pctxt);
                    729:        xmlFree(ctxt->filename);
                    730:        ctxt->doc = doc;
                    731:        ctxt->node = (xmlNodePtr) doc;   
                    732:        ctxt->pctxt = xmlXPathNewContext(doc);
                    733:        ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
                    734:     } else
                    735:         return(-1);
                    736:     return(0);
                    737: }
                    738: 
                    739: /**
                    740:  * xmlShellWrite:
                    741:  * @ctxt:  the shell context
                    742:  * @filename:  the file name
                    743:  * @node:  a node in the tree
                    744:  * @node2:  unused
                    745:  *
                    746:  * Implements the XML shell function "write"
                    747:  * Write the current node to the filename, it saves the serailization
                    748:  * of the subtree under the @node specified
                    749:  *
                    750:  * Returns 0 or -1 in case of error
                    751:  */
                    752: int
                    753: xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                    754:                   xmlNodePtr node2) {
                    755:     if (node == NULL)
                    756:         return(-1);
                    757:     if ((filename == NULL) || (filename[0] == 0)) {
                    758:         fprintf(stderr, "Write command requires a filename argument\n");
                    759:        return(-1);
                    760:     }
                    761: #ifdef W_OK
                    762:     if (access((char *) filename, W_OK)) {
                    763:         fprintf(stderr, "Cannot write to %s\n", filename);
                    764:        return(-1);
                    765:     }
                    766: #endif    
                    767:     switch(node->type) {
                    768:         case XML_DOCUMENT_NODE:
                    769:            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
                    770:                fprintf(stderr, "Failed to write to %s\n", filename);
                    771:                return(-1);
                    772:            }
                    773:            break;
                    774:         case XML_HTML_DOCUMENT_NODE:
                    775:            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                    776:                fprintf(stderr, "Failed to write to %s\n", filename);
                    777:                return(-1);
                    778:            }
                    779:            break;
                    780:        default: {
                    781:            FILE *f;
                    782: 
                    783:            f = fopen((char *) filename, "w");
                    784:            if (f == NULL) {
                    785:                fprintf(stderr, "Failed to write to %s\n", filename);
                    786:                return(-1);
                    787:            }
                    788:            xmlElemDump(f, ctxt->doc, node);
                    789:            fclose(f);
                    790:        }
                    791:     }
                    792:     return(0);
                    793: }
                    794: 
                    795: /**
                    796:  * xmlShellSave:
                    797:  * @ctxt:  the shell context
                    798:  * @filename:  the file name (optionnal)
                    799:  * @node:  unused
                    800:  * @node2:  unused
                    801:  *
                    802:  * Implements the XML shell function "save"
                    803:  * Write the current document to the filename, or it's original name
                    804:  *
                    805:  * Returns 0 or -1 in case of error
                    806:  */
                    807: int 
                    808: xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                    809:              xmlNodePtr node2) {
                    810:     if (ctxt->doc == NULL)
                    811:        return(-1);
                    812:     if ((filename == NULL) || (filename[0] == 0))
                    813:         filename = ctxt->filename;
                    814: #ifdef W_OK
                    815:     if (access((char *) filename, W_OK)) {
                    816:         fprintf(stderr, "Cannot save to %s\n", filename);
                    817:        return(-1);
                    818:     }
                    819: #endif
                    820:     switch(ctxt->doc->type) {
                    821:         case XML_DOCUMENT_NODE:
                    822:            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
                    823:                fprintf(stderr, "Failed to save to %s\n", filename);
                    824:            }
                    825:            break;
                    826:         case XML_HTML_DOCUMENT_NODE:
                    827:            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                    828:                fprintf(stderr, "Failed to save to %s\n", filename);
                    829:            }
                    830:            break;
                    831:        default:
                    832:            fprintf(stderr, 
                    833:              "To save to subparts of a document use the 'write' command\n");
                    834:            return(-1);
                    835:            
                    836:     }
                    837:     return(0);
                    838: }
                    839: 
                    840: /**
                    841:  * xmlShellValidate:
                    842:  * @ctxt:  the shell context
                    843:  * @dtd:  the DTD URI (optionnal)
                    844:  * @node:  unused
                    845:  * @node2:  unused
                    846:  *
                    847:  * Implements the XML shell function "validate"
                    848:  * Validate the document, if a DTD path is provided, then the validation
                    849:  * is done against the given DTD.
                    850:  *
                    851:  * Returns 0 or -1 in case of error
                    852:  */
                    853: int 
                    854: xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node,
                    855:                  xmlNodePtr node2) {
                    856:     xmlValidCtxt vctxt;
                    857:     int res = -1;
                    858: 
                    859:     vctxt.userData = stderr;
                    860:     vctxt.error = (xmlValidityErrorFunc) fprintf;
                    861:     vctxt.warning = (xmlValidityWarningFunc) fprintf;
                    862: 
                    863:     if ((dtd == NULL) || (dtd[0] == 0)) {
                    864:         res = xmlValidateDocument(&vctxt, ctxt->doc);
                    865:     } else {
                    866:         xmlDtdPtr subset;
                    867: 
                    868:        subset = xmlParseDTD(NULL, (xmlChar *) dtd);
                    869:        if (subset != NULL) {
                    870:             res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
                    871: 
                    872:            xmlFreeDtd(subset);
                    873:        }
                    874:     }
                    875:     return(res);
                    876: }
                    877: 
                    878: /**
                    879:  * xmlShellDu:
                    880:  * @ctxt:  the shell context
                    881:  * @arg:  unused
                    882:  * @tree:  a node defining a subtree
                    883:  * @node2:  unused
                    884:  *
                    885:  * Implements the XML shell function "du"
                    886:  * show the structure of the subtree under node @tree
                    887:  * If @tree is null, the command works on the current node.
                    888:  *
                    889:  * Returns 0 or -1 in case of error
                    890:  */
                    891: int 
                    892: xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
                    893:                   xmlNodePtr node2) {
                    894:     xmlNodePtr node;
                    895:     int indent = 0,i;
                    896: 
                    897:     if (tree == NULL) return(-1);
                    898:     node = tree;
                    899:     while (node != NULL) {
                    900:         if ((node->type == XML_DOCUMENT_NODE) ||
                    901:             (node->type == XML_HTML_DOCUMENT_NODE)) {
                    902:            printf("/\n");
                    903:        } else if (node->type == XML_ELEMENT_NODE) {
                    904:            for (i = 0;i < indent;i++)
                    905:                printf("  ");
                    906:            printf("%s\n", node->name);
                    907:        } else {
                    908:        }
                    909: 
                    910:        /*
                    911:         * Browse the full subtree, deep first
                    912:         */
                    913: 
                    914:         if ((node->type == XML_DOCUMENT_NODE) ||
                    915:             (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16      daniel    916:            node = ((xmlDocPtr) node)->children;
                    917:         } else if (node->children != NULL) {
1.12      daniel    918:            /* deep first */
1.16      daniel    919:            node = node->children;
1.12      daniel    920:            indent++;
                    921:        } else if ((node != tree) && (node->next != NULL)) {
                    922:            /* then siblings */
                    923:            node = node->next;
                    924:        } else if (node != tree) {
                    925:            /* go up to parents->next if needed */
                    926:            while (node != tree) {
                    927:                if (node->parent != NULL) {
                    928:                    node = node->parent;
                    929:                    indent--;
                    930:                }
                    931:                if ((node != tree) && (node->next != NULL)) {
                    932:                    node = node->next;
                    933:                    break;
                    934:                }
                    935:                if (node->parent == NULL) {
                    936:                    node = NULL;
                    937:                    break;
                    938:                }
                    939:                if (node == tree) {
                    940:                    node = NULL;
                    941:                    break;
                    942:                }
                    943:            }
                    944:            /* exit condition */
                    945:            if (node == tree) 
                    946:                node = NULL;
                    947:        } else
                    948:            node = NULL;
                    949:     }
                    950:     return(0);
                    951: }
                    952: 
                    953: /**
                    954:  * xmlShellPwd:
                    955:  * @ctxt:  the shell context
                    956:  * @buffer:  the output buffer
                    957:  * @tree:  a node 
                    958:  * @node2:  unused
                    959:  *
                    960:  * Implements the XML shell function "pwd"
                    961:  * Show the full path from the root to the node, if needed building
                    962:  * thumblers when similar elements exists at a given ancestor level.
                    963:  * The output is compatible with XPath commands.
                    964:  *
                    965:  * Returns 0 or -1 in case of error
                    966:  */
                    967: int 
                    968: xmlShellPwd(xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node,
                    969:                   xmlNodePtr node2) {
                    970:     xmlNodePtr cur, tmp, next;
                    971:     char buf[500];
                    972:     char sep;
                    973:     const char *name;
                    974:     int occur = 0;
                    975: 
                    976:     buffer[0] = 0;
                    977:     if (node == NULL) return(-1);
                    978:     cur = node;
                    979:     do {
                    980:        name = "";
                    981:        sep= '?';
                    982:        occur = 0;
                    983:        if ((cur->type == XML_DOCUMENT_NODE) ||
                    984:            (cur->type == XML_HTML_DOCUMENT_NODE)) {
                    985:            sep = '/';
                    986:            next = NULL;
                    987:        } else if (cur->type == XML_ELEMENT_NODE) {
                    988:            sep = '/';
                    989:            name = (const char *)cur->name;
                    990:            next = cur->parent;
                    991: 
                    992:            /*
                    993:             * Thumbler index computation
                    994:             */
                    995:            tmp = cur->prev;
                    996:             while (tmp != NULL) {
                    997:                if (!xmlStrcmp(cur->name, tmp->name))
                    998:                    occur++;
                    999:                tmp = tmp->prev;
                   1000:            }
                   1001:            if (occur == 0) {
                   1002:                tmp = cur->next;
                   1003:                while (tmp != NULL) {
                   1004:                    if (!xmlStrcmp(cur->name, tmp->name))
                   1005:                        occur++;
                   1006:                    tmp = tmp->next;
                   1007:                }
                   1008:                if (occur != 0) occur = 1;
                   1009:            } else
                   1010:                occur++;
                   1011:        } else if (cur->type == XML_ATTRIBUTE_NODE) {
                   1012:            sep = '@';
                   1013:            name = (const char *) (((xmlAttrPtr) cur)->name);
1.16      daniel   1014:            next = ((xmlAttrPtr) cur)->parent;
1.12      daniel   1015:        } else {
                   1016:            next = cur->parent;
                   1017:        }
                   1018:        if (occur == 0)
                   1019:            sprintf(buf, "%c%s%s", sep, name, buffer);
                   1020:        else
                   1021:            sprintf(buf, "%c%s[%d]%s", sep, name, occur, buffer);
                   1022:        strcpy(buffer, buf);
                   1023:         cur = next;
                   1024:     } while (cur != NULL);
                   1025:     return(0);
                   1026: }
                   1027: 
                   1028: /**
                   1029:  * xmlShell
                   1030:  * @doc:  the initial document
                   1031:  * @filename:  the output buffer
                   1032:  * @input:  the line reading function
                   1033:  * @output:  the output FILE*
                   1034:  *
                   1035:  * Implements the XML shell 
                   1036:  * This allow to load, validate, view, modify and save a document
                   1037:  * using a environment similar to a UNIX commandline.
                   1038:  */
                   1039: void
                   1040: xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                   1041:          FILE *output) {
                   1042:     char prompt[500] = "/ > ";
                   1043:     char *cmdline = NULL;
                   1044:     int nbargs;
                   1045:     char command[100];
                   1046:     char arg[400];
                   1047:     xmlShellCtxtPtr ctxt;
                   1048:     xmlXPathObjectPtr list;
                   1049: 
                   1050:     if (doc == NULL)
                   1051:         return;
                   1052:     if (filename == NULL)
                   1053:         return;
                   1054:     if (input == NULL)
                   1055:         return;
                   1056:     if (output == NULL)
                   1057:         return;
                   1058:     ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
                   1059:     if (ctxt == NULL) 
                   1060:         return;
                   1061:     ctxt->loaded = 0;
                   1062:     ctxt->doc = doc;
                   1063:     ctxt->input = input;
                   1064:     ctxt->output = output;
                   1065:     ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
                   1066:     ctxt->node = (xmlNodePtr) ctxt->doc;        
                   1067: 
                   1068:     ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
                   1069:     if (ctxt->pctxt == NULL) {
                   1070:        xmlFree(ctxt);
                   1071:        return;
                   1072:     }
                   1073:     while (1) {
                   1074:         if (ctxt->node == (xmlNodePtr) ctxt->doc)
                   1075:            sprintf(prompt, "%s > ", "/");
                   1076:        else if (ctxt->node->name)
                   1077:            sprintf(prompt, "%s > ", ctxt->node->name);
                   1078:        else
                   1079:            sprintf(prompt, "? > ");
                   1080: 
                   1081:         cmdline = ctxt->input(prompt);
                   1082:         if (cmdline == NULL) break;
                   1083: 
                   1084:        command[0] = 0;
                   1085:        arg[0] = 0;
                   1086:        nbargs = sscanf(cmdline, "%s %s", command, arg);
                   1087: 
                   1088:        if (command[0] == 0) continue;
                   1089:         if (!strcmp(command, "exit"))
                   1090:            break;
                   1091:         if (!strcmp(command, "quit"))
                   1092:            break;
                   1093:         if (!strcmp(command, "bye"))
                   1094:            break;
                   1095:        if (!strcmp(command, "validate")) {
                   1096:            xmlShellValidate(ctxt, arg, NULL, NULL);
                   1097:        } else if (!strcmp(command, "load")) {
                   1098:            xmlShellLoad(ctxt, arg, NULL, NULL);
                   1099:        } else if (!strcmp(command, "save")) {
                   1100:            xmlShellSave(ctxt, arg, NULL, NULL);
                   1101:        } else if (!strcmp(command, "write")) {
                   1102:            xmlShellWrite(ctxt, arg, NULL, NULL);
                   1103:        } else if (!strcmp(command, "free")) {
                   1104:            if (arg[0] == 0) {
                   1105:                xmlMemShow(stdout, 0);
                   1106:            } else {
                   1107:                int len = 0;
                   1108:                sscanf(arg, "%d", &len);
                   1109:                xmlMemShow(stdout, len);
                   1110:            }
                   1111:        } else if (!strcmp(command, "pwd")) {
                   1112:            char dir[500];
                   1113:            if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
                   1114:                printf("%s\n", dir);
                   1115:        } else  if (!strcmp(command, "du")) {
                   1116:            xmlShellDu(ctxt, NULL, ctxt->node, NULL);
                   1117:        } else  if ((!strcmp(command, "ls")) ||
                   1118:              (!strcmp(command, "dir"))) {
                   1119:            int dir = (!strcmp(command, "dir"));
                   1120:            if (arg[0] == 0) {
                   1121:                if (dir)
                   1122:                    xmlShellDir(ctxt, NULL, ctxt->node, NULL);
                   1123:                else
                   1124:                    xmlShellList(ctxt, NULL, ctxt->node, NULL);
                   1125:            } else {
                   1126:                ctxt->pctxt->node = ctxt->node;
                   1127:                if (ctxt->pctxt->nodelist != NULL)
                   1128:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1129:                ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
                   1130:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
                   1131:                if (list != NULL) {
                   1132:                    switch (list->type) {
                   1133:                        case XPATH_UNDEFINED:
                   1134:                            fprintf(stderr, "%s: no such node\n", arg);
                   1135:                            break;
                   1136:                        case XPATH_NODESET: {
                   1137:                            int i;
                   1138: 
                   1139:                            for (i = 0;i < list->nodesetval->nodeNr;i++) {
                   1140:                                if (dir)
                   1141:                                    xmlShellDir(ctxt, NULL,
                   1142:                                       list->nodesetval->nodeTab[i], NULL);
                   1143:                                else
                   1144:                                    xmlShellList(ctxt, NULL,
                   1145:                                       list->nodesetval->nodeTab[i], NULL);
                   1146:                            }
                   1147:                            break;
                   1148:                        }
                   1149:                        case XPATH_BOOLEAN:
                   1150:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1151:                            break;
                   1152:                        case XPATH_NUMBER:
                   1153:                            fprintf(stderr, "%s is a number\n", arg);
                   1154:                            break;
                   1155:                        case XPATH_STRING:
                   1156:                            fprintf(stderr, "%s is a string\n", arg);
                   1157:                            break;
                   1158:                    }
                   1159:                    xmlXPathFreeNodeSetList(list);
                   1160:                } else {
                   1161:                    fprintf(stderr, "%s: no such node\n", arg);
                   1162:                }
                   1163:                if (ctxt->pctxt->nodelist != NULL)
                   1164:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1165:                ctxt->pctxt->nodelist = NULL;
                   1166:            }
                   1167:        } else if (!strcmp(command, "cd")) {
                   1168:            if (arg[0] == 0) {
                   1169:                ctxt->node = (xmlNodePtr) ctxt->doc;
                   1170:            } else {
                   1171:                ctxt->pctxt->node = ctxt->node;
                   1172:                if (ctxt->pctxt->nodelist != NULL)
                   1173:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1174:                ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
                   1175:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
                   1176:                if (list != NULL) {
                   1177:                    switch (list->type) {
                   1178:                        case XPATH_UNDEFINED:
                   1179:                            fprintf(stderr, "%s: no such node\n", arg);
                   1180:                            break;
                   1181:                        case XPATH_NODESET:
                   1182:                            if (list->nodesetval->nodeNr == 1) {
                   1183:                                ctxt->node = list->nodesetval->nodeTab[0];
                   1184:                            } else 
                   1185:                                fprintf(stderr, "%s is a %d Node Set\n",
                   1186:                                        arg, list->nodesetval->nodeNr);
                   1187:                            break;
                   1188:                        case XPATH_BOOLEAN:
                   1189:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1190:                            break;
                   1191:                        case XPATH_NUMBER:
                   1192:                            fprintf(stderr, "%s is a number\n", arg);
                   1193:                            break;
                   1194:                        case XPATH_STRING:
                   1195:                            fprintf(stderr, "%s is a string\n", arg);
                   1196:                            break;
                   1197:                    }
                   1198:                    xmlXPathFreeNodeSetList(list);
                   1199:                } else {
                   1200:                    fprintf(stderr, "%s: no such node\n", arg);
                   1201:                }
                   1202:                if (ctxt->pctxt->nodelist != NULL)
                   1203:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1204:                ctxt->pctxt->nodelist = NULL;
                   1205:            }
                   1206:        } else if (!strcmp(command, "cat")) {
                   1207:            if (arg[0] == 0) {
                   1208:                xmlShellCat(ctxt, NULL, ctxt->node, NULL);
                   1209:            } else {
                   1210:                ctxt->pctxt->node = ctxt->node;
                   1211:                if (ctxt->pctxt->nodelist != NULL)
                   1212:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1213:                ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
                   1214:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
                   1215:                if (list != NULL) {
                   1216:                    switch (list->type) {
                   1217:                        case XPATH_UNDEFINED:
                   1218:                            fprintf(stderr, "%s: no such node\n", arg);
                   1219:                            break;
                   1220:                        case XPATH_NODESET: {
                   1221:                            int i;
                   1222: 
                   1223:                            for (i = 0;i < list->nodesetval->nodeNr;i++) {
                   1224:                                if (i > 0) printf(" -------\n");
                   1225:                                xmlShellCat(ctxt, NULL,
                   1226:                                    list->nodesetval->nodeTab[i], NULL);
                   1227:                            }
                   1228:                            break;
                   1229:                        }
                   1230:                        case XPATH_BOOLEAN:
                   1231:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1232:                            break;
                   1233:                        case XPATH_NUMBER:
                   1234:                            fprintf(stderr, "%s is a number\n", arg);
                   1235:                            break;
                   1236:                        case XPATH_STRING:
                   1237:                            fprintf(stderr, "%s is a string\n", arg);
                   1238:                            break;
                   1239:                    }
                   1240:                    xmlXPathFreeNodeSetList(list);
                   1241:                } else {
                   1242:                    fprintf(stderr, "%s: no such node\n", arg);
                   1243:                }
                   1244:                if (ctxt->pctxt->nodelist != NULL)
                   1245:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1246:                ctxt->pctxt->nodelist = NULL;
                   1247:            }
                   1248:        } else {
                   1249:            fprintf(stderr, "Unknown command %s\n", command);
                   1250:        }
                   1251:        free(cmdline); /* not xmlFree here ! */
                   1252:     }
                   1253:     xmlXPathFreeContext(ctxt->pctxt);
                   1254:     if (ctxt->loaded) {
                   1255:         xmlFreeDoc(ctxt->doc);
                   1256:     }
                   1257:     xmlFree(ctxt);
                   1258:     if (cmdline != NULL)
                   1259:         free(cmdline); /* not xmlFree here ! */
                   1260: }
                   1261: 

Webmaster