Annotation of XML/valid.c, revision 1.20

1.1       daniel      1: /*
                      2:  * valid.c : part of the code use to do the DTD handling and the validity
                      3:  *           checking
                      4:  *
                      5:  * See Copyright for the status of this software.
                      6:  *
                      7:  * Daniel.Veillard@w3.org
                      8:  */
                      9: 
                     10: #include <stdio.h>
                     11: #include <stdlib.h>
                     12: #include <string.h>
                     13: #include "valid.h"
                     14: #include "parser.h"
1.16      daniel     15: #include "parserInternals.h"
                     16: 
                     17: #define VERROR                                                 \
                     18:    if ((ctxt != NULL) && (ctxt->error != NULL)) ctxt->error
                     19: 
                     20: #define VWARNING                                               \
                     21:    if ((ctxt != NULL) && (ctxt->warning != NULL)) ctxt->warning
                     22: 
                     23: #define CHECK_DTD                                              \
                     24:    if (doc == NULL) return(0);                                 \
                     25:    else if (doc->intSubset == NULL) return(0)
1.1       daniel     26: 
1.15      daniel     27: xmlElementPtr xmlGetDtdElementDesc(xmlDtdPtr dtd, const CHAR *name);
                     28: xmlAttributePtr xmlScanAttributeDecl(xmlDtdPtr dtd, const CHAR *elem);
                     29: 
1.1       daniel     30: /****************************************************************
                     31:  *                                                             *
                     32:  *     Util functions for data allocation/deallocation         *
                     33:  *                                                             *
                     34:  ****************************************************************/
                     35: 
                     36: /**
                     37:  * xmlNewElementContent:
                     38:  * @name:  the subelement name or NULL
                     39:  * @type:  the type of element content decl
                     40:  *
                     41:  * Allocate an element content structure.
                     42:  *
1.6       daniel     43:  * Returns NULL if not, othervise the new element content structure
1.1       daniel     44:  */
                     45: xmlElementContentPtr
                     46: xmlNewElementContent(CHAR *name, int type) {
1.2       daniel     47:     xmlElementContentPtr ret;
                     48: 
                     49:     switch(type) {
                     50:        case XML_ELEMENT_CONTENT_ELEMENT:
                     51:            if (name == NULL) {
                     52:                fprintf(stderr, "xmlNewElementContent : name == NULL !\n");
                     53:            }
                     54:            break;
                     55:         case XML_ELEMENT_CONTENT_PCDATA:
                     56:        case XML_ELEMENT_CONTENT_SEQ:
                     57:        case XML_ELEMENT_CONTENT_OR:
                     58:            if (name != NULL) {
                     59:                fprintf(stderr, "xmlNewElementContent : name != NULL !\n");
                     60:            }
                     61:            break;
                     62:        default:
                     63:            fprintf(stderr, "xmlNewElementContent: unknown type %d\n", type);
                     64:            exit(1);
                     65:     }
                     66:     ret = (xmlElementContentPtr) malloc(sizeof(xmlElementContent));
                     67:     if (ret == NULL) {
                     68:        fprintf(stderr, "xmlNewElementContent : out of memory!\n");
                     69:        return(NULL);
                     70:     }
                     71:     ret->type = type;
                     72:     ret->ocur = XML_ELEMENT_CONTENT_ONCE;
                     73:     if (name != NULL)
                     74:         ret->name = xmlStrdup(name);
                     75:     else
                     76:         ret->name = NULL;
1.4       daniel     77:     ret->c1 = ret->c2 = NULL;
1.2       daniel     78:     return(ret);
                     79: }
                     80: 
                     81: /**
                     82:  * xmlCopyElementContent:
                     83:  * @content:  An element content pointer.
                     84:  *
                     85:  * Build a copy of an element content description.
                     86:  * 
1.6       daniel     87:  * Returns the new xmlElementContentPtr or NULL in case of error.
1.2       daniel     88:  */
                     89: xmlElementContentPtr
1.4       daniel     90: xmlCopyElementContent(xmlElementContentPtr cur) {
                     91:     xmlElementContentPtr ret;
                     92: 
                     93:     if (cur == NULL) return(NULL);
                     94:     ret = xmlNewElementContent((CHAR *) cur->name, cur->type);
1.11      daniel     95:     if (ret == NULL) {
                     96:         fprintf(stderr, "xmlCopyElementContent : out of memory\n");
                     97:        return(NULL);
                     98:     }
                     99:     ret->ocur = cur->ocur;
                    100:     if (cur->c1 != NULL) ret->c1 = xmlCopyElementContent(cur->c1);
                    101:     if (cur->c2 != NULL) ret->c2 = xmlCopyElementContent(cur->c2);
1.4       daniel    102:     return(ret);
1.1       daniel    103: }
                    104: 
                    105: /**
1.3       daniel    106:  * xmlFreeElementContent:
                    107:  * @cur:  the element content tree to free
1.1       daniel    108:  *
                    109:  * Free an element content structure. This is a recursive call !
                    110:  */
                    111: void
                    112: xmlFreeElementContent(xmlElementContentPtr cur) {
1.4       daniel    113:     if (cur == NULL) return;
                    114:     if (cur->c1 != NULL) xmlFreeElementContent(cur->c1);
                    115:     if (cur->c2 != NULL) xmlFreeElementContent(cur->c2);
                    116:     if (cur->name != NULL) free((CHAR *) cur->name);
                    117:     memset(cur, -1, sizeof(xmlElementContent));
                    118:     free(cur);
1.1       daniel    119: }
                    120: 
1.3       daniel    121: /**
                    122:  * xmlDumpElementContent:
1.8       daniel    123:  * @buf:  An XML buffer
1.3       daniel    124:  * @content:  An element table
                    125:  * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
                    126:  *
                    127:  * This will dump the content of the element table as an XML DTD definition
                    128:  */
                    129: void
1.8       daniel    130: xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content, int glob) {
1.3       daniel    131:     if (content == NULL) return;
                    132: 
1.8       daniel    133:     if (glob) xmlBufferWriteChar(buf, "(");
1.3       daniel    134:     switch (content->type) {
                    135:         case XML_ELEMENT_CONTENT_PCDATA:
1.8       daniel    136:             xmlBufferWriteChar(buf, "#PCDATA");
1.3       daniel    137:            break;
                    138:        case XML_ELEMENT_CONTENT_ELEMENT:
1.8       daniel    139:            xmlBufferWriteCHAR(buf, content->name);
1.3       daniel    140:            break;
                    141:        case XML_ELEMENT_CONTENT_SEQ:
                    142:            if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
                    143:                (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1.8       daniel    144:                xmlDumpElementContent(buf, content->c1, 1);
1.3       daniel    145:            else
1.8       daniel    146:                xmlDumpElementContent(buf, content->c1, 0);
                    147:             xmlBufferWriteChar(buf, " , ");
1.3       daniel    148:            if (content->c2->type == XML_ELEMENT_CONTENT_OR)
1.8       daniel    149:                xmlDumpElementContent(buf, content->c2, 1);
1.3       daniel    150:            else
1.8       daniel    151:                xmlDumpElementContent(buf, content->c2, 0);
1.3       daniel    152:            break;
                    153:        case XML_ELEMENT_CONTENT_OR:
                    154:            if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
                    155:                (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
1.8       daniel    156:                xmlDumpElementContent(buf, content->c1, 1);
1.3       daniel    157:            else
1.8       daniel    158:                xmlDumpElementContent(buf, content->c1, 0);
                    159:             xmlBufferWriteChar(buf, " | ");
1.3       daniel    160:            if (content->c2->type == XML_ELEMENT_CONTENT_SEQ)
1.8       daniel    161:                xmlDumpElementContent(buf, content->c2, 1);
1.3       daniel    162:            else
1.8       daniel    163:                xmlDumpElementContent(buf, content->c2, 0);
1.3       daniel    164:            break;
                    165:        default:
                    166:            fprintf(stderr, "xmlDumpElementContent: unknown type %d\n",
                    167:                    content->type);
                    168:     }
                    169:     if (glob)
1.8       daniel    170:         xmlBufferWriteChar(buf, ")");
1.3       daniel    171:     switch (content->ocur) {
                    172:         case XML_ELEMENT_CONTENT_ONCE:
                    173:            break;
                    174:         case XML_ELEMENT_CONTENT_OPT:
1.8       daniel    175:            xmlBufferWriteChar(buf, "?");
1.3       daniel    176:            break;
                    177:         case XML_ELEMENT_CONTENT_MULT:
1.8       daniel    178:            xmlBufferWriteChar(buf, "*");
1.3       daniel    179:            break;
                    180:         case XML_ELEMENT_CONTENT_PLUS:
1.8       daniel    181:            xmlBufferWriteChar(buf, "+");
1.3       daniel    182:            break;
                    183:     }
                    184: }
                    185: 
1.19      daniel    186: /**
                    187:  * xmlSprintfElementContent:
                    188:  * @buf:  an output buffer
                    189:  * @content:  An element table
                    190:  * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
                    191:  *
                    192:  * This will dump the content of the element content definition
                    193:  * Intended just for the debug routine
                    194:  */
                    195: void
                    196: xmlSprintfElementContent(char *buf, xmlElementContentPtr content, int glob) {
                    197:     if (content == NULL) return;
                    198:     if (glob) strcat(buf, "(");
                    199:     switch (content->type) {
                    200:         case XML_ELEMENT_CONTENT_PCDATA:
                    201:             strcat(buf, "#PCDATA");
                    202:            break;
                    203:        case XML_ELEMENT_CONTENT_ELEMENT:
                    204:            strcat(buf, content->name);
                    205:            break;
                    206:        case XML_ELEMENT_CONTENT_SEQ:
                    207:            if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
                    208:                (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
                    209:                xmlSprintfElementContent(buf, content->c1, 1);
                    210:            else
                    211:                xmlSprintfElementContent(buf, content->c1, 0);
                    212:             strcat(buf, " , ");
                    213:            if (content->c2->type == XML_ELEMENT_CONTENT_OR)
                    214:                xmlSprintfElementContent(buf, content->c2, 1);
                    215:            else
                    216:                xmlSprintfElementContent(buf, content->c2, 0);
                    217:            break;
                    218:        case XML_ELEMENT_CONTENT_OR:
                    219:            if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
                    220:                (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
                    221:                xmlSprintfElementContent(buf, content->c1, 1);
                    222:            else
                    223:                xmlSprintfElementContent(buf, content->c1, 0);
                    224:             strcat(buf, " | ");
                    225:            if (content->c2->type == XML_ELEMENT_CONTENT_SEQ)
                    226:                xmlSprintfElementContent(buf, content->c2, 1);
                    227:            else
                    228:                xmlSprintfElementContent(buf, content->c2, 0);
                    229:            break;
                    230:     }
                    231:     if (glob)
                    232:         strcat(buf, ")");
                    233:     switch (content->ocur) {
                    234:         case XML_ELEMENT_CONTENT_ONCE:
                    235:            break;
                    236:         case XML_ELEMENT_CONTENT_OPT:
                    237:            strcat(buf, "?");
                    238:            break;
                    239:         case XML_ELEMENT_CONTENT_MULT:
                    240:            strcat(buf, "*");
                    241:            break;
                    242:         case XML_ELEMENT_CONTENT_PLUS:
                    243:            strcat(buf, "+");
                    244:            break;
                    245:     }
                    246: }
                    247: 
1.1       daniel    248: /****************************************************************
                    249:  *                                                             *
                    250:  *     Registration of DTD declarations                        *
                    251:  *                                                             *
                    252:  ****************************************************************/
                    253: 
1.2       daniel    254: /**
                    255:  * xmlCreateElementTable:
                    256:  *
                    257:  * create and initialize an empty element hash table.
                    258:  *
1.6       daniel    259:  * Returns the xmlElementTablePtr just created or NULL in case of error.
1.2       daniel    260:  */
                    261: xmlElementTablePtr
                    262: xmlCreateElementTable(void) {
                    263:     xmlElementTablePtr ret;
                    264: 
                    265:     ret = (xmlElementTablePtr) 
                    266:          malloc(sizeof(xmlElementTable));
                    267:     if (ret == NULL) {
1.12      daniel    268:         fprintf(stderr, "xmlCreateElementTable : malloc(%ld) failed\n",
                    269:                (long)sizeof(xmlElementTable));
1.2       daniel    270:         return(NULL);
                    271:     }
1.4       daniel    272:     ret->max_elements = XML_MIN_ELEMENT_TABLE;
1.2       daniel    273:     ret->nb_elements = 0;
1.15      daniel    274:     ret->table = (xmlElementPtr *) 
                    275:          malloc(ret->max_elements * sizeof(xmlElementPtr));
1.2       daniel    276:     if (ret == NULL) {
1.12      daniel    277:         fprintf(stderr, "xmlCreateElementTable : malloc(%ld) failed\n",
                    278:                ret->max_elements * (long)sizeof(xmlElement));
1.2       daniel    279:        free(ret);
                    280:         return(NULL);
                    281:     }
                    282:     return(ret);
                    283: }
                    284: 
1.1       daniel    285: 
                    286: /**
                    287:  * xmlAddElementDecl:
1.6       daniel    288:  * @dtd:  pointer to the DTD
1.1       daniel    289:  * @name:  the entity name
1.6       daniel    290:  * @type:  the element type
                    291:  * @content:  the element content tree or NULL
1.1       daniel    292:  *
                    293:  * Register a new element declaration
                    294:  *
1.6       daniel    295:  * Returns NULL if not, othervise the entity
1.1       daniel    296:  */
                    297: xmlElementPtr
1.16      daniel    298: xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const CHAR *name,
                    299:                   int type, xmlElementContentPtr content) {
1.2       daniel    300:     xmlElementPtr ret, cur;
                    301:     xmlElementTablePtr table;
                    302:     int i;
1.1       daniel    303: 
                    304:     if (dtd == NULL) {
                    305:         fprintf(stderr, "xmlAddElementDecl: dtd == NULL\n");
                    306:        return(NULL);
                    307:     }
                    308:     if (name == NULL) {
                    309:         fprintf(stderr, "xmlAddElementDecl: name == NULL\n");
                    310:        return(NULL);
                    311:     }
                    312:     switch (type) {
                    313:         case XML_ELEMENT_TYPE_EMPTY:
                    314:            if (content != NULL) {
                    315:                fprintf(stderr,
                    316:                        "xmlAddElementDecl: content != NULL for EMPTY\n");
                    317:                return(NULL);
                    318:            }
                    319:            break;
                    320:        case XML_ELEMENT_TYPE_ANY:
                    321:            if (content != NULL) {
                    322:                fprintf(stderr,
                    323:                        "xmlAddElementDecl: content != NULL for ANY\n");
                    324:                return(NULL);
                    325:            }
                    326:            break;
                    327:        case XML_ELEMENT_TYPE_MIXED:
                    328:            if (content == NULL) {
                    329:                fprintf(stderr,
                    330:                        "xmlAddElementDecl: content == NULL for MIXED\n");
                    331:                return(NULL);
                    332:            }
                    333:            break;
                    334:        case XML_ELEMENT_TYPE_ELEMENT:
                    335:            if (content == NULL) {
                    336:                fprintf(stderr,
                    337:                        "xmlAddElementDecl: content == NULL for ELEMENT\n");
                    338:                return(NULL);
                    339:            }
                    340:            break;
                    341:        default:
                    342:            fprintf(stderr, "xmlAddElementDecl: unknown type %d\n", type);
                    343:            return(NULL);
                    344:     }
                    345: 
                    346:     /*
1.2       daniel    347:      * Create the Element table if needed.
                    348:      */
                    349:     table = dtd->elements;
                    350:     if (table == NULL) 
                    351:         table = dtd->elements = xmlCreateElementTable();
                    352:     if (table == NULL) {
                    353:        fprintf(stderr, "xmlAddElementDecl: Table creation failed!\n");
                    354:         return(NULL);
                    355:     }
                    356: 
                    357:     /*
1.1       daniel    358:      * Validity Check:
                    359:      * Search the DTD for previous declarations of the ELEMENT
                    360:      */
1.2       daniel    361:     for (i = 0;i < table->nb_elements;i++) {
1.15      daniel    362:         cur = table->table[i];
1.2       daniel    363:        if (!xmlStrcmp(cur->name, name)) {
                    364:            /*
                    365:             * The element is already defined in this Dtd.
                    366:             */
1.16      daniel    367:            VERROR(ctxt->userData, "Redefinition of element %s\n", name);
1.2       daniel    368:            return(NULL);
                    369:        }
                    370:     }
1.1       daniel    371: 
                    372:     /*
1.2       daniel    373:      * Grow the table, if needed.
1.1       daniel    374:      */
1.2       daniel    375:     if (table->nb_elements >= table->max_elements) {
                    376:         /*
                    377:         * need more elements.
                    378:         */
                    379:        table->max_elements *= 2;
1.15      daniel    380:        table->table = (xmlElementPtr *) 
                    381:            realloc(table->table, table->max_elements * sizeof(xmlElementPtr));
1.13      daniel    382:        if (table->table == NULL) {
1.2       daniel    383:            fprintf(stderr, "xmlAddElementDecl: out of memory\n");
                    384:            return(NULL);
                    385:        }
1.1       daniel    386:     }
1.15      daniel    387:     ret = (xmlElementPtr) malloc(sizeof(xmlElement));
                    388:     if (ret == NULL) {
                    389:        fprintf(stderr, "xmlAddElementDecl: out of memory\n");
                    390:        return(NULL);
                    391:     }
                    392:     table->table[table->nb_elements] = ret;
1.2       daniel    393: 
                    394:     /*
                    395:      * fill the structure.
                    396:      */
1.1       daniel    397:     ret->type = type;
                    398:     ret->name = xmlStrdup(name);
1.11      daniel    399:     ret->content = xmlCopyElementContent(content);
1.15      daniel    400:     ret->attributes = xmlScanAttributeDecl(dtd, name);
1.2       daniel    401:     table->nb_elements++;
                    402: 
                    403:     return(ret);
                    404: }
                    405: 
                    406: /**
                    407:  * xmlFreeElement:
                    408:  * @elem:  An element
                    409:  *
                    410:  * Deallocate the memory used by an element definition
                    411:  */
                    412: void
                    413: xmlFreeElement(xmlElementPtr elem) {
                    414:     if (elem == NULL) return;
                    415:     xmlFreeElementContent(elem->content);
                    416:     if (elem->name != NULL)
                    417:        free((CHAR *) elem->name);
                    418:     memset(elem, -1, sizeof(xmlElement));
1.15      daniel    419:     free(elem);
1.2       daniel    420: }
1.1       daniel    421: 
1.2       daniel    422: /**
                    423:  * xmlFreeElementTable:
                    424:  * @table:  An element table
                    425:  *
1.4       daniel    426:  * Deallocate the memory used by an element hash table.
1.2       daniel    427:  */
                    428: void
                    429: xmlFreeElementTable(xmlElementTablePtr table) {
                    430:     int i;
                    431: 
                    432:     if (table == NULL) return;
                    433: 
                    434:     for (i = 0;i < table->nb_elements;i++) {
1.15      daniel    435:         xmlFreeElement(table->table[i]);
1.2       daniel    436:     }
                    437:     free(table->table);
                    438:     free(table);
                    439: }
                    440: 
                    441: /**
                    442:  * xmlCopyElementTable:
                    443:  * @table:  An element table
                    444:  *
                    445:  * Build a copy of an element table.
                    446:  * 
1.6       daniel    447:  * Returns the new xmlElementTablePtr or NULL in case of error.
1.2       daniel    448:  */
                    449: xmlElementTablePtr
                    450: xmlCopyElementTable(xmlElementTablePtr table) {
                    451:     xmlElementTablePtr ret;
                    452:     xmlElementPtr cur, ent;
                    453:     int i;
1.1       daniel    454: 
1.2       daniel    455:     ret = (xmlElementTablePtr) malloc(sizeof(xmlElementTable));
                    456:     if (ret == NULL) {
                    457:         fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
                    458:        return(NULL);
                    459:     }
1.15      daniel    460:     ret->table = (xmlElementPtr *) malloc(table->max_elements *
                    461:                                          sizeof(xmlElementPtr));
1.2       daniel    462:     if (ret->table == NULL) {
                    463:         fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
                    464:        free(ret);
                    465:        return(NULL);
                    466:     }
                    467:     ret->max_elements = table->max_elements;
                    468:     ret->nb_elements = table->nb_elements;
                    469:     for (i = 0;i < ret->nb_elements;i++) {
1.15      daniel    470:        cur = (xmlElementPtr) malloc(sizeof(xmlElement));
                    471:        if (cur == NULL) {
                    472:            fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
                    473:            free(ret);
                    474:            free(ret->table);
                    475:            return(NULL);
                    476:        }
                    477:        ret->table[i] = cur;
                    478:        ent = table->table[i];
1.2       daniel    479:        cur->type = ent->type;
                    480:        if (ent->name != NULL)
                    481:            cur->name = xmlStrdup(ent->name);
                    482:        else
                    483:            cur->name = NULL;
                    484:        cur->content = xmlCopyElementContent(ent->content);
1.15      daniel    485:        cur->attributes = NULL;
1.2       daniel    486:     }
1.1       daniel    487:     return(ret);
                    488: }
                    489: 
1.2       daniel    490: /**
                    491:  * xmlDumpElementTable:
1.9       daniel    492:  * @buf:  the XML buffer output
1.2       daniel    493:  * @table:  An element table
                    494:  *
                    495:  * This will dump the content of the element table as an XML DTD definition
                    496:  */
                    497: void
1.8       daniel    498: xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
1.2       daniel    499:     int i;
                    500:     xmlElementPtr cur;
                    501: 
                    502:     if (table == NULL) return;
                    503: 
                    504:     for (i = 0;i < table->nb_elements;i++) {
1.15      daniel    505:         cur = table->table[i];
1.2       daniel    506:         switch (cur->type) {
                    507:            case XML_ELEMENT_TYPE_EMPTY:
1.8       daniel    508:                xmlBufferWriteChar(buf, "<!ELEMENT ");
                    509:                xmlBufferWriteCHAR(buf, cur->name);
                    510:                xmlBufferWriteChar(buf, " EMPTY>\n");
1.2       daniel    511:                break;
                    512:            case XML_ELEMENT_TYPE_ANY:
1.8       daniel    513:                xmlBufferWriteChar(buf, "<!ELEMENT ");
                    514:                xmlBufferWriteCHAR(buf, cur->name);
                    515:                xmlBufferWriteChar(buf, " ANY>\n");
1.2       daniel    516:                break;
                    517:            case XML_ELEMENT_TYPE_MIXED:
1.8       daniel    518:                xmlBufferWriteChar(buf, "<!ELEMENT ");
                    519:                xmlBufferWriteCHAR(buf, cur->name);
                    520:                xmlBufferWriteChar(buf, " ");
                    521:                xmlDumpElementContent(buf, cur->content, 1);
                    522:                xmlBufferWriteChar(buf, ">\n");
1.2       daniel    523:                break;
                    524:            case XML_ELEMENT_TYPE_ELEMENT:
1.8       daniel    525:                xmlBufferWriteChar(buf, "<!ELEMENT ");
                    526:                xmlBufferWriteCHAR(buf, cur->name);
                    527:                xmlBufferWriteChar(buf, " ");
                    528:                xmlDumpElementContent(buf, cur->content, 1);
                    529:                xmlBufferWriteChar(buf, ">\n");
1.2       daniel    530:                break;
                    531:            default:
                    532:                fprintf(stderr,
                    533:                    "xmlDumpElementTable: internal: unknown type %d\n",
                    534:                        cur->type);
                    535:        }
1.4       daniel    536:     }
                    537: }
                    538: 
                    539: /**
                    540:  * xmlCreateEnumeration:
                    541:  * @name:  the enumeration name or NULL
                    542:  *
                    543:  * create and initialize an enumeration attribute node.
                    544:  *
1.6       daniel    545:  * Returns the xmlEnumerationPtr just created or NULL in case
1.4       daniel    546:  *                of error.
                    547:  */
                    548: xmlEnumerationPtr
                    549: xmlCreateEnumeration(CHAR *name) {
                    550:     xmlEnumerationPtr ret;
                    551: 
                    552:     ret = (xmlEnumerationPtr) malloc(sizeof(xmlEnumeration));
                    553:     if (ret == NULL) {
1.12      daniel    554:         fprintf(stderr, "xmlCreateEnumeration : malloc(%ld) failed\n",
                    555:                (long)sizeof(xmlEnumeration));
1.4       daniel    556:         return(NULL);
                    557:     }
                    558: 
                    559:     if (name != NULL)
                    560:         ret->name = xmlStrdup(name);
                    561:     else
                    562:         ret->name = NULL;
                    563:     ret->next = NULL;
                    564:     return(ret);
                    565: }
                    566: 
                    567: /**
                    568:  * xmlFreeEnumeration:
                    569:  * @cur:  the tree to free.
                    570:  *
                    571:  * free an enumeration attribute node (recursive).
                    572:  */
                    573: void
                    574: xmlFreeEnumeration(xmlEnumerationPtr cur) {
                    575:     if (cur == NULL) return;
                    576: 
                    577:     if (cur->next != NULL) xmlFreeEnumeration(cur->next);
                    578: 
                    579:     if (cur->name != NULL) free((CHAR *) cur->name);
                    580:     memset(cur, -1, sizeof(xmlEnumeration));
                    581:     free(cur);
                    582: }
                    583: 
                    584: /**
                    585:  * xmlCopyEnumeration:
                    586:  * @cur:  the tree to copy.
                    587:  *
                    588:  * Copy an enumeration attribute node (recursive).
                    589:  *
1.6       daniel    590:  * Returns the xmlEnumerationPtr just created or NULL in case
1.4       daniel    591:  *                of error.
                    592:  */
                    593: xmlEnumerationPtr
                    594: xmlCopyEnumeration(xmlEnumerationPtr cur) {
                    595:     xmlEnumerationPtr ret;
                    596: 
                    597:     if (cur == NULL) return(NULL);
                    598:     ret = xmlCreateEnumeration((CHAR *) cur->name);
                    599: 
                    600:     if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
                    601:     else ret->next = NULL;
                    602: 
                    603:     return(ret);
                    604: }
                    605: 
                    606: /**
1.18      daniel    607:  * xmlDumpEnumeration:
                    608:  * @buf:  the XML buffer output
                    609:  * @enum:  An enumeration
                    610:  *
                    611:  * This will dump the content of the enumeration
                    612:  */
                    613: void
                    614: xmlDumpEnumeration(xmlBufferPtr buf, xmlEnumerationPtr cur) {
                    615:     if (cur == NULL)  return;
                    616:     
                    617:     xmlBufferWriteCHAR(buf, cur->name);
                    618:     if (cur->next == NULL)
                    619:        xmlBufferWriteChar(buf, ")");
                    620:     else {
                    621:        xmlBufferWriteChar(buf, " | ");
                    622:        xmlDumpEnumeration(buf, cur->next);
                    623:     }
                    624: }
                    625: 
                    626: /**
1.4       daniel    627:  * xmlCreateAttributeTable:
                    628:  *
                    629:  * create and initialize an empty attribute hash table.
                    630:  *
1.6       daniel    631:  * Returns the xmlAttributeTablePtr just created or NULL in case
1.4       daniel    632:  *                of error.
                    633:  */
                    634: xmlAttributeTablePtr
                    635: xmlCreateAttributeTable(void) {
                    636:     xmlAttributeTablePtr ret;
                    637: 
                    638:     ret = (xmlAttributeTablePtr) 
                    639:          malloc(sizeof(xmlAttributeTable));
                    640:     if (ret == NULL) {
1.12      daniel    641:         fprintf(stderr, "xmlCreateAttributeTable : malloc(%ld) failed\n",
                    642:                (long)sizeof(xmlAttributeTable));
1.4       daniel    643:         return(NULL);
                    644:     }
                    645:     ret->max_attributes = XML_MIN_ATTRIBUTE_TABLE;
                    646:     ret->nb_attributes = 0;
1.15      daniel    647:     ret->table = (xmlAttributePtr *) 
                    648:          malloc(ret->max_attributes * sizeof(xmlAttributePtr));
1.4       daniel    649:     if (ret == NULL) {
1.12      daniel    650:         fprintf(stderr, "xmlCreateAttributeTable : malloc(%ld) failed\n",
1.15      daniel    651:                ret->max_attributes * (long)sizeof(xmlAttributePtr));
1.4       daniel    652:        free(ret);
                    653:         return(NULL);
                    654:     }
                    655:     return(ret);
                    656: }
                    657: 
1.15      daniel    658: /**
                    659:  * xmlScanAttributeDecl:
                    660:  * @dtd:  pointer to the DTD
                    661:  * @elem:  the element name
                    662:  *
                    663:  * When inserting a new element scan the DtD for existing attributes
                    664:  * for taht element and initialize the Attribute chain
                    665:  *
                    666:  * Returns the pointer to the first attribute decl in the chain,
                    667:  *         possibly NULL.
                    668:  */
                    669: xmlAttributePtr
                    670: xmlScanAttributeDecl(xmlDtdPtr dtd, const CHAR *elem) {
1.16      daniel    671:     xmlAttributePtr ret = NULL;
1.15      daniel    672:     xmlAttributeTablePtr table;
                    673:     int i;
                    674: 
                    675:     if (dtd == NULL) {
                    676:         fprintf(stderr, "xmlScanAttributeDecl: dtd == NULL\n");
                    677:        return(NULL);
                    678:     }
                    679:     if (elem == NULL) {
                    680:         fprintf(stderr, "xmlScanAttributeDecl: elem == NULL\n");
                    681:        return(NULL);
                    682:     }
                    683:     table = dtd->attributes;
                    684:     if (table == NULL) 
                    685:         return(NULL);
                    686: 
                    687:     for (i = 0;i < table->nb_attributes;i++) {
                    688:         if (!xmlStrcmp(table->table[i]->elem, elem)) {
1.16      daniel    689:            table->table[i]->next = ret;
                    690:            ret = table->table[i];
                    691:        }
                    692:     }
                    693:     return(ret);
                    694: }
                    695: 
                    696: /**
                    697:  * xmlScanIDAttributeDecl:
                    698:  * @ctxt:  the validation context
                    699:  * @elem:  the element name
                    700:  *
                    701:  * Veryfy that the element don't have too many ID attributes
                    702:  * declared.
                    703:  *
                    704:  * Returns the number of ID attributes found.
                    705:  */
                    706: int
                    707: xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
                    708:     xmlAttributePtr cur;
                    709:     int ret = 0;
                    710: 
                    711:     if (elem == NULL) return(0);
                    712:     cur = elem->attributes;
                    713:     while (cur != NULL) {
                    714:         if (cur->type == XML_ATTRIBUTE_ID) {
                    715:            ret ++;
                    716:            if (ret > 1)
                    717:                VERROR(ctxt->userData, 
                    718:               "Element %s has too may ID attributes defined : %s\n",
                    719:                       elem->name, cur->name);
1.15      daniel    720:        }
1.16      daniel    721:        cur = cur->next;
1.15      daniel    722:     }
                    723:     return(ret);
                    724: }
                    725: 
1.4       daniel    726: 
                    727: /**
                    728:  * xmlAddAttributeDecl:
1.16      daniel    729:  * @ctxt:  the validation context
1.6       daniel    730:  * @dtd:  pointer to the DTD
                    731:  * @elem:  the element name
                    732:  * @name:  the attribute name
                    733:  * @type:  the attribute type
                    734:  * @def:  the attribute default type
                    735:  * @defaultValue:  the attribute default value
                    736:  * @tree:  if it's an enumeration, the associated list
1.4       daniel    737:  *
                    738:  * Register a new attribute declaration
                    739:  *
1.6       daniel    740:  * Returns NULL if not, othervise the entity
1.4       daniel    741:  */
                    742: xmlAttributePtr
1.16      daniel    743: xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const CHAR *elem,
                    744:                     const CHAR *name, int type, int def,
                    745:                    const CHAR *defaultValue, xmlEnumerationPtr tree) {
1.4       daniel    746:     xmlAttributePtr ret, cur;
                    747:     xmlAttributeTablePtr table;
1.15      daniel    748:     xmlElementPtr elemDef;
1.4       daniel    749:     int i;
                    750: 
                    751:     if (dtd == NULL) {
                    752:         fprintf(stderr, "xmlAddAttributeDecl: dtd == NULL\n");
                    753:        return(NULL);
                    754:     }
                    755:     if (name == NULL) {
                    756:         fprintf(stderr, "xmlAddAttributeDecl: name == NULL\n");
                    757:        return(NULL);
                    758:     }
                    759:     if (elem == NULL) {
                    760:         fprintf(stderr, "xmlAddAttributeDecl: elem == NULL\n");
                    761:        return(NULL);
                    762:     }
                    763:     /* TODO: Lacks verifications !!! */
                    764:     switch (type) {
                    765:         case XML_ATTRIBUTE_CDATA:
                    766:            break;
                    767:         case XML_ATTRIBUTE_ID:
                    768:            break;
                    769:         case XML_ATTRIBUTE_IDREF:
                    770:            break;
                    771:         case XML_ATTRIBUTE_IDREFS:
                    772:            break;
                    773:         case XML_ATTRIBUTE_ENTITY:
                    774:            break;
                    775:         case XML_ATTRIBUTE_ENTITIES:
                    776:            break;
                    777:         case XML_ATTRIBUTE_NMTOKEN:
                    778:            break;
                    779:         case XML_ATTRIBUTE_NMTOKENS:
                    780:            break;
                    781:         case XML_ATTRIBUTE_ENUMERATION:
                    782:            break;
                    783:         case XML_ATTRIBUTE_NOTATION:
                    784:            break;
                    785:        default:
                    786:            fprintf(stderr, "xmlAddAttributeDecl: unknown type %d\n", type);
                    787:            return(NULL);
                    788:     }
                    789: 
                    790:     /*
                    791:      * Create the Attribute table if needed.
                    792:      */
                    793:     table = dtd->attributes;
                    794:     if (table == NULL) 
                    795:         table = dtd->attributes = xmlCreateAttributeTable();
                    796:     if (table == NULL) {
                    797:        fprintf(stderr, "xmlAddAttributeDecl: Table creation failed!\n");
                    798:         return(NULL);
                    799:     }
                    800: 
                    801:     /*
                    802:      * Validity Check:
                    803:      * Search the DTD for previous declarations of the ATTLIST
                    804:      */
                    805:     for (i = 0;i < table->nb_attributes;i++) {
1.15      daniel    806:         cur = table->table[i];
1.4       daniel    807:        if ((!xmlStrcmp(cur->name, name)) && (!xmlStrcmp(cur->elem, elem))) {
                    808:            /*
                    809:             * The attribute is already defined in this Dtd.
                    810:             */
                    811:            fprintf(stderr,
                    812:                    "xmlAddAttributeDecl: %s already defined\n", name);
                    813:        }
                    814:     }
                    815: 
                    816:     /*
                    817:      * Grow the table, if needed.
                    818:      */
                    819:     if (table->nb_attributes >= table->max_attributes) {
                    820:         /*
                    821:         * need more attributes.
                    822:         */
                    823:        table->max_attributes *= 2;
1.15      daniel    824:        table->table = (xmlAttributePtr *) 
                    825:            realloc(table->table, table->max_attributes * 
                    826:                    sizeof(xmlAttributePtr));
1.13      daniel    827:        if (table->table == NULL) {
1.4       daniel    828:            fprintf(stderr, "xmlAddAttributeDecl: out of memory\n");
                    829:            return(NULL);
                    830:        }
                    831:     }
1.15      daniel    832:     ret = (xmlAttributePtr) malloc(sizeof(xmlAttribute));
                    833:     if (ret == NULL) {
                    834:        fprintf(stderr, "xmlAddAttributeDecl: out of memory\n");
                    835:        return(NULL);
                    836:     }
                    837:     table->table[table->nb_attributes] = ret;
1.4       daniel    838: 
                    839:     /*
                    840:      * fill the structure.
                    841:      */
                    842:     ret->type = type;
                    843:     ret->name = xmlStrdup(name);
                    844:     ret->elem = xmlStrdup(elem);
                    845:     ret->def = def;
                    846:     ret->tree = tree;
                    847:     if (defaultValue != NULL)
                    848:        ret->defaultValue = xmlStrdup(defaultValue);
                    849:     else
                    850:         ret->defaultValue = NULL;
1.15      daniel    851:     elemDef = xmlGetDtdElementDesc(dtd, elem);
                    852:     if (elemDef != NULL) {
1.16      daniel    853:         if ((type == XML_ATTRIBUTE_ID) &&
                    854:            (xmlScanIDAttributeDecl(NULL, elemDef) != 0))
                    855:            VERROR(ctxt->userData, 
                    856:           "Element %s has too may ID attributes defined : %s\n",
                    857:                   elem, name);
1.15      daniel    858:         ret->next = elemDef->attributes;
                    859:         elemDef->attributes = ret;
                    860:     }
1.4       daniel    861:     table->nb_attributes++;
                    862: 
                    863:     return(ret);
                    864: }
                    865: 
                    866: /**
                    867:  * xmlFreeAttribute:
                    868:  * @elem:  An attribute
                    869:  *
                    870:  * Deallocate the memory used by an attribute definition
                    871:  */
                    872: void
                    873: xmlFreeAttribute(xmlAttributePtr attr) {
                    874:     if (attr == NULL) return;
                    875:     if (attr->tree != NULL)
                    876:         xmlFreeEnumeration(attr->tree);
                    877:     if (attr->elem != NULL)
                    878:        free((CHAR *) attr->elem);
                    879:     if (attr->name != NULL)
                    880:        free((CHAR *) attr->name);
                    881:     if (attr->defaultValue != NULL)
                    882:        free((CHAR *) attr->defaultValue);
                    883:     memset(attr, -1, sizeof(xmlAttribute));
1.15      daniel    884:     free(attr);
1.4       daniel    885: }
                    886: 
                    887: /**
                    888:  * xmlFreeAttributeTable:
                    889:  * @table:  An attribute table
                    890:  *
                    891:  * Deallocate the memory used by an entities hash table.
                    892:  */
                    893: void
                    894: xmlFreeAttributeTable(xmlAttributeTablePtr table) {
                    895:     int i;
                    896: 
                    897:     if (table == NULL) return;
                    898: 
                    899:     for (i = 0;i < table->nb_attributes;i++) {
1.15      daniel    900:         xmlFreeAttribute(table->table[i]);
1.4       daniel    901:     }
                    902:     free(table->table);
                    903:     free(table);
                    904: }
                    905: 
                    906: /**
                    907:  * xmlCopyAttributeTable:
                    908:  * @table:  An attribute table
                    909:  *
                    910:  * Build a copy of an attribute table.
                    911:  * 
1.6       daniel    912:  * Returns the new xmlAttributeTablePtr or NULL in case of error.
1.4       daniel    913:  */
                    914: xmlAttributeTablePtr
                    915: xmlCopyAttributeTable(xmlAttributeTablePtr table) {
                    916:     xmlAttributeTablePtr ret;
                    917:     xmlAttributePtr cur, attr;
                    918:     int i;
                    919: 
                    920:     ret = (xmlAttributeTablePtr) malloc(sizeof(xmlAttributeTable));
                    921:     if (ret == NULL) {
                    922:         fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
                    923:        return(NULL);
                    924:     }
1.15      daniel    925:     ret->table = (xmlAttributePtr *) malloc(table->max_attributes *
                    926:                                           sizeof(xmlAttributePtr));
1.4       daniel    927:     if (ret->table == NULL) {
                    928:         fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
                    929:        free(ret);
                    930:        return(NULL);
                    931:     }
                    932:     ret->max_attributes = table->max_attributes;
                    933:     ret->nb_attributes = table->nb_attributes;
                    934:     for (i = 0;i < ret->nb_attributes;i++) {
1.15      daniel    935:        attr = table->table[i];
                    936:        cur = (xmlAttributePtr) malloc(sizeof(xmlAttribute));
                    937:        if (cur == NULL) {
                    938:            fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
                    939:            free(ret);
                    940:            free(ret->table);
                    941:            return(NULL);
                    942:        }
                    943:        ret->table[i] = cur;
1.4       daniel    944:        cur->type = attr->type;
                    945:        cur->def = attr->def;
                    946:        cur->tree = xmlCopyEnumeration(attr->tree);
                    947:        if (attr->elem != NULL)
                    948:            cur->elem = xmlStrdup(attr->elem);
                    949:        else
                    950:            cur->elem = NULL;
                    951:        if (attr->name != NULL)
                    952:            cur->name = xmlStrdup(attr->name);
                    953:        else
                    954:            cur->name = NULL;
                    955:        if (attr->defaultValue != NULL)
                    956:            cur->defaultValue = xmlStrdup(attr->defaultValue);
                    957:        else
                    958:            cur->defaultValue = NULL;
1.15      daniel    959:        /* NEED to rebuild the next chain !!!!!! */
1.4       daniel    960:     }
                    961:     return(ret);
                    962: }
                    963: 
                    964: /**
                    965:  * xmlDumpAttributeTable:
1.9       daniel    966:  * @buf:  the XML buffer output
1.4       daniel    967:  * @table:  An attribute table
                    968:  *
                    969:  * This will dump the content of the attribute table as an XML DTD definition
                    970:  */
                    971: void
1.8       daniel    972: xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
1.4       daniel    973:     int i;
                    974:     xmlAttributePtr cur;
                    975: 
                    976:     if (table == NULL) return;
                    977: 
                    978:     for (i = 0;i < table->nb_attributes;i++) {
1.15      daniel    979:         cur = table->table[i];
1.8       daniel    980:        xmlBufferWriteChar(buf, "<!ATTLIST ");
                    981:        xmlBufferWriteCHAR(buf, cur->elem);
                    982:        xmlBufferWriteChar(buf, " ");
                    983:        xmlBufferWriteCHAR(buf, cur->name);
1.4       daniel    984:         switch (cur->type) {
                    985:             case XML_ATTRIBUTE_CDATA:
1.8       daniel    986:                xmlBufferWriteChar(buf, " CDATA");
1.4       daniel    987:                 break;
                    988:             case XML_ATTRIBUTE_ID:
1.8       daniel    989:                xmlBufferWriteChar(buf, " ID");
1.4       daniel    990:                 break;
                    991:             case XML_ATTRIBUTE_IDREF:
1.8       daniel    992:                xmlBufferWriteChar(buf, " IDREF");
1.4       daniel    993:                 break;
                    994:             case XML_ATTRIBUTE_IDREFS:
1.8       daniel    995:                xmlBufferWriteChar(buf, " IDREFS");
1.4       daniel    996:                 break;
                    997:             case XML_ATTRIBUTE_ENTITY:
1.8       daniel    998:                xmlBufferWriteChar(buf, " ENTITY");
1.4       daniel    999:                 break;
                   1000:             case XML_ATTRIBUTE_ENTITIES:
1.8       daniel   1001:                xmlBufferWriteChar(buf, " ENTITIES");
1.4       daniel   1002:                 break;
                   1003:             case XML_ATTRIBUTE_NMTOKEN:
1.8       daniel   1004:                xmlBufferWriteChar(buf, " NMTOKEN");
1.4       daniel   1005:                 break;
                   1006:             case XML_ATTRIBUTE_NMTOKENS:
1.8       daniel   1007:                xmlBufferWriteChar(buf, " NMTOKENS");
1.4       daniel   1008:                 break;
                   1009:             case XML_ATTRIBUTE_ENUMERATION:
1.18      daniel   1010:                 xmlBufferWriteChar(buf, " (");
                   1011:                xmlDumpEnumeration(buf, cur->tree);
1.4       daniel   1012:                 break;
                   1013:             case XML_ATTRIBUTE_NOTATION:
1.18      daniel   1014:                 xmlBufferWriteChar(buf, " NOTATION (");
                   1015:                xmlDumpEnumeration(buf, cur->tree);
1.4       daniel   1016:                 break;
                   1017:            default:
                   1018:                fprintf(stderr,
                   1019:                    "xmlDumpAttributeTable: internal: unknown type %d\n",
                   1020:                        cur->type);
                   1021:        }
                   1022:         switch (cur->def) {
                   1023:             case XML_ATTRIBUTE_NONE:
                   1024:                 break;
                   1025:             case XML_ATTRIBUTE_REQUIRED:
1.8       daniel   1026:                xmlBufferWriteChar(buf, " #REQUIRED");
1.4       daniel   1027:                 break;
                   1028:             case XML_ATTRIBUTE_IMPLIED:
1.8       daniel   1029:                xmlBufferWriteChar(buf, " #IMPLIED");
1.4       daniel   1030:                 break;
                   1031:             case XML_ATTRIBUTE_FIXED:
1.17      daniel   1032:                xmlBufferWriteChar(buf, " #FIXED");
1.4       daniel   1033:                 break;
                   1034:            default:
                   1035:                fprintf(stderr,
                   1036:                    "xmlDumpAttributeTable: internal: unknown default %d\n",
                   1037:                        cur->def);
                   1038:         }
1.17      daniel   1039:        if (cur->defaultValue != NULL) {
                   1040:            xmlBufferWriteChar(buf, " ");
                   1041:            xmlBufferWriteQuotedString(buf, cur->defaultValue);
                   1042:        }
1.8       daniel   1043:         xmlBufferWriteChar(buf, ">\n");
1.5       daniel   1044:     }
                   1045: }
                   1046: 
                   1047: /************************************************************************
                   1048:  *                                                                     *
                   1049:  *                             NOTATIONs                               *
                   1050:  *                                                                     *
                   1051:  ************************************************************************/
                   1052: /**
                   1053:  * xmlCreateNotationTable:
                   1054:  *
                   1055:  * create and initialize an empty notation hash table.
                   1056:  *
1.6       daniel   1057:  * Returns the xmlNotationTablePtr just created or NULL in case
1.5       daniel   1058:  *                of error.
                   1059:  */
                   1060: xmlNotationTablePtr
                   1061: xmlCreateNotationTable(void) {
                   1062:     xmlNotationTablePtr ret;
                   1063: 
                   1064:     ret = (xmlNotationTablePtr) 
                   1065:          malloc(sizeof(xmlNotationTable));
                   1066:     if (ret == NULL) {
1.12      daniel   1067:         fprintf(stderr, "xmlCreateNotationTable : malloc(%ld) failed\n",
                   1068:                (long)sizeof(xmlNotationTable));
1.5       daniel   1069:         return(NULL);
                   1070:     }
                   1071:     ret->max_notations = XML_MIN_NOTATION_TABLE;
                   1072:     ret->nb_notations = 0;
1.15      daniel   1073:     ret->table = (xmlNotationPtr *) 
                   1074:          malloc(ret->max_notations * sizeof(xmlNotationPtr));
1.5       daniel   1075:     if (ret == NULL) {
1.12      daniel   1076:         fprintf(stderr, "xmlCreateNotationTable : malloc(%ld) failed\n",
                   1077:                ret->max_notations * (long)sizeof(xmlNotation));
1.5       daniel   1078:        free(ret);
                   1079:         return(NULL);
                   1080:     }
                   1081:     return(ret);
                   1082: }
                   1083: 
                   1084: 
                   1085: /**
                   1086:  * xmlAddNotationDecl:
1.6       daniel   1087:  * @dtd:  pointer to the DTD
1.16      daniel   1088:  * @ctxt:  the validation context
1.5       daniel   1089:  * @name:  the entity name
1.6       daniel   1090:  * @PublicID:  the public identifier or NULL
                   1091:  * @SystemID:  the system identifier or NULL
1.5       daniel   1092:  *
                   1093:  * Register a new notation declaration
                   1094:  *
1.6       daniel   1095:  * Returns NULL if not, othervise the entity
1.5       daniel   1096:  */
                   1097: xmlNotationPtr
1.16      daniel   1098: xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const CHAR *name,
                   1099:                    const CHAR *PublicID, const CHAR *SystemID) {
1.5       daniel   1100:     xmlNotationPtr ret, cur;
                   1101:     xmlNotationTablePtr table;
                   1102:     int i;
                   1103: 
                   1104:     if (dtd == NULL) {
                   1105:         fprintf(stderr, "xmlAddNotationDecl: dtd == NULL\n");
                   1106:        return(NULL);
                   1107:     }
                   1108:     if (name == NULL) {
                   1109:         fprintf(stderr, "xmlAddNotationDecl: name == NULL\n");
                   1110:        return(NULL);
                   1111:     }
                   1112:     if ((PublicID == NULL) && (SystemID == NULL)) {
                   1113:         fprintf(stderr, "xmlAddNotationDecl: no PUBLIC ID nor SYSTEM ID\n");
                   1114:     }
                   1115: 
                   1116:     /*
                   1117:      * Create the Notation table if needed.
                   1118:      */
                   1119:     table = dtd->notations;
                   1120:     if (table == NULL) 
                   1121:         table = dtd->notations = xmlCreateNotationTable();
                   1122:     if (table == NULL) {
                   1123:        fprintf(stderr, "xmlAddNotationDecl: Table creation failed!\n");
                   1124:         return(NULL);
                   1125:     }
                   1126: 
                   1127:     /*
                   1128:      * Validity Check:
                   1129:      * Search the DTD for previous declarations of the ATTLIST
                   1130:      */
                   1131:     for (i = 0;i < table->nb_notations;i++) {
1.15      daniel   1132:         cur = table->table[i];
1.5       daniel   1133:        if (!xmlStrcmp(cur->name, name)) {
                   1134:            /*
                   1135:             * The notation is already defined in this Dtd.
                   1136:             */
                   1137:            fprintf(stderr,
                   1138:                    "xmlAddNotationDecl: %s already defined\n", name);
                   1139:        }
                   1140:     }
                   1141: 
                   1142:     /*
                   1143:      * Grow the table, if needed.
                   1144:      */
                   1145:     if (table->nb_notations >= table->max_notations) {
                   1146:         /*
                   1147:         * need more notations.
                   1148:         */
                   1149:        table->max_notations *= 2;
1.15      daniel   1150:        table->table = (xmlNotationPtr *) 
                   1151:            realloc(table->table, table->max_notations *
                   1152:                    sizeof(xmlNotationPtr));
1.13      daniel   1153:        if (table->table == NULL) {
1.5       daniel   1154:            fprintf(stderr, "xmlAddNotationDecl: out of memory\n");
                   1155:            return(NULL);
                   1156:        }
                   1157:     }
1.15      daniel   1158:     ret = (xmlNotationPtr) malloc(sizeof(xmlNotation));
                   1159:     if (ret == NULL) {
                   1160:        fprintf(stderr, "xmlAddNotationDecl: out of memory\n");
                   1161:        return(NULL);
                   1162:     }
                   1163:     table->table[table->nb_notations] = ret;
1.5       daniel   1164: 
                   1165:     /*
                   1166:      * fill the structure.
                   1167:      */
                   1168:     ret->name = xmlStrdup(name);
                   1169:     if (SystemID != NULL)
                   1170:         ret->SystemID = xmlStrdup(SystemID);
                   1171:     else
                   1172:         ret->SystemID = NULL;
                   1173:     if (PublicID != NULL)
                   1174:         ret->PublicID = xmlStrdup(PublicID);
                   1175:     else
                   1176:         ret->PublicID = NULL;
                   1177:     table->nb_notations++;
                   1178: 
                   1179:     return(ret);
                   1180: }
                   1181: 
                   1182: /**
                   1183:  * xmlFreeNotation:
                   1184:  * @not:  A notation
                   1185:  *
                   1186:  * Deallocate the memory used by an notation definition
                   1187:  */
                   1188: void
                   1189: xmlFreeNotation(xmlNotationPtr nota) {
                   1190:     if (nota == NULL) return;
                   1191:     if (nota->name != NULL)
                   1192:        free((CHAR *) nota->name);
                   1193:     if (nota->PublicID != NULL)
                   1194:        free((CHAR *) nota->PublicID);
                   1195:     if (nota->SystemID != NULL)
                   1196:        free((CHAR *) nota->SystemID);
                   1197:     memset(nota, -1, sizeof(xmlNotation));
1.15      daniel   1198:     free(nota);
1.5       daniel   1199: }
                   1200: 
                   1201: /**
                   1202:  * xmlFreeNotationTable:
                   1203:  * @table:  An notation table
                   1204:  *
                   1205:  * Deallocate the memory used by an entities hash table.
                   1206:  */
                   1207: void
                   1208: xmlFreeNotationTable(xmlNotationTablePtr table) {
                   1209:     int i;
                   1210: 
                   1211:     if (table == NULL) return;
                   1212: 
                   1213:     for (i = 0;i < table->nb_notations;i++) {
1.15      daniel   1214:         xmlFreeNotation(table->table[i]);
1.5       daniel   1215:     }
                   1216:     free(table->table);
                   1217:     free(table);
                   1218: }
                   1219: 
                   1220: /**
                   1221:  * xmlCopyNotationTable:
                   1222:  * @table:  A notation table
                   1223:  *
                   1224:  * Build a copy of a notation table.
                   1225:  * 
1.6       daniel   1226:  * Returns the new xmlNotationTablePtr or NULL in case of error.
1.5       daniel   1227:  */
                   1228: xmlNotationTablePtr
                   1229: xmlCopyNotationTable(xmlNotationTablePtr table) {
                   1230:     xmlNotationTablePtr ret;
                   1231:     xmlNotationPtr cur, nota;
                   1232:     int i;
                   1233: 
                   1234:     ret = (xmlNotationTablePtr) malloc(sizeof(xmlNotationTable));
                   1235:     if (ret == NULL) {
                   1236:         fprintf(stderr, "xmlCopyNotationTable: out of memory !\n");
                   1237:        return(NULL);
                   1238:     }
1.15      daniel   1239:     ret->table = (xmlNotationPtr *) malloc(table->max_notations *
                   1240:                                          sizeof(xmlNotationPtr));
1.5       daniel   1241:     if (ret->table == NULL) {
                   1242:         fprintf(stderr, "xmlCopyNotationTable: out of memory !\n");
                   1243:        free(ret);
                   1244:        return(NULL);
                   1245:     }
                   1246:     ret->max_notations = table->max_notations;
                   1247:     ret->nb_notations = table->nb_notations;
                   1248:     for (i = 0;i < ret->nb_notations;i++) {
1.15      daniel   1249:        cur = (xmlNotationPtr) malloc(sizeof(xmlNotation));
                   1250:        if (cur == NULL) {
                   1251:            fprintf(stderr, "xmlCopyNotationTable: out of memory !\n");
                   1252:            free(ret);
                   1253:            free(ret->table);
                   1254:            return(NULL);
                   1255:        }
                   1256:        ret->table[i] = cur;
                   1257:        nota = table->table[i];
1.5       daniel   1258:        if (nota->name != NULL)
                   1259:            cur->name = xmlStrdup(nota->name);
                   1260:        else
                   1261:            cur->name = NULL;
                   1262:        if (nota->PublicID != NULL)
                   1263:            cur->PublicID = xmlStrdup(nota->PublicID);
                   1264:        else
                   1265:            cur->PublicID = NULL;
                   1266:        if (nota->SystemID != NULL)
                   1267:            cur->SystemID = xmlStrdup(nota->SystemID);
                   1268:        else
                   1269:            cur->SystemID = NULL;
                   1270:     }
                   1271:     return(ret);
                   1272: }
                   1273: 
                   1274: /**
                   1275:  * xmlDumpNotationTable:
1.9       daniel   1276:  * @buf:  the XML buffer output
1.5       daniel   1277:  * @table:  A notation table
                   1278:  *
                   1279:  * This will dump the content of the notation table as an XML DTD definition
                   1280:  */
                   1281: void
1.8       daniel   1282: xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
1.5       daniel   1283:     int i;
                   1284:     xmlNotationPtr cur;
                   1285: 
                   1286:     if (table == NULL) return;
                   1287: 
                   1288:     for (i = 0;i < table->nb_notations;i++) {
1.15      daniel   1289:         cur = table->table[i];
1.8       daniel   1290:        xmlBufferWriteChar(buf, "<!NOTATION ");
                   1291:        xmlBufferWriteCHAR(buf, cur->name);
1.5       daniel   1292:        if (cur->PublicID != NULL) {
1.10      daniel   1293:            xmlBufferWriteChar(buf, " PUBLIC ");
                   1294:            xmlBufferWriteQuotedString(buf, cur->PublicID);
1.5       daniel   1295:            if (cur->SystemID != NULL) {
1.8       daniel   1296:                xmlBufferWriteChar(buf, " ");
                   1297:                xmlBufferWriteCHAR(buf, cur->SystemID);
1.5       daniel   1298:            }
                   1299:        } else {
1.8       daniel   1300:            xmlBufferWriteChar(buf, " SYSTEM ");
                   1301:            xmlBufferWriteCHAR(buf, cur->SystemID);
1.5       daniel   1302:        }
1.8       daniel   1303:         xmlBufferWriteChar(buf, " >\n");
1.2       daniel   1304:     }
                   1305: }
1.14      daniel   1306: 
                   1307: /************************************************************************
                   1308:  *                                                                     *
                   1309:  *             Routines for validity checking                          *
                   1310:  *                                                                     *
                   1311:  ************************************************************************/
                   1312: 
                   1313: /**
                   1314:  * xmlGetDtdElementDesc:
                   1315:  * @dtd:  a pointer to the DtD to search
                   1316:  * @name:  the element name
                   1317:  *
                   1318:  * Search the Dtd for the description of this element
                   1319:  *
                   1320:  * returns the xmlElementPtr if found or NULL
                   1321:  */
                   1322: 
                   1323: xmlElementPtr
                   1324: xmlGetDtdElementDesc(xmlDtdPtr dtd, const CHAR *name) {
                   1325:     xmlElementTablePtr table;
                   1326:     xmlElementPtr cur;
                   1327:     int i;
                   1328: 
                   1329:     if (dtd == NULL) return(NULL);
                   1330:     if (dtd->elements == NULL) return(NULL);
                   1331:     table = dtd->elements;
                   1332: 
                   1333:     for (i = 0;i < table->nb_elements;i++) {
1.15      daniel   1334:         cur = table->table[i];
1.14      daniel   1335:        if (!xmlStrcmp(cur->name, name))
                   1336:            return(cur);
                   1337:     }
                   1338:     return(NULL);
                   1339: }
                   1340: 
                   1341: /**
                   1342:  * xmlGetDtdAttrDesc:
                   1343:  * @dtd:  a pointer to the DtD to search
1.15      daniel   1344:  * @elem:  the element name
1.14      daniel   1345:  * @name:  the attribute name
                   1346:  *
1.15      daniel   1347:  * Search the Dtd for the description of this attribute on
                   1348:  * this element.
1.14      daniel   1349:  *
                   1350:  * returns the xmlAttributePtr if found or NULL
                   1351:  */
                   1352: 
                   1353: xmlAttributePtr
1.15      daniel   1354: xmlGetDtdAttrDesc(xmlDtdPtr dtd, const CHAR *elem, const CHAR *name) {
1.14      daniel   1355:     xmlAttributeTablePtr table;
                   1356:     xmlAttributePtr cur;
                   1357:     int i;
                   1358: 
                   1359:     if (dtd == NULL) return(NULL);
                   1360:     if (dtd->attributes == NULL) return(NULL);
                   1361:     table = dtd->attributes;
                   1362: 
                   1363:     for (i = 0;i < table->nb_attributes;i++) {
1.15      daniel   1364:         cur = table->table[i];
                   1365:        if ((!xmlStrcmp(cur->name, name)) &&
                   1366:            (!xmlStrcmp(cur->elem, elem)))
1.14      daniel   1367:            return(cur);
                   1368:     }
                   1369:     return(NULL);
                   1370: }
                   1371: 
                   1372: /**
                   1373:  * xmlGetDtdNotationDesc:
                   1374:  * @dtd:  a pointer to the DtD to search
                   1375:  * @name:  the notation name
                   1376:  *
                   1377:  * Search the Dtd for the description of this notation
                   1378:  *
                   1379:  * returns the xmlNotationPtr if found or NULL
                   1380:  */
                   1381: 
                   1382: xmlNotationPtr
                   1383: xmlGetDtdNotationDesc(xmlDtdPtr dtd, const CHAR *name) {
                   1384:     xmlNotationTablePtr table;
                   1385:     xmlNotationPtr cur;
                   1386:     int i;
                   1387: 
                   1388:     if (dtd == NULL) return(NULL);
                   1389:     if (dtd->notations == NULL) return(NULL);
                   1390:     table = dtd->notations;
                   1391: 
                   1392:     for (i = 0;i < table->nb_notations;i++) {
1.15      daniel   1393:         cur = table->table[i];
1.14      daniel   1394:        if (!xmlStrcmp(cur->name, name))
                   1395:            return(cur);
                   1396:     }
                   1397:     return(NULL);
                   1398: }
                   1399: 
                   1400: /**
1.18      daniel   1401:  * xmlIsMixedElement
                   1402:  * @doc:  the document
                   1403:  * @name:  the element name
                   1404:  *
                   1405:  * Search in the DtDs whether an element accept Mixed content (or ANY)
                   1406:  * basically if it is supposed to accept text childs
                   1407:  *
                   1408:  * returns 0 if no, 1 if yes, and -1 if no element description is available
                   1409:  */
                   1410: 
                   1411: int
                   1412: xmlIsMixedElement(xmlDocPtr doc, const CHAR *name) {
                   1413:     xmlElementPtr elemDecl;
                   1414: 
                   1415:     if ((doc == NULL) || (doc->intSubset == NULL)) return(-1);
                   1416: 
                   1417:     elemDecl = xmlGetDtdElementDesc(doc->intSubset, name);
                   1418:     if ((elemDecl == NULL) && (doc->extSubset != NULL))
                   1419:        elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
                   1420:     if (elemDecl == NULL) return(-1);
                   1421:     switch (elemDecl->type) {
                   1422:        case XML_ELEMENT_TYPE_ELEMENT:
                   1423:            return(0);
                   1424:         case XML_ELEMENT_TYPE_EMPTY:
                   1425:            /*
                   1426:             * return 1 for EMPTY since we want VC error to pop up
                   1427:             * on <empty>     </empty> for example
                   1428:             */
                   1429:        case XML_ELEMENT_TYPE_ANY:
                   1430:        case XML_ELEMENT_TYPE_MIXED:
                   1431:            return(1);
                   1432:     }
                   1433:     return(1);
                   1434: }
                   1435: 
                   1436: /**
1.16      daniel   1437:  * xmlValidateNameValue:
                   1438:  * @value:  an Name value
                   1439:  *
                   1440:  * Validate that the given value match Name production
                   1441:  *
                   1442:  * returns 1 if valid or 0 otherwise
                   1443:  */
                   1444: 
                   1445: int
                   1446: xmlValidateNameValue(const CHAR *value) {
                   1447:     const CHAR *cur;
                   1448: 
                   1449:     if (value == NULL) return(0);
                   1450:     cur = value;
                   1451:     
                   1452:     if (!IS_LETTER(*cur) && (*cur != '_') &&
                   1453:         (*cur != ':')) {
                   1454:        return(0);
                   1455:     }
                   1456: 
                   1457:     while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1458:            (*cur == '.') || (*cur == '-') ||
                   1459:           (*cur == '_') || (*cur == ':') || 
                   1460:           (IS_COMBINING(*cur)) ||
                   1461:           (IS_EXTENDER(*cur)))
                   1462:           cur++;
                   1463: 
                   1464:     if (*cur != 0) return(0);
                   1465: 
                   1466:     return(1);
                   1467: }
                   1468: 
                   1469: /**
                   1470:  * xmlValidateNamesValue:
                   1471:  * @value:  an Names value
                   1472:  *
                   1473:  * Validate that the given value match Names production
                   1474:  *
                   1475:  * returns 1 if valid or 0 otherwise
                   1476:  */
                   1477: 
                   1478: int
                   1479: xmlValidateNamesValue(const CHAR *value) {
                   1480:     const CHAR *cur;
                   1481: 
                   1482:     if (value == NULL) return(0);
                   1483:     cur = value;
                   1484:     
                   1485:     if (!IS_LETTER(*cur) && (*cur != '_') &&
                   1486:         (*cur != ':')) {
                   1487:        return(0);
                   1488:     }
                   1489: 
                   1490:     while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1491:            (*cur == '.') || (*cur == '-') ||
                   1492:           (*cur == '_') || (*cur == ':') || 
                   1493:           (IS_COMBINING(*cur)) ||
                   1494:           (IS_EXTENDER(*cur)))
                   1495:           cur++;
                   1496: 
                   1497:     while (IS_BLANK(*cur)) {
                   1498:        while (IS_BLANK(*cur)) cur++;
                   1499: 
                   1500:        if (!IS_LETTER(*cur) && (*cur != '_') &&
                   1501:            (*cur != ':')) {
                   1502:            return(0);
                   1503:        }
                   1504: 
                   1505:        while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1506:               (*cur == '.') || (*cur == '-') ||
                   1507:               (*cur == '_') || (*cur == ':') || 
                   1508:               (IS_COMBINING(*cur)) ||
                   1509:               (IS_EXTENDER(*cur)))
                   1510:               cur++;
                   1511:     }
                   1512: 
                   1513:     if (*cur != 0) return(0);
                   1514: 
                   1515:     return(1);
                   1516: }
                   1517: 
                   1518: /**
                   1519:  * xmlValidateNmtokenValue:
                   1520:  * @value:  an Mntoken value
                   1521:  *
                   1522:  * Validate that the given value match Nmtoken production
                   1523:  *
                   1524:  * [ VC: Name Token ]
                   1525:  * 
                   1526:  * returns 1 if valid or 0 otherwise
                   1527:  */
                   1528: 
                   1529: int
                   1530: xmlValidateNmtokenValue(const CHAR *value) {
                   1531:     const CHAR *cur;
                   1532: 
                   1533:     if (value == NULL) return(0);
                   1534:     cur = value;
                   1535:     
                   1536:     if (!IS_LETTER(*cur) && !IS_DIGIT(*cur) &&
                   1537:         (*cur != '.') && (*cur != '-') &&
                   1538:         (*cur != '_') && (*cur != ':') && 
                   1539:         (!IS_COMBINING(*cur)) &&
                   1540:         (!IS_EXTENDER(*cur)))
                   1541:        return(0);
                   1542: 
                   1543:     while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1544:            (*cur == '.') || (*cur == '-') ||
                   1545:           (*cur == '_') || (*cur == ':') || 
                   1546:           (IS_COMBINING(*cur)) ||
                   1547:           (IS_EXTENDER(*cur)))
                   1548:           cur++;
                   1549: 
                   1550:     if (*cur != 0) return(0);
                   1551: 
                   1552:     return(1);
                   1553:     return(1);
                   1554: }
                   1555: 
                   1556: /**
                   1557:  * xmlValidateNmtokensValue:
                   1558:  * @value:  an Mntokens value
                   1559:  *
                   1560:  * Validate that the given value match Nmtokens production
                   1561:  *
                   1562:  * [ VC: Name Token ]
                   1563:  * 
                   1564:  * returns 1 if valid or 0 otherwise
                   1565:  */
                   1566: 
                   1567: int
                   1568: xmlValidateNmtokensValue(const CHAR *value) {
                   1569:     const CHAR *cur;
                   1570: 
                   1571:     if (value == NULL) return(0);
                   1572:     cur = value;
                   1573:     
                   1574:     if (!IS_LETTER(*cur) && !IS_DIGIT(*cur) &&
                   1575:         (*cur != '.') && (*cur != '-') &&
                   1576:         (*cur != '_') && (*cur != ':') && 
                   1577:         (!IS_COMBINING(*cur)) &&
                   1578:         (!IS_EXTENDER(*cur)))
                   1579:        return(0);
                   1580: 
                   1581:     while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1582:            (*cur == '.') || (*cur == '-') ||
                   1583:           (*cur == '_') || (*cur == ':') || 
                   1584:           (IS_COMBINING(*cur)) ||
                   1585:           (IS_EXTENDER(*cur)))
                   1586:           cur++;
                   1587: 
                   1588:     while (IS_BLANK(*cur)) {
                   1589:        while (IS_BLANK(*cur)) cur++;
                   1590: 
                   1591:        if (!IS_LETTER(*cur) && !IS_DIGIT(*cur) &&
                   1592:            (*cur != '.') && (*cur != '-') &&
                   1593:            (*cur != '_') && (*cur != ':') && 
                   1594:            (!IS_COMBINING(*cur)) &&
                   1595:            (!IS_EXTENDER(*cur)))
                   1596:            return(0);
                   1597: 
                   1598:        while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1599:               (*cur == '.') || (*cur == '-') ||
                   1600:               (*cur == '_') || (*cur == ':') || 
                   1601:               (IS_COMBINING(*cur)) ||
                   1602:               (IS_EXTENDER(*cur)))
                   1603:               cur++;
                   1604:     }
                   1605: 
                   1606:     if (*cur != 0) return(0);
                   1607: 
                   1608:     return(1);
                   1609: }
                   1610: 
                   1611: /**
                   1612:  * xmlValidateNotationDecl:
                   1613:  * @doc:  a document instance
                   1614:  * @nota:  a notation definition
                   1615:  *
                   1616:  * Try to validate a single notation definition
                   1617:  * basically it does the following checks as described by the
                   1618:  * XML-1.0 recommendation:
1.18      daniel   1619:  *  - it seems that no validity constraing exist on notation declarations
                   1620:  * But this function get called anyway ...
1.16      daniel   1621:  *
                   1622:  * returns 1 if valid or 0 otherwise
                   1623:  */
                   1624: 
                   1625: int
                   1626: xmlValidateNotationDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
                   1627:                          xmlNotationPtr nota) {
                   1628:     int ret = 1;
                   1629: 
                   1630:     return(ret);
                   1631: }
                   1632: 
                   1633: /**
                   1634:  * xmlValidateAttributeValue:
                   1635:  * @type:  an attribute type
                   1636:  * @value:  an attribute value
                   1637:  *
                   1638:  * Validate that the given attribute value match  the proper production
                   1639:  *
                   1640:  * [ VC: ID ]
                   1641:  * Values of type ID must match the Name production....
                   1642:  *
                   1643:  * [ VC: IDREF ]
                   1644:  * Values of type IDREF must match the Name production, and values
                   1645:  * of type IDREFS must match Names ...
                   1646:  *
                   1647:  * [ VC: Entity Name ]
                   1648:  * Values of type ENTITY must match the Name production, values
                   1649:  * of type ENTITIES must match Names ...
                   1650:  *
                   1651:  * [ VC: Name Token ]
                   1652:  * Values of type NMTOKEN must match the Nmtoken production; values
                   1653:  * of type NMTOKENS must match Nmtokens. 
                   1654:  *
                   1655:  * returns 1 if valid or 0 otherwise
                   1656:  */
                   1657: 
                   1658: int
                   1659: xmlValidateAttributeValue(xmlAttributeType type, const CHAR *value) {
                   1660:     switch (type) {
                   1661:        case XML_ATTRIBUTE_IDREFS:
                   1662:        case XML_ATTRIBUTE_ENTITIES:
                   1663:            return(xmlValidateNamesValue(value));
                   1664:        case XML_ATTRIBUTE_IDREF:
                   1665:        case XML_ATTRIBUTE_ID:
                   1666:        case XML_ATTRIBUTE_ENTITY:
                   1667:        case XML_ATTRIBUTE_NOTATION:
                   1668:            return(xmlValidateNameValue(value));
                   1669:        case XML_ATTRIBUTE_NMTOKENS:
                   1670:        case XML_ATTRIBUTE_ENUMERATION:
                   1671:            return(xmlValidateNmtokensValue(value));
                   1672:        case XML_ATTRIBUTE_NMTOKEN:
                   1673:            return(xmlValidateNmtokenValue(value));
                   1674:         case XML_ATTRIBUTE_CDATA:
                   1675:            break;
                   1676:     }
                   1677:     return(1);
                   1678: }
                   1679: 
                   1680: /**
1.14      daniel   1681:  * xmlValidateAttributeDecl:
                   1682:  * @doc:  a document instance
                   1683:  * @attr:  an attribute definition
                   1684:  *
                   1685:  * Try to validate a single attribute definition
                   1686:  * basically it does the following checks as described by the
                   1687:  * XML-1.0 recommendation:
                   1688:  *  - [ VC: Attribute Default Legal ]
                   1689:  *  - [ VC: Enumeration ]
                   1690:  *  - [ VC: ID Attribute Default ]
                   1691:  *
                   1692:  * The ID/IDREF uniqueness and matching are done separately
                   1693:  *
                   1694:  * returns 1 if valid or 0 otherwise
                   1695:  */
                   1696: 
                   1697: int
                   1698: xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
                   1699:                          xmlAttributePtr attr) {
1.16      daniel   1700:     int ret = 1;
                   1701:     int val;
1.14      daniel   1702:     CHECK_DTD;
1.16      daniel   1703:     if(attr == NULL) return(1);
                   1704:     
                   1705:     /* Attribute Default Legal */
                   1706:     /* Enumeration */
                   1707:     if (attr->defaultValue != NULL) {
                   1708:        val = xmlValidateAttributeValue(attr->type, attr->defaultValue);
                   1709:        if (val == 0) {
                   1710:            VERROR(ctxt->userData, 
                   1711:               "Syntax of default value for attribute %s on %s is not valid\n",
                   1712:                   attr->name, attr->elem);
                   1713:        }
                   1714:         ret &= val;
                   1715:     }
                   1716: 
                   1717:     /* ID Attribute Default */
                   1718:     if ((attr->type == XML_ATTRIBUTE_ID)&&
                   1719:         (attr->def != XML_ATTRIBUTE_IMPLIED) &&
                   1720:        (attr->def != XML_ATTRIBUTE_REQUIRED)) {
                   1721:        VERROR(ctxt->userData, 
                   1722:           "ID attribute %s on %s is not valid must be #IMPLIED or #REQUIRED\n",
                   1723:               attr->name, attr->elem);
                   1724:        ret = 0;
                   1725:     }
                   1726: 
                   1727:     /* max ID per element */
                   1728:     if ((attr->type == XML_ATTRIBUTE_ID) && (doc->extSubset != NULL)) {
                   1729:         int nbId = 0;
                   1730: 
                   1731:        /* the trick is taht we parse DtD as their own internal subset */
                   1732:         xmlElementPtr elem = xmlGetDtdElementDesc(doc->extSubset,
                   1733:                                                  attr->elem);
                   1734:        if (elem != NULL) {
                   1735:            nbId = xmlScanIDAttributeDecl(NULL, elem);
                   1736:        }
                   1737:        if (nbId >= 1)
                   1738:            VERROR(ctxt->userData, 
                   1739:           "Element %s has ID attribute defined in the external subset : %s\n",
                   1740:                   attr->elem, attr->name);
                   1741:     }
1.14      daniel   1742: 
1.16      daniel   1743:     return(ret);
1.14      daniel   1744: }
                   1745: 
                   1746: /**
                   1747:  * xmlValidateElementDecl:
                   1748:  * @ctxt:  the validation context
                   1749:  * @doc:  a document instance
                   1750:  * @elem:  an element definition
                   1751:  *
                   1752:  * Try to validate a single element definition
                   1753:  * basically it does the following checks as described by the
                   1754:  * XML-1.0 recommendation:
                   1755:  *  - [ VC: One ID per Element Type ]
                   1756:  *  - [ VC: No Duplicate Types ]
                   1757:  *  - [ VC: Unique Element Type Declaration ]
                   1758:  *
                   1759:  * returns 1 if valid or 0 otherwise
                   1760:  */
                   1761: 
                   1762: int
1.16      daniel   1763: xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
                   1764:                        xmlElementPtr elem) {
                   1765:     int ret = 1;
                   1766:     xmlElementPtr tst;
                   1767: 
1.14      daniel   1768:     CHECK_DTD;
1.16      daniel   1769:     
                   1770:     if (elem == NULL) return(1);
1.14      daniel   1771: 
1.16      daniel   1772:     /* No Duplicate Types */
                   1773:     if (elem->type == XML_ELEMENT_TYPE_MIXED) {
                   1774:        xmlElementContentPtr cur, next;
                   1775:         const CHAR *name;
                   1776: 
                   1777:        cur = elem->content;
                   1778:        while (cur != NULL) {
                   1779:            if (cur->type != XML_ELEMENT_CONTENT_OR) break;
                   1780:            if (cur->c1 == NULL) break;
                   1781:            if (cur->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
                   1782:                name = cur->c1->name;
                   1783:                next = cur->c2;
                   1784:                while (next != NULL) {
                   1785:                    if (next->type == XML_ELEMENT_CONTENT_ELEMENT) {
                   1786:                        if (!xmlStrcmp(next->name, name)) {
                   1787:                            VERROR(ctxt->userData, 
                   1788:                   "Definition of %s has duplicate references of %s\n",
                   1789:                                   elem->name, name);
                   1790:                            ret = 0;
                   1791:                        }
                   1792:                        break;
                   1793:                    }
                   1794:                    if (next->c1 == NULL) break;
                   1795:                    if (next->c1->type != XML_ELEMENT_CONTENT_ELEMENT) break;
                   1796:                    if (!xmlStrcmp(next->c1->name, name)) {
                   1797:                        VERROR(ctxt->userData, 
                   1798:               "Definition of %s has duplicate references of %s\n",
                   1799:                               elem->name, name);
                   1800:                        ret = 0;
                   1801:                    }
                   1802:                    next = next->c2;
                   1803:                }
                   1804:            }
                   1805:            cur = cur->c2;
                   1806:        }
                   1807:     }
                   1808: 
                   1809:     /* VC: Unique Element Type Declaration */
                   1810:     tst = xmlGetDtdElementDesc(doc->intSubset, elem->name);
                   1811:     if ((tst != NULL ) && (tst != elem)) {
                   1812:        VERROR(ctxt->userData, "Redefinition of element %s\n",
                   1813:               elem->name);
                   1814:        ret = 0;
                   1815:     }
                   1816:     tst = xmlGetDtdElementDesc(doc->extSubset, elem->name);
                   1817:     if ((tst != NULL ) && (tst != elem)) {
                   1818:        VERROR(ctxt->userData, "Redefinition of element %s\n",
                   1819:               elem->name);
                   1820:        ret = 0;
                   1821:     }
                   1822: 
                   1823:     /* One ID per Element Type */
                   1824:     if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
                   1825:        ret = 0;
                   1826:     }
                   1827:     return(ret);
1.14      daniel   1828: }
                   1829: 
                   1830: /**
                   1831:  * xmlValidateOneAttribute:
                   1832:  * @ctxt:  the validation context
                   1833:  * @doc:  a document instance
                   1834:  * @elem:  an element instance
                   1835:  * @attr:  an attribute instance
                   1836:  *
                   1837:  * Try to validate a single attribute for an element
                   1838:  * basically it * does the following checks as described by the
                   1839:  * XML-1.0 recommendation:
1.18      daniel   1840:  *  - [ VC: Attribute Value Type ]
                   1841:  *  - [ VC: Fixed Attribute Default ]
1.14      daniel   1842:  *  - [ VC: Entity Name ]
                   1843:  *  - [ VC: Name Token ]
                   1844:  *  - [ VC: ID ]
                   1845:  *  - [ VC: IDREF ]
                   1846:  *  - [ VC: Entity Name ]
1.16      daniel   1847:  *  - [ VC: Notation Attributes ]
1.14      daniel   1848:  *
                   1849:  * The ID/IDREF uniqueness and matching are done separately
                   1850:  *
                   1851:  * returns 1 if valid or 0 otherwise
                   1852:  */
                   1853: 
                   1854: int
1.16      daniel   1855: xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
1.18      daniel   1856:                         xmlNodePtr elem, xmlAttrPtr attr, const CHAR *value) {
                   1857:     xmlElementPtr elemDecl;
                   1858:     xmlAttributePtr attrDecl;
                   1859:     int val;
                   1860:     int ret = 1;
                   1861: 
1.14      daniel   1862:     CHECK_DTD;
1.18      daniel   1863:     if ((elem == NULL) || (elem->name == NULL)) return(0);
                   1864:     if ((attr == NULL) || (attr->name == NULL)) return(0);
                   1865: 
                   1866:     attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name);
                   1867:     if ((attrDecl == NULL) && (doc->extSubset != NULL))
                   1868:        attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, attr->name);
                   1869: 
1.14      daniel   1870: 
1.18      daniel   1871:     /* Validity Constraint: Attribute Value Type */
                   1872:     if (attrDecl == NULL) {
                   1873:        VERROR(ctxt->userData,
                   1874:               "No declaration for attribute %s on element %s\n",
                   1875:               attr->name, elem->name);
                   1876:        return(0);
                   1877:     }
                   1878:     val = xmlValidateAttributeValue(attrDecl->type, value);
                   1879:     if (val == 0) {
                   1880:        VERROR(ctxt->userData, 
                   1881:           "Syntax of value for attribute %s on %s is not valid\n",
                   1882:               attr->name, elem->name);
                   1883:         ret = 0;
                   1884:     }
                   1885: 
                   1886:     /* Validity Constraint: Notation Attributes */
                   1887:     if (attrDecl->type == XML_ATTRIBUTE_NOTATION) {
                   1888:         xmlEnumerationPtr tree = attrDecl->tree;
                   1889:         xmlNotationPtr nota;
                   1890: 
                   1891:         /* First check that the given NOTATION was declared */
                   1892:        nota = xmlGetDtdNotationDesc(doc->intSubset, value);
                   1893:        if (nota == NULL)
                   1894:            nota = xmlGetDtdNotationDesc(doc->extSubset, value);
                   1895:        
                   1896:        if (nota == NULL) {
                   1897:            VERROR(ctxt->userData, 
                   1898:        "Value \"%s\" for attribute %s on %s is not a declared Notation\n",
                   1899:                   value, attr->name, elem->name);
                   1900:            ret = 0;
                   1901:         }
                   1902: 
                   1903:        /* Second, verify that it's among the list */
                   1904:        while (tree != NULL) {
                   1905:            if (!xmlStrcmp(tree->name, value)) break;
                   1906:            tree = tree->next;
                   1907:        }
                   1908:        if (tree == NULL) {
                   1909:            VERROR(ctxt->userData, 
                   1910:    "Value \"%s\" for attribute %s on %s is among the enumerated notations\n",
                   1911:                   value, attr->name, elem->name);
                   1912:            ret = 0;
                   1913:        }
                   1914:     }
                   1915: 
                   1916:     /* Validity Constraint: Enumeration */
                   1917:     if (attrDecl->type == XML_ATTRIBUTE_ENUMERATION) {
                   1918:         xmlEnumerationPtr tree = attrDecl->tree;
                   1919:        while (tree != NULL) {
                   1920:            if (!xmlStrcmp(tree->name, value)) break;
                   1921:            tree = tree->next;
                   1922:        }
                   1923:        if (tree == NULL) {
                   1924:            VERROR(ctxt->userData, 
                   1925:        "Value \"%s\" for attribute %s on %s is among the enumerated set\n",
                   1926:                   value, attr->name, elem->name);
                   1927:            ret = 0;
                   1928:        }
                   1929:     }
                   1930: 
                   1931:     /* Fixed Attribute Default */
                   1932:     if ((attrDecl->def == XML_ATTRIBUTE_FIXED) &&
                   1933:         (xmlStrcmp(attrDecl->defaultValue, value))) {
                   1934:        VERROR(ctxt->userData, 
                   1935:           "Value for attribute %s on %s must be \"%s\"\n",
                   1936:               attr->name, elem->name, attrDecl->defaultValue);
                   1937:         ret = 0;
                   1938:     }
                   1939: 
                   1940:     elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name);
                   1941:     if ((elemDecl == NULL) && (doc->extSubset != NULL))
                   1942:        elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name);
                   1943:     if (elemDecl == NULL) {
                   1944:        /* the error has or will be reported soon in xmlValidateOneElement */
                   1945:        return(0);
                   1946:     }
                   1947:     return(ret);
                   1948: }
                   1949: 
                   1950: int xmlValidateElementTypeElement(xmlValidCtxtPtr ctxt, xmlNodePtr *child,
                   1951:                                  xmlElementContentPtr cont);
                   1952: 
                   1953: /**
                   1954:  * xmlValidateElementTypeExpr:
                   1955:  * @ctxt:  the validation context
                   1956:  * @child:  pointer to the child list
                   1957:  * @cont:  pointer to the content declaration
                   1958:  *
                   1959:  * Try to validate the content of an element of type element
                   1960:  * but don't handle the occurence factor
                   1961:  *
                   1962:  * returns 1 if valid or 0 and -1 if PCDATA stuff is found,
                   1963:  *         also update child value in-situ.
                   1964:  */
                   1965: 
                   1966: int
                   1967: xmlValidateElementTypeExpr(xmlValidCtxtPtr ctxt, xmlNodePtr *child,
                   1968:                           xmlElementContentPtr cont) {
                   1969:     xmlNodePtr cur;
                   1970:     int ret = 1;
                   1971: 
                   1972:     if (cont == NULL) return(-1);
                   1973:     while (*child != NULL) {
                   1974:         if ((*child)->type == XML_PI_NODE) {
                   1975:            *child = (*child)->next;
                   1976:            continue;
                   1977:        }
                   1978:         if ((*child)->type == XML_COMMENT_NODE) {
                   1979:            *child = (*child)->next;
                   1980:            continue;
                   1981:        }
                   1982:        else if ((*child)->type != XML_ELEMENT_NODE) {
                   1983:            return(-1);
                   1984:        }
                   1985:        break;
                   1986:     }
                   1987:     switch (cont->type) {
                   1988:        case XML_ELEMENT_CONTENT_PCDATA:
                   1989:            /* Internal error !!! */
                   1990:            fprintf(stderr, "Internal: MIXED struct bad\n");
                   1991:            return(-1);
                   1992:        case XML_ELEMENT_CONTENT_ELEMENT:
1.20    ! daniel   1993:            if (*child == NULL) return(0);
1.18      daniel   1994:            ret = (!xmlStrcmp((*child)->name, cont->name));
                   1995:            if (ret == 1)
                   1996:                *child = (*child)->next;
                   1997:            return(ret);
                   1998:        case XML_ELEMENT_CONTENT_OR:
                   1999:            cur = *child;
                   2000:            ret = xmlValidateElementTypeElement(ctxt, child, cont->c1);
                   2001:            if (ret == -1) return(-1);
                   2002:            if (ret == 1) {
                   2003:                 return(1);
                   2004:            }
                   2005:            /* rollback and retry the other path */
                   2006:            *child = cur;
                   2007:            ret = xmlValidateElementTypeElement(ctxt, child, cont->c2);
                   2008:            if (ret == -1) return(-1);
                   2009:            if (ret == 0) {
                   2010:                *child = cur;
                   2011:                return(0);
                   2012:            }
                   2013:            return(1);
                   2014:        case XML_ELEMENT_CONTENT_SEQ:
                   2015:            cur = *child;
                   2016:            ret = xmlValidateElementTypeElement(ctxt, child, cont->c1);
                   2017:            if (ret == -1) return(-1);
                   2018:            if (ret == 0) {
                   2019:                *child = cur;
                   2020:                return(0);
                   2021:            }
                   2022:            ret = xmlValidateElementTypeElement(ctxt, child, cont->c2);
                   2023:            if (ret == -1) return(-1);
                   2024:            if (ret == 0) {
                   2025:                *child = cur;
                   2026:                return(0);
                   2027:            }
                   2028:            return(1);
                   2029:     }
                   2030:     return(ret);
                   2031: }
                   2032: 
                   2033: /**
                   2034:  * xmlValidateElementTypeElement:
                   2035:  * @ctxt:  the validation context
                   2036:  * @child:  pointer to the child list
                   2037:  * @cont:  pointer to the content declaration
                   2038:  *
                   2039:  * Try to validate the content of an element of type element
                   2040:  * yeah, Yet Another Regexp Implementation, and recursive
                   2041:  *
                   2042:  * returns 1 if valid or 0 and -1 if PCDATA stuff is found,
                   2043:  *         also update child and content values in-situ.
                   2044:  */
                   2045: 
                   2046: int
                   2047: xmlValidateElementTypeElement(xmlValidCtxtPtr ctxt, xmlNodePtr *child,
                   2048:                              xmlElementContentPtr cont) {
                   2049:     xmlNodePtr cur;
                   2050:     int ret = 1;
                   2051: 
                   2052:     if (cont == NULL) return(-1);
                   2053:     while (*child != NULL) {
                   2054:         if ((*child)->type == XML_PI_NODE) {
                   2055:            *child = (*child)->next;
                   2056:            continue;
                   2057:        }
                   2058:         if ((*child)->type == XML_COMMENT_NODE) {
                   2059:            *child = (*child)->next;
                   2060:            continue;
                   2061:        }
                   2062:        else if ((*child)->type != XML_ELEMENT_NODE) {
                   2063:            return(-1);
                   2064:        }
                   2065:        break;
                   2066:     }
                   2067:     cur = *child;
                   2068:     ret = xmlValidateElementTypeExpr(ctxt, child, cont);
                   2069:     if (ret == -1) return(-1);
                   2070:     switch (cont->ocur) {
                   2071:        case XML_ELEMENT_CONTENT_ONCE:
                   2072:            if (ret == 1) {
                   2073:                return(1);
                   2074:            }
                   2075:            *child = cur;
                   2076:            return(0);
                   2077:        case XML_ELEMENT_CONTENT_OPT:
                   2078:            if (ret == 0) {
                   2079:                *child = cur;
                   2080:                return(1);
                   2081:            }
1.19      daniel   2082:            break;
1.18      daniel   2083:        case XML_ELEMENT_CONTENT_MULT:
                   2084:            if (ret == 0) {
                   2085:                *child = cur;
1.19      daniel   2086:                break;
1.18      daniel   2087:            }
                   2088:            /* no break on purpose */
                   2089:        case XML_ELEMENT_CONTENT_PLUS:
                   2090:            if (ret == 0) {
                   2091:                *child = cur;
                   2092:                return(0);
                   2093:            }
                   2094:            do {
                   2095:                cur = *child;
                   2096:                ret = xmlValidateElementTypeExpr(ctxt, child, cont);
                   2097:            } while (ret == 1);
                   2098:            if (ret == -1) return(-1);
                   2099:            *child = cur;
1.19      daniel   2100:            break;
                   2101:     }
                   2102:     while (*child != NULL) {
                   2103:         if ((*child)->type == XML_PI_NODE) {
                   2104:            *child = (*child)->next;
                   2105:            continue;
                   2106:        }
                   2107:         if ((*child)->type == XML_COMMENT_NODE) {
                   2108:            *child = (*child)->next;
                   2109:            continue;
                   2110:        }
                   2111:        else if ((*child)->type != XML_ELEMENT_NODE) {
                   2112:            return(-1);
                   2113:        }
                   2114:        break;
                   2115:     }
                   2116:     return(1);
                   2117: }
                   2118: 
                   2119: /**
                   2120:  * xmlSprintfElementChilds:
                   2121:  * @buf:  an output buffer
                   2122:  * @content:  An element
                   2123:  * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
                   2124:  *
                   2125:  * This will dump the list of childs to the buffer
                   2126:  * Intended just for the debug routine
                   2127:  */
                   2128: void
                   2129: xmlSprintfElementChilds(char *buf, xmlNodePtr node, int glob) {
                   2130:     xmlNodePtr cur;
                   2131: 
                   2132:     if (node == NULL) return;
                   2133:     if (glob) strcat(buf, "(");
                   2134:     cur = node->childs;
                   2135:     while (cur != NULL) {
                   2136:         switch (cur->type) {
                   2137:             case XML_ELEMENT_NODE:
                   2138:                 strcat(buf, cur->name);
                   2139:                 if (cur->next != NULL)
                   2140:                     strcat(buf, " ");
                   2141:                 break;
                   2142:             case XML_TEXT_NODE:
                   2143:             case XML_CDATA_SECTION_NODE:
                   2144:             case XML_ENTITY_REF_NODE:
                   2145:                 strcat(buf, "CDATA");
                   2146:                 if (cur->next != NULL)
                   2147:                     strcat(buf, " ");
                   2148:                 break;
                   2149:             case XML_ATTRIBUTE_NODE:
                   2150:             case XML_DOCUMENT_NODE:
                   2151:             case XML_DOCUMENT_TYPE_NODE:
                   2152:             case XML_DOCUMENT_FRAG_NODE:
                   2153:             case XML_NOTATION_NODE:
                   2154:                 strcat(buf, "???");
                   2155:                 if (cur->next != NULL)
                   2156:                     strcat(buf, " ");
                   2157:                 break;
                   2158:             case XML_ENTITY_NODE:
                   2159:             case XML_PI_NODE:
                   2160:             case XML_COMMENT_NODE:
                   2161:                 break;
                   2162:        }
                   2163:        cur = cur->next;
1.18      daniel   2164:     }
1.19      daniel   2165:     if (glob) strcat(buf, ")");
1.14      daniel   2166: }
                   2167: 
1.19      daniel   2168: 
1.14      daniel   2169: /**
                   2170:  * xmlValidateOneElement:
                   2171:  * @ctxt:  the validation context
                   2172:  * @doc:  a document instance
                   2173:  * @elem:  an element instance
                   2174:  *
                   2175:  * Try to validate a single element and it's attributes,
                   2176:  * basically it does the following checks as described by the
                   2177:  * XML-1.0 recommendation:
                   2178:  *  - [ VC: Element Valid ]
                   2179:  *  - [ VC: Required Attribute ]
                   2180:  * Then call xmlValidateOneAttribute() for each attribute present.
                   2181:  *
                   2182:  * The ID/IDREF checkings are done separately
                   2183:  *
                   2184:  * returns 1 if valid or 0 otherwise
                   2185:  */
                   2186: 
                   2187: int
1.16      daniel   2188: xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
1.18      daniel   2189:                       xmlNodePtr elem) {
                   2190:     xmlElementPtr elemDecl;
                   2191:     xmlElementContentPtr cont;
                   2192:     xmlNodePtr child;
                   2193:     int ret = 1;
                   2194:     const CHAR *name;
                   2195: 
1.14      daniel   2196:     CHECK_DTD;
                   2197: 
1.18      daniel   2198:     if ((elem == NULL) || (elem->name == NULL)) return(0);
                   2199: 
                   2200:     elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name);
                   2201:     if ((elemDecl == NULL) && (doc->extSubset != NULL))
                   2202:        elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name);
                   2203:     if (elemDecl == NULL) {
                   2204:        VERROR(ctxt->userData, "No declaration for element %s\n",
                   2205:               elem->name);
                   2206:        return(0);
                   2207:     }
                   2208: 
                   2209:     /* Check taht the element content matches the definition */
                   2210:     switch (elemDecl->type) {
                   2211:         case XML_ELEMENT_TYPE_EMPTY:
                   2212:            if (elem->childs != NULL) {
                   2213:                VERROR(ctxt->userData,
                   2214:               "Element %s was declared EMPTY this one has content\n",
                   2215:                       elem->name);
                   2216:                ret = 0;
                   2217:            }
                   2218:            break;
                   2219:         case XML_ELEMENT_TYPE_ANY:
                   2220:            /* I don't think anything is required then */
                   2221:            break;
                   2222:         case XML_ELEMENT_TYPE_MIXED:
                   2223:            /* Hum, this start to get messy */
                   2224:            child = elem->childs;
                   2225:            while (child != NULL) {
                   2226:                if (child->type == XML_ELEMENT_NODE) {
                   2227:                    name = child->name;
                   2228:                    cont = elemDecl->content;
                   2229:                    while (cont != NULL) {
                   2230:                        if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
                   2231:                            if (!xmlStrcmp(cont->name, name)) break;
                   2232:                        } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
                   2233:                           (cont->c1 != NULL) &&
                   2234:                           (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)) {
                   2235:                            if (!xmlStrcmp(cont->c1->name, name)) break;
                   2236:                        } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
                   2237:                            (cont->c1 == NULL) ||
                   2238:                            (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)) {
                   2239:                            /* Internal error !!! */
                   2240:                            fprintf(stderr, "Internal: MIXED struct bad\n");
                   2241:                            break;
                   2242:                        }
                   2243:                        cont = cont->c2;
                   2244:                    }
                   2245:                    if (cont == NULL) {
                   2246:                        VERROR(ctxt->userData,
                   2247:               "Element %s is not declared in %s list of possible childs\n",
                   2248:                               name, elem->name);
                   2249:                        ret = 0;
                   2250:                    }
                   2251:                }
                   2252:                child = child->next;
                   2253:            }
                   2254:            break;
                   2255:         case XML_ELEMENT_TYPE_ELEMENT:
                   2256:            child = elem->childs;
                   2257:            cont = elemDecl->content;
                   2258:            ret = xmlValidateElementTypeElement(ctxt, &child, cont);
1.19      daniel   2259:            if ((ret == 0) || (child != NULL)) {
                   2260:                char expr[1000];
                   2261:                char list[2000];
                   2262: 
                   2263:                expr[0] = 0;
                   2264:                xmlSprintfElementContent(expr, cont, 1);
                   2265:                list[0] = 0;
                   2266:                xmlSprintfElementChilds(list, elem, 1);
                   2267: 
1.18      daniel   2268:                VERROR(ctxt->userData,
1.19      daniel   2269:           "Element %s content doesn't follow the Dtd\nExpecting %s, got %s\n",
                   2270:                       elem->name, expr, list);
1.18      daniel   2271:                ret = 0;
                   2272:            }
                   2273:            break;
                   2274:     }
                   2275: 
                   2276:     return(ret);
1.14      daniel   2277: }
                   2278: 
                   2279: /**
                   2280:  * xmlValidateRoot:
                   2281:  * @ctxt:  the validation context
                   2282:  * @doc:  a document instance
                   2283:  *
                   2284:  * Try to validate a the root element
                   2285:  * basically it does the following check as described by the
                   2286:  * XML-1.0 recommendation:
                   2287:  *  - [ VC: Root Element Type ]
                   2288:  * it doesn't try to recurse or apply other check to the element
                   2289:  *
                   2290:  * returns 1 if valid or 0 otherwise
                   2291:  */
                   2292: 
                   2293: int
                   2294: xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
                   2295:     if (doc == NULL) return(0);
                   2296: 
                   2297:     if ((doc->intSubset == NULL) ||
                   2298:        (doc->intSubset->name == NULL)) {
                   2299:        VERROR(ctxt->userData, "Not valid: no DtD found\n");
                   2300:         return(0);
                   2301:     }
                   2302:     if ((doc->root == NULL) || (doc->root->name == NULL)) {
                   2303:        VERROR(ctxt->userData, "Not valid: no root element\n");
                   2304:         return(0);
                   2305:     }
                   2306:     if (xmlStrcmp(doc->intSubset->name, doc->root->name)) {
                   2307:        VERROR(ctxt->userData,
                   2308:               "Not valid: root and DtD name do not match %s and %s\n",
                   2309:               doc->root->name, doc->intSubset->name);
                   2310:        return(0);
                   2311:     }
                   2312:     return(1);
                   2313: }
                   2314: 
                   2315: 
                   2316: /**
                   2317:  * xmlValidateElement:
                   2318:  * @ctxt:  the validation context
                   2319:  * @doc:  a document instance
                   2320:  * @elem:  an element instance
                   2321:  *
                   2322:  * Try to validate the subtree under an element 
                   2323:  *
                   2324:  * returns 1 if valid or 0 otherwise
                   2325:  */
                   2326: 
                   2327: int
1.18      daniel   2328: xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem) {
1.14      daniel   2329:     CHECK_DTD;
                   2330: 
                   2331:     return(1);
                   2332: }
                   2333: 
                   2334: /**
                   2335:  * xmlValidateDtd:
                   2336:  * @ctxt:  the validation context
                   2337:  * @doc:  a document instance
                   2338:  * @dtd:  a dtd instance
                   2339:  *
                   2340:  * Try to validate the dtd instance
                   2341:  *
                   2342:  * basically it does check all the definitions in the DtD.
                   2343:  *
                   2344:  * returns 1 if valid or 0 otherwise
                   2345:  */
                   2346: 
                   2347: int
                   2348: xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
                   2349:     return(1);
                   2350: }
                   2351: 
                   2352: /**
                   2353:  * xmlValidateDocument:
                   2354:  * @ctxt:  the validation context
                   2355:  * @doc:  a document instance
                   2356:  *
                   2357:  * Try to validate the document instance
                   2358:  *
                   2359:  * basically it does the all the checks described by the
                   2360:  * i.e. validates the internal and external subset (if present)
                   2361:  * and validate the document tree.
                   2362:  *
                   2363:  * returns 1 if valid or 0 otherwise
                   2364:  */
                   2365: 
                   2366: int
                   2367: xmlValidateDocument(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
                   2368:     if (!xmlValidateRoot(ctxt, doc)) return(0);
                   2369: 
                   2370:     return(1);
                   2371: }
                   2372: 

Webmaster