Annotation of XML/debugXML.c, revision 1.25

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:     }
                    676:     if (doc->standalone)
                    677:         fprintf(output, "standalone=true\n");
                    678:     if (doc->oldNs != NULL) 
                    679:         xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
1.12      daniel    680: }
                    681: 
                    682: void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
                    683:     if (output == NULL) output = stdout;
                    684:     if (doc == NULL) {
                    685:         fprintf(output, "DOCUMENT == NULL !\n");
                    686:        return;
                    687:     }
                    688:     xmlDebugDumpDocumentHead(output, doc);
                    689:     if (((doc->type == XML_DOCUMENT_NODE) ||
                    690:          (doc->type == XML_HTML_DOCUMENT_NODE)) &&
1.16      daniel    691:         (doc->children != NULL))
                    692:         xmlDebugDumpNodeList(output, doc->children, 1);
1.12      daniel    693: }    
1.9       daniel    694: 
                    695: void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
                    696:     int i;
                    697:     xmlEntityPtr cur;
                    698: 
                    699:     if (output == NULL) output = stdout;
                    700:     if (doc == NULL) {
                    701:         fprintf(output, "DOCUMENT == NULL !\n");
                    702:        return;
                    703:     }
                    704: 
                    705:     switch (doc->type) {
                    706:        case XML_ELEMENT_NODE:
                    707:            fprintf(output, "Error, ELEMENT found here ");
                    708:            break;
                    709:        case XML_ATTRIBUTE_NODE:
                    710:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    711:            break;
                    712:        case XML_TEXT_NODE:
                    713:            fprintf(output, "Error, TEXT\n");
                    714:            break;
                    715:        case XML_CDATA_SECTION_NODE:
                    716:            fprintf(output, "Error, CDATA_SECTION\n");
                    717:            break;
                    718:        case XML_ENTITY_REF_NODE:
                    719:            fprintf(output, "Error, ENTITY_REF\n");
                    720:            break;
                    721:        case XML_ENTITY_NODE:
                    722:            fprintf(output, "Error, ENTITY\n");
                    723:            break;
                    724:        case XML_PI_NODE:
                    725:            fprintf(output, "Error, PI\n");
                    726:            break;
                    727:        case XML_COMMENT_NODE:
                    728:            fprintf(output, "Error, COMMENT\n");
                    729:            break;
                    730:        case XML_DOCUMENT_NODE:
                    731:            fprintf(output, "DOCUMENT\n");
                    732:            break;
                    733:        case XML_HTML_DOCUMENT_NODE:
                    734:            fprintf(output, "HTML DOCUMENT\n");
                    735:            break;
                    736:        case XML_DOCUMENT_TYPE_NODE:
                    737:            fprintf(output, "Error, DOCUMENT_TYPE\n");
                    738:            break;
                    739:        case XML_DOCUMENT_FRAG_NODE:
                    740:            fprintf(output, "Error, DOCUMENT_FRAG\n");
                    741:            break;
                    742:        case XML_NOTATION_NODE:
                    743:            fprintf(output, "Error, NOTATION\n");
                    744:            break;
                    745:        default:
                    746:            fprintf(output, "NODE_%d\n", doc->type);
                    747:     }
                    748:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                    749:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
                    750:                                    doc->intSubset->entities;
                    751:        fprintf(output, "Entities in internal subset\n");
                    752:        for (i = 0;i < table->nb_entities;i++) {
1.20      daniel    753:            cur = table->table[i];
1.9       daniel    754:            fprintf(output, "%d : %s : ", i, cur->name);
1.19      daniel    755:            switch (cur->etype) {
1.9       daniel    756:                case XML_INTERNAL_GENERAL_ENTITY:
1.22      daniel    757:                    fprintf(output, "INTERNAL GENERAL, ");
1.9       daniel    758:                    break;
                    759:                case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1.22      daniel    760:                    fprintf(output, "EXTERNAL PARSED, ");
1.9       daniel    761:                    break;
                    762:                case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.22      daniel    763:                    fprintf(output, "EXTERNAL UNPARSED, ");
1.9       daniel    764:                    break;
                    765:                case XML_INTERNAL_PARAMETER_ENTITY:
1.22      daniel    766:                    fprintf(output, "INTERNAL PARAMETER, ");
1.9       daniel    767:                    break;
                    768:                case XML_EXTERNAL_PARAMETER_ENTITY:
1.22      daniel    769:                    fprintf(output, "EXTERNAL PARAMETER, ");
1.9       daniel    770:                    break;
                    771:                default:
                    772:                    fprintf(output, "UNKNOWN TYPE %d",
1.19      daniel    773:                            cur->etype);
1.9       daniel    774:            }
                    775:            if (cur->ExternalID != NULL) 
                    776:                fprintf(output, "ID \"%s\"", cur->ExternalID);
                    777:            if (cur->SystemID != NULL)
                    778:                fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
                    779:            if (cur->orig != NULL)
                    780:                fprintf(output, "\n orig \"%s\"", cur->orig);
                    781:            if (cur->content != NULL)
                    782:                fprintf(output, "\n content \"%s\"", cur->content);
                    783:            fprintf(output, "\n");      
                    784:        }
                    785:     } else
                    786:        fprintf(output, "No entities in internal subset\n");
                    787:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    788:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
                    789:                                    doc->extSubset->entities;
                    790:        fprintf(output, "Entities in external subset\n");
                    791:        for (i = 0;i < table->nb_entities;i++) {
1.20      daniel    792:            cur = table->table[i];
1.9       daniel    793:            fprintf(output, "%d : %s : ", i, cur->name);
1.19      daniel    794:            switch (cur->etype) {
1.9       daniel    795:                case XML_INTERNAL_GENERAL_ENTITY:
1.22      daniel    796:                    fprintf(output, "INTERNAL GENERAL, ");
1.9       daniel    797:                    break;
                    798:                case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1.22      daniel    799:                    fprintf(output, "EXTERNAL PARSED, ");
1.9       daniel    800:                    break;
                    801:                case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.22      daniel    802:                    fprintf(output, "EXTERNAL UNPARSED, ");
1.9       daniel    803:                    break;
                    804:                case XML_INTERNAL_PARAMETER_ENTITY:
1.22      daniel    805:                    fprintf(output, "INTERNAL PARAMETER, ");
1.9       daniel    806:                    break;
                    807:                case XML_EXTERNAL_PARAMETER_ENTITY:
1.22      daniel    808:                    fprintf(output, "EXTERNAL PARAMETER, ");
1.9       daniel    809:                    break;
                    810:                default:
                    811:                    fprintf(output, "UNKNOWN TYPE %d",
1.19      daniel    812:                            cur->etype);
1.9       daniel    813:            }
                    814:            if (cur->ExternalID != NULL) 
                    815:                fprintf(output, "ID \"%s\"", cur->ExternalID);
                    816:            if (cur->SystemID != NULL)
                    817:                fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
                    818:            if (cur->orig != NULL)
                    819:                fprintf(output, "\n orig \"%s\"", cur->orig);
                    820:            if (cur->content != NULL)
                    821:                fprintf(output, "\n content \"%s\"", cur->content);
                    822:            fprintf(output, "\n");      
                    823:        }
                    824:     } else
                    825:        fprintf(output, "No entities in external subset\n");
                    826: }
1.12      daniel    827: 
                    828: static int xmlLsCountNode(xmlNodePtr node) {
                    829:     int ret = 0;
                    830:     xmlNodePtr list = NULL;
                    831: 
                    832:     switch (node->type) {
                    833:        case XML_ELEMENT_NODE:
1.16      daniel    834:            list = node->children;
1.12      daniel    835:            break;
                    836:        case XML_DOCUMENT_NODE:
                    837:        case XML_HTML_DOCUMENT_NODE:
1.16      daniel    838:            list = ((xmlDocPtr) node)->children;
1.12      daniel    839:            break;
                    840:        case XML_ATTRIBUTE_NODE:
1.16      daniel    841:            list = ((xmlAttrPtr) node)->children;
1.12      daniel    842:            break;
                    843:        case XML_TEXT_NODE:
                    844:        case XML_CDATA_SECTION_NODE:
                    845:        case XML_PI_NODE:
                    846:        case XML_COMMENT_NODE:
                    847:            if (node->content != NULL) {
                    848: #ifndef XML_USE_BUFFER_CONTENT     
                    849:                ret = xmlStrlen(node->content);
                    850: #else
                    851:                ret = xmlBufferLength(node->content);
                    852: #endif
                    853:             }
                    854:            break;
                    855:        case XML_ENTITY_REF_NODE:
                    856:        case XML_DOCUMENT_TYPE_NODE:
                    857:        case XML_ENTITY_NODE:
                    858:        case XML_DOCUMENT_FRAG_NODE:
                    859:        case XML_NOTATION_NODE:
1.16      daniel    860:        case XML_DTD_NODE:
1.17      daniel    861:         case XML_ELEMENT_DECL:
                    862:         case XML_ATTRIBUTE_DECL:
1.20      daniel    863:         case XML_ENTITY_DECL:
1.12      daniel    864:            ret = 1;
                    865:            break;
                    866:     }
                    867:     for (;list != NULL;ret++) 
                    868:         list = list->next;
                    869:     return(ret);
                    870: }
                    871: 
                    872: void xmlLsOneNode(FILE *output, xmlNodePtr node) {
                    873:     switch (node->type) {
                    874:        case XML_ELEMENT_NODE:
                    875:            fprintf(output, "-");
                    876:            break;
                    877:        case XML_ATTRIBUTE_NODE:
                    878:            fprintf(output, "a");
                    879:            break;
                    880:        case XML_TEXT_NODE:
                    881:            fprintf(output, "t");
                    882:            break;
                    883:        case XML_CDATA_SECTION_NODE:
                    884:            fprintf(output, "c");
                    885:            break;
                    886:        case XML_ENTITY_REF_NODE:
                    887:            fprintf(output, "e");
                    888:            break;
                    889:        case XML_ENTITY_NODE:
                    890:            fprintf(output, "E");
                    891:            break;
                    892:        case XML_PI_NODE:
                    893:            fprintf(output, "p");
                    894:            break;
                    895:        case XML_COMMENT_NODE:
                    896:            fprintf(output, "c");
                    897:            break;
                    898:        case XML_DOCUMENT_NODE:
                    899:            fprintf(output, "d");
                    900:            break;
                    901:        case XML_HTML_DOCUMENT_NODE:
                    902:            fprintf(output, "h");
                    903:            break;
                    904:        case XML_DOCUMENT_TYPE_NODE:
                    905:            fprintf(output, "T");
                    906:            break;
                    907:        case XML_DOCUMENT_FRAG_NODE:
                    908:            fprintf(output, "F");
                    909:            break;
                    910:        case XML_NOTATION_NODE:
                    911:            fprintf(output, "N");
                    912:            break;
                    913:        default:
                    914:            fprintf(output, "?");
                    915:     }
                    916:     if (node->properties != NULL)
                    917:        fprintf(output, "a");
                    918:     else       
                    919:        fprintf(output, "-");
                    920:     if (node->nsDef != NULL) 
                    921:        fprintf(output, "n");
                    922:     else       
                    923:        fprintf(output, "-");
                    924: 
                    925:     fprintf(output, " %8d ", xmlLsCountNode(node));
                    926: 
                    927:     switch (node->type) {
                    928:        case XML_ELEMENT_NODE:
                    929:            if (node->name != NULL)
                    930:                fprintf(output, "%s", node->name);
                    931:            break;
                    932:        case XML_ATTRIBUTE_NODE:
                    933:            if (node->name != NULL)
                    934:                fprintf(output, "%s", node->name);
                    935:            break;
                    936:        case XML_TEXT_NODE:
                    937:            if (node->content != NULL) {
                    938: #ifndef XML_USE_BUFFER_CONTENT     
                    939:                xmlDebugDumpString(output, node->content);
                    940: #else
                    941:                xmlDebugDumpString(output, xmlBufferContent(node->content));
                    942: #endif
                    943:             }
                    944:            break;
                    945:        case XML_CDATA_SECTION_NODE:
                    946:            break;
                    947:        case XML_ENTITY_REF_NODE:
                    948:            if (node->name != NULL)
                    949:                fprintf(output, "%s", node->name);
                    950:            break;
                    951:        case XML_ENTITY_NODE:
                    952:            if (node->name != NULL)
                    953:                fprintf(output, "%s", node->name);
                    954:            break;
                    955:        case XML_PI_NODE:
                    956:            if (node->name != NULL)
                    957:                fprintf(output, "%s", node->name);
                    958:            break;
                    959:        case XML_COMMENT_NODE:
                    960:            break;
                    961:        case XML_DOCUMENT_NODE:
                    962:            break;
                    963:        case XML_HTML_DOCUMENT_NODE:
                    964:            break;
                    965:        case XML_DOCUMENT_TYPE_NODE:
                    966:            break;
                    967:        case XML_DOCUMENT_FRAG_NODE:
                    968:            break;
                    969:        case XML_NOTATION_NODE:
                    970:            break;
                    971:        default:
                    972:            if (node->name != NULL)
                    973:                fprintf(output, "%s", node->name);
                    974:     }
                    975:     fprintf(output, "\n");
                    976: }
                    977: 
                    978: /****************************************************************
                    979:  *                                                             *
                    980:  *             The XML shell related functions                 *
                    981:  *                                                             *
                    982:  ****************************************************************/
                    983: 
                    984: /*
                    985:  * TODO: Improvement/cleanups for the XML shell
                    986:  *     - allow to shell out an editor on a subpart
                    987:  *     - cleanup function registrations (with help) and calling
                    988:  *     - provide registration routines
                    989:  */
                    990: 
                    991: /**
                    992:  * xmlShellList:
                    993:  * @ctxt:  the shell context
                    994:  * @arg:  unused
                    995:  * @node:  a node
                    996:  * @node2:  unused
                    997:  *
                    998:  * Implements the XML shell function "ls"
                    999:  * Does an Unix like listing of the given node (like a directory)
                   1000:  *
                   1001:  * Returns 0
                   1002:  */
                   1003: int
                   1004: xmlShellList(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                   1005:                   xmlNodePtr node2) {
                   1006:     xmlNodePtr cur;
                   1007: 
                   1008:     if ((node->type == XML_DOCUMENT_NODE) ||
                   1009:         (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16      daniel   1010:         cur = ((xmlDocPtr) node)->children;
                   1011:     } else if (node->children != NULL) {
                   1012:         cur = node->children;
1.12      daniel   1013:     } else {
                   1014:        xmlLsOneNode(stdout, node);
                   1015:         return(0);
                   1016:     }
                   1017:     while (cur != NULL) {
                   1018:        xmlLsOneNode(stdout, cur);
                   1019:        cur = cur->next;
                   1020:     }
                   1021:     return(0);
                   1022: }
                   1023: 
                   1024: /**
                   1025:  * xmlShellDir:
                   1026:  * @ctxt:  the shell context
                   1027:  * @arg:  unused
                   1028:  * @node:  a node
                   1029:  * @node2:  unused
                   1030:  *
                   1031:  * Implements the XML shell function "dir"
                   1032:  * dumps informations about the node (namespace, attributes, content).
                   1033:  *
                   1034:  * Returns 0
                   1035:  */
                   1036: int
                   1037: xmlShellDir(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                   1038:                   xmlNodePtr node2) {
                   1039:     if ((node->type == XML_DOCUMENT_NODE) ||
                   1040:         (node->type == XML_HTML_DOCUMENT_NODE)) {
                   1041:        xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
                   1042:     } else if (node->type == XML_ATTRIBUTE_NODE) {
                   1043:        xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
                   1044:     } else {
                   1045:        xmlDebugDumpOneNode(stdout, node, 0);
                   1046:     }
                   1047:     return(0);
                   1048: }
                   1049: 
                   1050: /**
                   1051:  * xmlShellCat:
                   1052:  * @ctxt:  the shell context
                   1053:  * @arg:  unused
                   1054:  * @node:  a node
                   1055:  * @node2:  unused
                   1056:  *
                   1057:  * Implements the XML shell function "cat"
                   1058:  * dumps the serialization node content (XML or HTML).
                   1059:  *
                   1060:  * Returns 0
                   1061:  */
                   1062: int
                   1063: xmlShellCat(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                   1064:                   xmlNodePtr node2) {
1.13      daniel   1065:     if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1.23      daniel   1066: #ifdef LIBXML_HTML_ENABLED
1.13      daniel   1067:        if (node->type == XML_HTML_DOCUMENT_NODE)
                   1068:            htmlDocDump(stdout, (htmlDocPtr) node);
                   1069:        else
1.14      daniel   1070:            htmlNodeDumpFile(stdout, ctxt->doc, node);
1.23      daniel   1071: #else
                   1072:        if (node->type == XML_DOCUMENT_NODE)
                   1073:            xmlDocDump(stdout, (xmlDocPtr) node);
                   1074:        else
                   1075:            xmlElemDump(stdout, ctxt->doc, node);
                   1076: #endif /* LIBXML_HTML_ENABLED */
1.13      daniel   1077:     } else {
                   1078:        if (node->type == XML_DOCUMENT_NODE)
                   1079:            xmlDocDump(stdout, (xmlDocPtr) node);
                   1080:        else
                   1081:            xmlElemDump(stdout, ctxt->doc, node);
                   1082:     }
1.12      daniel   1083:     printf("\n");
                   1084:     return(0);
                   1085: }
                   1086: 
                   1087: /**
                   1088:  * xmlShellLoad:
                   1089:  * @ctxt:  the shell context
                   1090:  * @filename:  the file name
                   1091:  * @node:  unused
                   1092:  * @node2:  unused
                   1093:  *
                   1094:  * Implements the XML shell function "load"
                   1095:  * loads a new document specified by the filename
                   1096:  *
                   1097:  * Returns 0 or -1 if loading failed
                   1098:  */
                   1099: int
                   1100: xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   1101:              xmlNodePtr node2) {
                   1102:     xmlDocPtr doc;
                   1103:     int html = 0;
                   1104: 
                   1105:     if (ctxt->doc != NULL)
                   1106:        html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
                   1107: 
                   1108:     if (html) {
1.23      daniel   1109: #ifdef LIBXML_HTML_ENABLED
1.12      daniel   1110:        doc = htmlParseFile(filename, NULL);
1.23      daniel   1111: #else  
                   1112:        printf("HTML support not compiled in\n");
                   1113:        doc = NULL;
                   1114: #endif /* LIBXML_HTML_ENABLED */
1.12      daniel   1115:     } else {
                   1116:        doc = xmlParseFile(filename);
                   1117:     }
                   1118:     if (doc != NULL) {
                   1119:         if (ctxt->loaded == 1) {
                   1120:            xmlFreeDoc(ctxt->doc);
                   1121:        }
                   1122:        ctxt->loaded = 1;
1.23      daniel   1123: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1124:        xmlXPathFreeContext(ctxt->pctxt);
1.23      daniel   1125: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1126:        xmlFree(ctxt->filename);
                   1127:        ctxt->doc = doc;
                   1128:        ctxt->node = (xmlNodePtr) doc;   
1.23      daniel   1129: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1130:        ctxt->pctxt = xmlXPathNewContext(doc);
1.23      daniel   1131: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1132:        ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
                   1133:     } else
                   1134:         return(-1);
                   1135:     return(0);
                   1136: }
                   1137: 
                   1138: /**
                   1139:  * xmlShellWrite:
                   1140:  * @ctxt:  the shell context
                   1141:  * @filename:  the file name
                   1142:  * @node:  a node in the tree
                   1143:  * @node2:  unused
                   1144:  *
                   1145:  * Implements the XML shell function "write"
                   1146:  * Write the current node to the filename, it saves the serailization
                   1147:  * of the subtree under the @node specified
                   1148:  *
                   1149:  * Returns 0 or -1 in case of error
                   1150:  */
                   1151: int
                   1152: xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   1153:                   xmlNodePtr node2) {
                   1154:     if (node == NULL)
                   1155:         return(-1);
                   1156:     if ((filename == NULL) || (filename[0] == 0)) {
                   1157:         fprintf(stderr, "Write command requires a filename argument\n");
                   1158:        return(-1);
                   1159:     }
                   1160: #ifdef W_OK
                   1161:     if (access((char *) filename, W_OK)) {
                   1162:         fprintf(stderr, "Cannot write to %s\n", filename);
                   1163:        return(-1);
                   1164:     }
                   1165: #endif    
                   1166:     switch(node->type) {
                   1167:         case XML_DOCUMENT_NODE:
                   1168:            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
                   1169:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1170:                return(-1);
                   1171:            }
                   1172:            break;
                   1173:         case XML_HTML_DOCUMENT_NODE:
1.23      daniel   1174: #ifdef LIBXML_HTML_ENABLED
1.12      daniel   1175:            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1176:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1177:                return(-1);
                   1178:            }
1.23      daniel   1179: #else
                   1180:            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
                   1181:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1182:                return(-1);
                   1183:            }
                   1184: #endif /* LIBXML_HTML_ENABLED */
1.12      daniel   1185:            break;
                   1186:        default: {
                   1187:            FILE *f;
                   1188: 
                   1189:            f = fopen((char *) filename, "w");
                   1190:            if (f == NULL) {
                   1191:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1192:                return(-1);
                   1193:            }
                   1194:            xmlElemDump(f, ctxt->doc, node);
                   1195:            fclose(f);
                   1196:        }
                   1197:     }
                   1198:     return(0);
                   1199: }
                   1200: 
                   1201: /**
                   1202:  * xmlShellSave:
                   1203:  * @ctxt:  the shell context
                   1204:  * @filename:  the file name (optionnal)
                   1205:  * @node:  unused
                   1206:  * @node2:  unused
                   1207:  *
                   1208:  * Implements the XML shell function "save"
                   1209:  * Write the current document to the filename, or it's original name
                   1210:  *
                   1211:  * Returns 0 or -1 in case of error
                   1212:  */
                   1213: int 
                   1214: xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   1215:              xmlNodePtr node2) {
                   1216:     if (ctxt->doc == NULL)
                   1217:        return(-1);
                   1218:     if ((filename == NULL) || (filename[0] == 0))
                   1219:         filename = ctxt->filename;
                   1220: #ifdef W_OK
                   1221:     if (access((char *) filename, W_OK)) {
                   1222:         fprintf(stderr, "Cannot save to %s\n", filename);
                   1223:        return(-1);
                   1224:     }
                   1225: #endif
                   1226:     switch(ctxt->doc->type) {
                   1227:         case XML_DOCUMENT_NODE:
                   1228:            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1229:                fprintf(stderr, "Failed to save to %s\n", filename);
                   1230:            }
                   1231:            break;
                   1232:         case XML_HTML_DOCUMENT_NODE:
1.23      daniel   1233: #ifdef LIBXML_HTML_ENABLED
1.12      daniel   1234:            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1235:                fprintf(stderr, "Failed to save to %s\n", filename);
                   1236:            }
1.23      daniel   1237: #else
                   1238:            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1239:                fprintf(stderr, "Failed to save to %s\n", filename);
                   1240:            }
                   1241: #endif /* LIBXML_HTML_ENABLED */
1.12      daniel   1242:            break;
                   1243:        default:
                   1244:            fprintf(stderr, 
                   1245:              "To save to subparts of a document use the 'write' command\n");
                   1246:            return(-1);
                   1247:            
                   1248:     }
                   1249:     return(0);
                   1250: }
                   1251: 
                   1252: /**
                   1253:  * xmlShellValidate:
                   1254:  * @ctxt:  the shell context
                   1255:  * @dtd:  the DTD URI (optionnal)
                   1256:  * @node:  unused
                   1257:  * @node2:  unused
                   1258:  *
                   1259:  * Implements the XML shell function "validate"
                   1260:  * Validate the document, if a DTD path is provided, then the validation
                   1261:  * is done against the given DTD.
                   1262:  *
                   1263:  * Returns 0 or -1 in case of error
                   1264:  */
                   1265: int 
                   1266: xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node,
                   1267:                  xmlNodePtr node2) {
                   1268:     xmlValidCtxt vctxt;
                   1269:     int res = -1;
                   1270: 
                   1271:     vctxt.userData = stderr;
                   1272:     vctxt.error = (xmlValidityErrorFunc) fprintf;
                   1273:     vctxt.warning = (xmlValidityWarningFunc) fprintf;
                   1274: 
                   1275:     if ((dtd == NULL) || (dtd[0] == 0)) {
                   1276:         res = xmlValidateDocument(&vctxt, ctxt->doc);
                   1277:     } else {
                   1278:         xmlDtdPtr subset;
                   1279: 
                   1280:        subset = xmlParseDTD(NULL, (xmlChar *) dtd);
                   1281:        if (subset != NULL) {
                   1282:             res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
                   1283: 
                   1284:            xmlFreeDtd(subset);
                   1285:        }
                   1286:     }
                   1287:     return(res);
                   1288: }
                   1289: 
                   1290: /**
                   1291:  * xmlShellDu:
                   1292:  * @ctxt:  the shell context
                   1293:  * @arg:  unused
                   1294:  * @tree:  a node defining a subtree
                   1295:  * @node2:  unused
                   1296:  *
                   1297:  * Implements the XML shell function "du"
                   1298:  * show the structure of the subtree under node @tree
                   1299:  * If @tree is null, the command works on the current node.
                   1300:  *
                   1301:  * Returns 0 or -1 in case of error
                   1302:  */
                   1303: int 
                   1304: xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
                   1305:                   xmlNodePtr node2) {
                   1306:     xmlNodePtr node;
                   1307:     int indent = 0,i;
                   1308: 
                   1309:     if (tree == NULL) return(-1);
                   1310:     node = tree;
                   1311:     while (node != NULL) {
                   1312:         if ((node->type == XML_DOCUMENT_NODE) ||
                   1313:             (node->type == XML_HTML_DOCUMENT_NODE)) {
                   1314:            printf("/\n");
                   1315:        } else if (node->type == XML_ELEMENT_NODE) {
                   1316:            for (i = 0;i < indent;i++)
                   1317:                printf("  ");
                   1318:            printf("%s\n", node->name);
                   1319:        } else {
                   1320:        }
                   1321: 
                   1322:        /*
                   1323:         * Browse the full subtree, deep first
                   1324:         */
                   1325: 
                   1326:         if ((node->type == XML_DOCUMENT_NODE) ||
                   1327:             (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16      daniel   1328:            node = ((xmlDocPtr) node)->children;
1.25    ! daniel   1329:         } else if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1.12      daniel   1330:            /* deep first */
1.16      daniel   1331:            node = node->children;
1.12      daniel   1332:            indent++;
                   1333:        } else if ((node != tree) && (node->next != NULL)) {
                   1334:            /* then siblings */
                   1335:            node = node->next;
                   1336:        } else if (node != tree) {
                   1337:            /* go up to parents->next if needed */
                   1338:            while (node != tree) {
                   1339:                if (node->parent != NULL) {
                   1340:                    node = node->parent;
                   1341:                    indent--;
                   1342:                }
                   1343:                if ((node != tree) && (node->next != NULL)) {
                   1344:                    node = node->next;
                   1345:                    break;
                   1346:                }
                   1347:                if (node->parent == NULL) {
                   1348:                    node = NULL;
                   1349:                    break;
                   1350:                }
                   1351:                if (node == tree) {
                   1352:                    node = NULL;
                   1353:                    break;
                   1354:                }
                   1355:            }
                   1356:            /* exit condition */
                   1357:            if (node == tree) 
                   1358:                node = NULL;
                   1359:        } else
                   1360:            node = NULL;
                   1361:     }
                   1362:     return(0);
                   1363: }
                   1364: 
                   1365: /**
                   1366:  * xmlShellPwd:
                   1367:  * @ctxt:  the shell context
                   1368:  * @buffer:  the output buffer
                   1369:  * @tree:  a node 
                   1370:  * @node2:  unused
                   1371:  *
                   1372:  * Implements the XML shell function "pwd"
                   1373:  * Show the full path from the root to the node, if needed building
                   1374:  * thumblers when similar elements exists at a given ancestor level.
                   1375:  * The output is compatible with XPath commands.
                   1376:  *
                   1377:  * Returns 0 or -1 in case of error
                   1378:  */
                   1379: int 
                   1380: xmlShellPwd(xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node,
                   1381:                   xmlNodePtr node2) {
                   1382:     xmlNodePtr cur, tmp, next;
                   1383:     char buf[500];
                   1384:     char sep;
                   1385:     const char *name;
                   1386:     int occur = 0;
                   1387: 
                   1388:     buffer[0] = 0;
                   1389:     if (node == NULL) return(-1);
                   1390:     cur = node;
                   1391:     do {
                   1392:        name = "";
                   1393:        sep= '?';
                   1394:        occur = 0;
                   1395:        if ((cur->type == XML_DOCUMENT_NODE) ||
                   1396:            (cur->type == XML_HTML_DOCUMENT_NODE)) {
                   1397:            sep = '/';
                   1398:            next = NULL;
                   1399:        } else if (cur->type == XML_ELEMENT_NODE) {
                   1400:            sep = '/';
                   1401:            name = (const char *)cur->name;
                   1402:            next = cur->parent;
                   1403: 
                   1404:            /*
                   1405:             * Thumbler index computation
                   1406:             */
                   1407:            tmp = cur->prev;
                   1408:             while (tmp != NULL) {
                   1409:                if (!xmlStrcmp(cur->name, tmp->name))
                   1410:                    occur++;
                   1411:                tmp = tmp->prev;
                   1412:            }
                   1413:            if (occur == 0) {
                   1414:                tmp = cur->next;
                   1415:                while (tmp != NULL) {
                   1416:                    if (!xmlStrcmp(cur->name, tmp->name))
                   1417:                        occur++;
                   1418:                    tmp = tmp->next;
                   1419:                }
                   1420:                if (occur != 0) occur = 1;
                   1421:            } else
                   1422:                occur++;
                   1423:        } else if (cur->type == XML_ATTRIBUTE_NODE) {
                   1424:            sep = '@';
                   1425:            name = (const char *) (((xmlAttrPtr) cur)->name);
1.16      daniel   1426:            next = ((xmlAttrPtr) cur)->parent;
1.12      daniel   1427:        } else {
                   1428:            next = cur->parent;
                   1429:        }
                   1430:        if (occur == 0)
                   1431:            sprintf(buf, "%c%s%s", sep, name, buffer);
                   1432:        else
                   1433:            sprintf(buf, "%c%s[%d]%s", sep, name, occur, buffer);
                   1434:        strcpy(buffer, buf);
                   1435:         cur = next;
                   1436:     } while (cur != NULL);
                   1437:     return(0);
                   1438: }
                   1439: 
                   1440: /**
                   1441:  * xmlShell
                   1442:  * @doc:  the initial document
                   1443:  * @filename:  the output buffer
                   1444:  * @input:  the line reading function
                   1445:  * @output:  the output FILE*
                   1446:  *
                   1447:  * Implements the XML shell 
                   1448:  * This allow to load, validate, view, modify and save a document
                   1449:  * using a environment similar to a UNIX commandline.
                   1450:  */
                   1451: void
                   1452: xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                   1453:          FILE *output) {
                   1454:     char prompt[500] = "/ > ";
                   1455:     char *cmdline = NULL;
                   1456:     int nbargs;
                   1457:     char command[100];
                   1458:     char arg[400];
                   1459:     xmlShellCtxtPtr ctxt;
                   1460:     xmlXPathObjectPtr list;
                   1461: 
                   1462:     if (doc == NULL)
                   1463:         return;
                   1464:     if (filename == NULL)
                   1465:         return;
                   1466:     if (input == NULL)
                   1467:         return;
                   1468:     if (output == NULL)
                   1469:         return;
                   1470:     ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
                   1471:     if (ctxt == NULL) 
                   1472:         return;
                   1473:     ctxt->loaded = 0;
                   1474:     ctxt->doc = doc;
                   1475:     ctxt->input = input;
                   1476:     ctxt->output = output;
                   1477:     ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
                   1478:     ctxt->node = (xmlNodePtr) ctxt->doc;        
                   1479: 
1.23      daniel   1480: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1481:     ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
                   1482:     if (ctxt->pctxt == NULL) {
                   1483:        xmlFree(ctxt);
                   1484:        return;
                   1485:     }
1.23      daniel   1486: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1487:     while (1) {
                   1488:         if (ctxt->node == (xmlNodePtr) ctxt->doc)
                   1489:            sprintf(prompt, "%s > ", "/");
                   1490:        else if (ctxt->node->name)
                   1491:            sprintf(prompt, "%s > ", ctxt->node->name);
                   1492:        else
                   1493:            sprintf(prompt, "? > ");
                   1494: 
                   1495:         cmdline = ctxt->input(prompt);
                   1496:         if (cmdline == NULL) break;
                   1497: 
                   1498:        command[0] = 0;
                   1499:        arg[0] = 0;
                   1500:        nbargs = sscanf(cmdline, "%s %s", command, arg);
                   1501: 
                   1502:        if (command[0] == 0) continue;
                   1503:         if (!strcmp(command, "exit"))
                   1504:            break;
                   1505:         if (!strcmp(command, "quit"))
                   1506:            break;
                   1507:         if (!strcmp(command, "bye"))
                   1508:            break;
                   1509:        if (!strcmp(command, "validate")) {
                   1510:            xmlShellValidate(ctxt, arg, NULL, NULL);
                   1511:        } else if (!strcmp(command, "load")) {
                   1512:            xmlShellLoad(ctxt, arg, NULL, NULL);
                   1513:        } else if (!strcmp(command, "save")) {
                   1514:            xmlShellSave(ctxt, arg, NULL, NULL);
                   1515:        } else if (!strcmp(command, "write")) {
                   1516:            xmlShellWrite(ctxt, arg, NULL, NULL);
                   1517:        } else if (!strcmp(command, "free")) {
                   1518:            if (arg[0] == 0) {
                   1519:                xmlMemShow(stdout, 0);
                   1520:            } else {
                   1521:                int len = 0;
                   1522:                sscanf(arg, "%d", &len);
                   1523:                xmlMemShow(stdout, len);
                   1524:            }
                   1525:        } else if (!strcmp(command, "pwd")) {
                   1526:            char dir[500];
                   1527:            if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
                   1528:                printf("%s\n", dir);
                   1529:        } else  if (!strcmp(command, "du")) {
                   1530:            xmlShellDu(ctxt, NULL, ctxt->node, NULL);
                   1531:        } else  if ((!strcmp(command, "ls")) ||
                   1532:              (!strcmp(command, "dir"))) {
                   1533:            int dir = (!strcmp(command, "dir"));
                   1534:            if (arg[0] == 0) {
                   1535:                if (dir)
                   1536:                    xmlShellDir(ctxt, NULL, ctxt->node, NULL);
                   1537:                else
                   1538:                    xmlShellList(ctxt, NULL, ctxt->node, NULL);
                   1539:            } else {
                   1540:                ctxt->pctxt->node = ctxt->node;
1.23      daniel   1541: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1542:                if (ctxt->pctxt->nodelist != NULL)
                   1543:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1544:                ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
                   1545:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23      daniel   1546: #else
                   1547:                list = NULL;
                   1548: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1549:                if (list != NULL) {
                   1550:                    switch (list->type) {
                   1551:                        case XPATH_UNDEFINED:
                   1552:                            fprintf(stderr, "%s: no such node\n", arg);
                   1553:                            break;
                   1554:                        case XPATH_NODESET: {
                   1555:                            int i;
                   1556: 
                   1557:                            for (i = 0;i < list->nodesetval->nodeNr;i++) {
                   1558:                                if (dir)
                   1559:                                    xmlShellDir(ctxt, NULL,
                   1560:                                       list->nodesetval->nodeTab[i], NULL);
                   1561:                                else
                   1562:                                    xmlShellList(ctxt, NULL,
                   1563:                                       list->nodesetval->nodeTab[i], NULL);
                   1564:                            }
                   1565:                            break;
                   1566:                        }
                   1567:                        case XPATH_BOOLEAN:
                   1568:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1569:                            break;
                   1570:                        case XPATH_NUMBER:
                   1571:                            fprintf(stderr, "%s is a number\n", arg);
                   1572:                            break;
                   1573:                        case XPATH_STRING:
                   1574:                            fprintf(stderr, "%s is a string\n", arg);
                   1575:                            break;
                   1576:                    }
                   1577:                    xmlXPathFreeNodeSetList(list);
                   1578:                } else {
                   1579:                    fprintf(stderr, "%s: no such node\n", arg);
                   1580:                }
1.23      daniel   1581: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1582:                if (ctxt->pctxt->nodelist != NULL)
                   1583:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1.23      daniel   1584: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1585:                ctxt->pctxt->nodelist = NULL;
                   1586:            }
                   1587:        } else if (!strcmp(command, "cd")) {
                   1588:            if (arg[0] == 0) {
                   1589:                ctxt->node = (xmlNodePtr) ctxt->doc;
                   1590:            } else {
                   1591:                ctxt->pctxt->node = ctxt->node;
1.23      daniel   1592: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1593:                if (ctxt->pctxt->nodelist != NULL)
                   1594:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1595:                ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
                   1596:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23      daniel   1597: #else
                   1598:                list = NULL;
                   1599: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1600:                if (list != NULL) {
                   1601:                    switch (list->type) {
                   1602:                        case XPATH_UNDEFINED:
                   1603:                            fprintf(stderr, "%s: no such node\n", arg);
                   1604:                            break;
                   1605:                        case XPATH_NODESET:
                   1606:                            if (list->nodesetval->nodeNr == 1) {
                   1607:                                ctxt->node = list->nodesetval->nodeTab[0];
                   1608:                            } else 
                   1609:                                fprintf(stderr, "%s is a %d Node Set\n",
                   1610:                                        arg, list->nodesetval->nodeNr);
                   1611:                            break;
                   1612:                        case XPATH_BOOLEAN:
                   1613:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1614:                            break;
                   1615:                        case XPATH_NUMBER:
                   1616:                            fprintf(stderr, "%s is a number\n", arg);
                   1617:                            break;
                   1618:                        case XPATH_STRING:
                   1619:                            fprintf(stderr, "%s is a string\n", arg);
                   1620:                            break;
                   1621:                    }
                   1622:                    xmlXPathFreeNodeSetList(list);
                   1623:                } else {
                   1624:                    fprintf(stderr, "%s: no such node\n", arg);
                   1625:                }
1.23      daniel   1626: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1627:                if (ctxt->pctxt->nodelist != NULL)
                   1628:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1.23      daniel   1629: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1630:                ctxt->pctxt->nodelist = NULL;
                   1631:            }
                   1632:        } else if (!strcmp(command, "cat")) {
                   1633:            if (arg[0] == 0) {
                   1634:                xmlShellCat(ctxt, NULL, ctxt->node, NULL);
                   1635:            } else {
                   1636:                ctxt->pctxt->node = ctxt->node;
1.23      daniel   1637: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1638:                if (ctxt->pctxt->nodelist != NULL)
                   1639:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
                   1640:                ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
                   1641:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23      daniel   1642: #else
                   1643:                list = NULL;
                   1644: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1645:                if (list != NULL) {
                   1646:                    switch (list->type) {
                   1647:                        case XPATH_UNDEFINED:
                   1648:                            fprintf(stderr, "%s: no such node\n", arg);
                   1649:                            break;
                   1650:                        case XPATH_NODESET: {
                   1651:                            int i;
                   1652: 
                   1653:                            for (i = 0;i < list->nodesetval->nodeNr;i++) {
                   1654:                                if (i > 0) printf(" -------\n");
                   1655:                                xmlShellCat(ctxt, NULL,
                   1656:                                    list->nodesetval->nodeTab[i], NULL);
                   1657:                            }
                   1658:                            break;
                   1659:                        }
                   1660:                        case XPATH_BOOLEAN:
                   1661:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1662:                            break;
                   1663:                        case XPATH_NUMBER:
                   1664:                            fprintf(stderr, "%s is a number\n", arg);
                   1665:                            break;
                   1666:                        case XPATH_STRING:
                   1667:                            fprintf(stderr, "%s is a string\n", arg);
                   1668:                            break;
                   1669:                    }
                   1670:                    xmlXPathFreeNodeSetList(list);
                   1671:                } else {
                   1672:                    fprintf(stderr, "%s: no such node\n", arg);
                   1673:                }
1.23      daniel   1674: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1675:                if (ctxt->pctxt->nodelist != NULL)
                   1676:                    xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
1.23      daniel   1677: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1678:                ctxt->pctxt->nodelist = NULL;
                   1679:            }
                   1680:        } else {
                   1681:            fprintf(stderr, "Unknown command %s\n", command);
                   1682:        }
                   1683:        free(cmdline); /* not xmlFree here ! */
                   1684:     }
1.23      daniel   1685: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1686:     xmlXPathFreeContext(ctxt->pctxt);
1.23      daniel   1687: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1688:     if (ctxt->loaded) {
                   1689:         xmlFreeDoc(ctxt->doc);
                   1690:     }
                   1691:     xmlFree(ctxt);
                   1692:     if (cmdline != NULL)
                   1693:         free(cmdline); /* not xmlFree here ! */
                   1694: }
                   1695: 
1.23      daniel   1696: #endif /* LIBXML_DEBUG_ENABLED */

Webmaster