Annotation of XML/debugXML.c, revision 1.13

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

Webmaster