Annotation of XML/debugXML.c, revision 1.24

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

Webmaster