Annotation of XML/debugXML.c, revision 1.20

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

Webmaster