On Thu, Jan 10, 2008 at 02:53:20PM +0530, Ashwin wrote:
> > I will look at this probably tomorrow morning,
>
> How about adding this check in function xmlHashAddEntry3:-
>
>
> If (insert != NULL)
>
> entry->payload = userdata;
>
>
> This check will ensure that in case of duplicate entries the type
> remains the original one instead the latest one.
That doesn't work, on the given example there is only one
special attribute defined and that's the second one, you won't
even get a duplicate in ctxt->attsSpecial . Also I really don't
want to change the semantic of public API, that's impossible.
I have made a proper patch for this. There is no way around
callecting all attribute type definitions at the parser ctxt
level, I did this in the DTD parsing phase using ctxt->attsSpecial,
then xmlAddSpecialAttr is modified to always keep only the first
entry, then when the DTD parsing for the document is done,
all CDATA attributes are removed from ctxt->attsSpecial.
This last step is done at 3 places in the code 1 for the normal
parsing and 2 for the push parser which operates differently.
This also required to fix the Hash table scanner to not crash
in some case of hashed element removal in the scanner callback.
Patch enclosed has been tested on various tests, and looks fine to
me so I commited it in revision 3669.
thanks for the report,
Daniel
--
Red Hat Virtualization group http://redhat.com/virtualization/
Daniel Veillard | virtualization library http://libvirt.org/
[EMAIL PROTECTED] | libxml GNOME XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/
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
_______________________________________________
xml mailing list, project page http://xmlsoft.org/
[email protected]
http://mail.gnome.org/mailman/listinfo/xml