Index: hash.c =================================================================== --- hash.c (revision 3667) +++ hash.c (working copy) @@ -828,7 +828,7 @@ */ void xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) { - int i; + int i, nb; xmlHashEntryPtr iter; xmlHashEntryPtr next; @@ -844,10 +844,21 @@ iter = &(table->table[i]); while (iter) { next = iter->next; + nb = table->nbElems; if ((f != NULL) && (iter->payload != NULL)) f(iter->payload, data, iter->name, iter->name2, iter->name3); - iter = next; + if (nb != table->nbElems) { + /* table was modified by the callback, be careful */ + if (iter == &(table->table[i])) { + if (table->table[i].valid == 0) + iter = NULL; + if (table->table[i].next != next) + iter = &(table->table[i]); + } else + iter = next; + } else + iter = next; } } } Index: parser.c =================================================================== --- parser.c (revision 3667) +++ parser.c (working copy) @@ -957,7 +957,7 @@ * @fullattr: the attribute fullname * @type: the attribute type * - * Register that this attribute is not CDATA + * Register this attribute type */ static void xmlAddSpecialAttr(xmlParserCtxtPtr ctxt, @@ -971,6 +971,9 @@ goto mem_error; } + if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL) + return; + xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr, (void *) (long) type); return; @@ -981,6 +984,45 @@ } /** + * xmlCleanSpecialAttrCallback: + * + * Removes CDATA attributes from the special attribute table + */ +static void +xmlCleanSpecialAttrCallback(void *payload, void *data, + const xmlChar *fullname, const xmlChar *fullattr, + const xmlChar *unused ATTRIBUTE_UNUSED) { + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data; + + if (((int) payload) == XML_ATTRIBUTE_CDATA) { + xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL); + } +} + +/** + * xmlCleanSpecialAttr: + * @ctxt: an XML parser context + * + * Trim the list of attributes defined to remove all those of type + * CDATA as they are not special. This call should be done when finishing + * to parse the DTD and before starting to parse the document root. + */ +static void +xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt) +{ + if (ctxt->attsSpecial == NULL) + return; + + xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt); + + if (xmlHashSize(ctxt->attsSpecial) == 0) { + xmlHashFree(ctxt->attsSpecial, NULL); + ctxt->attsSpecial = NULL; + } + return; +} + +/** * xmlCheckLanguageID: * @lang: pointer to the string value * @@ -5006,7 +5048,7 @@ (def != XML_ATTRIBUTE_REQUIRED)) { xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue); } - if ((ctxt->sax2) && (type != XML_ATTRIBUTE_CDATA)) { + if (ctxt->sax2) { xmlAddSpecialAttr(ctxt, elemName, attrName, type); } if (defaultValue != NULL) @@ -9245,6 +9287,7 @@ ctxt->extSubSystem, ctxt->extSubURI); ctxt->inSubset = 0; + xmlCleanSpecialAttr(ctxt); ctxt->instate = XML_PARSER_PROLOG; xmlParseMisc(ctxt); @@ -10208,6 +10251,7 @@ ctxt->intSubName, ctxt->extSubSystem, ctxt->extSubURI); ctxt->inSubset = 0; + xmlCleanSpecialAttr(ctxt); ctxt->instate = XML_PARSER_PROLOG; #ifdef DEBUG_PUSH xmlGenericError(xmlGenericErrorContext, @@ -10435,6 +10479,7 @@ ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName, ctxt->extSubSystem, ctxt->extSubURI); ctxt->inSubset = 0; + xmlCleanSpecialAttr(ctxt); ctxt->instate = XML_PARSER_PROLOG; ctxt->checkIndex = 0; #ifdef DEBUG_PUSH