diff --git a/include/libxml/valid.h b/include/libxml/valid.h index 10d6d190..abef788b 100644 --- a/include/libxml/valid.h +++ b/include/libxml/valid.h @@ -255,11 +255,8 @@ XMLPUBFUN void /* IDs */ XMLPUBFUN int - xmlAddIDSafe (xmlDocPtr doc, - const xmlChar *value, - xmlAttrPtr attr, - int streaming, - xmlIDPtr *id); + xmlAddIDSafe (xmlAttrPtr attr, + const xmlChar *value); XMLPUBFUN xmlIDPtr xmlAddID (xmlValidCtxtPtr ctxt, xmlDocPtr doc, diff --git a/tree.c b/tree.c index 2e8a5dff..1f689814 100644 --- a/tree.c +++ b/tree.c @@ -1817,7 +1817,7 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, if ((value != NULL) && (node != NULL) && (xmlIsID(node->doc, node, cur) == 1) && - (xmlAddIDSafe(node->doc, value, cur, 0, NULL) < 0)) + (xmlAddIDSafe(cur, value) < 0)) goto error; /* @@ -4018,7 +4018,7 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { id = xmlNodeListGetString(cur->doc, cur->children, 1); if (id == NULL) goto error; - res = xmlAddIDSafe(target->doc, id, ret, 0, NULL); + res = xmlAddIDSafe(ret, id); xmlFree(id); if (res < 0) goto error; @@ -6911,7 +6911,7 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, } } if ((prop->atype == XML_ATTRIBUTE_ID) && - (xmlAddIDSafe(node->doc, value, prop, 0, NULL) < 0)) { + (xmlAddIDSafe(prop, value) < 0)) { return(NULL); } return(prop); @@ -9633,8 +9633,7 @@ end_ns_reference: idVal = xmlNodeListGetString(cur->doc, cur->children, 1); if (idVal != NULL) { - if (xmlAddIDSafe(destDoc, idVal, (xmlAttrPtr) cur, 0, - NULL) < 0) { + if (xmlAddIDSafe((xmlAttrPtr) cur, idVal) < 0) { /* TODO: error message. */ xmlFree(idVal); goto internal_error; diff --git a/valid.c b/valid.c index ada36a66..76dd812c 100644 --- a/valid.c +++ b/valid.c @@ -2280,35 +2280,36 @@ xmlFreeID(xmlIDPtr id) { /** - * xmlAddIDSafe: - * @doc: pointer to the document - * @value: the value name + * xmlAddIDInternal: * @attr: the attribute holding the ID - * @id: pointer to new xmlIdPtr (optional) + * @value: the attribute (ID) value + * @idPtr: pointer to resulting ID * * Register a new id declaration * * Returns 1 on success, 0 if the ID already exists, -1 if a memory * allocation fails. */ -int -xmlAddIDSafe(xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr, - int streaming, xmlIDPtr *id) { - xmlIDPtr ret; +static int +xmlAddIDInternal(xmlAttrPtr attr, const xmlChar *value, xmlIDPtr *idPtr) { + xmlDocPtr doc; + xmlIDPtr id; xmlIDTablePtr table; + int ret; - if (id != NULL) - *id = NULL; - - if (doc == NULL) { - return(-1); - } - if ((value == NULL) || (value[0] == 0)) { + if (idPtr != NULL) + *idPtr = NULL; + if ((value == NULL) || (value[0] == 0)) return(0); - } - if (attr == NULL) { - return(-1); - } + if (attr == NULL) + return(0); + + doc = attr->doc; + if (doc == NULL) + return(0); + + if (attr->id != NULL) + xmlRemoveID(doc, attr); /* * Create the ID table if needed. @@ -2319,69 +2320,63 @@ xmlAddIDSafe(xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr, if (table == NULL) return(-1); } else { - ret = xmlHashLookup(table, value); - if (ret != NULL) { - /* - * Update the attribute unless we are parsing in streaming - * mode. If the attribute is copied from an entity we want - * the ID reference the copy. - */ - if (ret->attr != NULL) { - ret->attr->id = NULL; - ret->attr = attr; - attr->id = ret; + id = xmlHashLookup(table, value); + if (id != NULL) { + if (id->attr != NULL) { + id->attr->id = NULL; + id->attr->atype = 0; } - ret->lineno = xmlGetLineNo(attr->parent); - attr->atype = XML_ATTRIBUTE_ID; - return(0); + ret = 0; + goto done; } } - ret = (xmlIDPtr) xmlMalloc(sizeof(xmlID)); - if (ret == NULL) + id = (xmlIDPtr) xmlMalloc(sizeof(xmlID)); + if (id == NULL) return(-1); - memset(ret, 0, sizeof(*ret)); + memset(id, 0, sizeof(*id)); /* * fill the structure. */ - ret->doc = doc; - ret->value = xmlStrdup(value); - if (ret->value == NULL) { - xmlFreeID(ret); + id->doc = doc; + id->value = xmlStrdup(value); + if (id->value == NULL) { + xmlFreeID(id); return(-1); } - if (streaming) { - /* - * Operating in streaming mode, attr is gonna disappear - */ - if (doc->dict != NULL) - ret->name = xmlDictLookup(doc->dict, attr->name, -1); - else - ret->name = xmlStrdup(attr->name); - if (ret->name == NULL) { - xmlFreeID(ret); - return(-1); - } - ret->attr = NULL; - } else { - ret->attr = attr; - ret->name = NULL; - } - ret->lineno = xmlGetLineNo(attr->parent); - if (xmlHashAddEntry(table, value, ret) < 0) { - xmlFreeID(ret); + if (xmlHashAddEntry(table, value, id) < 0) { + xmlFreeID(id); return(-1); } - attr->atype = XML_ATTRIBUTE_ID; - if (!streaming) - attr->id = ret; + ret = 1; + if (idPtr != NULL) + *idPtr = id; - if (id != NULL) - *id = ret; - return(1); +done: + id->attr = attr; + id->lineno = xmlGetLineNo(attr->parent); + attr->atype = XML_ATTRIBUTE_ID; + attr->id = id; + + return(ret); +} + +/** + * xmlAddIDSafe: + * @attr: the attribute holding the ID + * @value: the attribute (ID) value + * + * Register a new id declaration + * + * Returns 1 on success, 0 if the ID already exists, -1 if a memory + * allocation fails. + */ +int +xmlAddIDSafe(xmlAttrPtr attr, const xmlChar *value) { + return(xmlAddIDInternal(attr, value, NULL)); } /** @@ -2401,7 +2396,10 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlIDPtr id; int res; - res = xmlAddIDSafe(doc, value, attr, xmlIsStreaming(ctxt), &id); + if ((attr == NULL) || (doc != attr->doc)) + return(NULL); + + res = xmlAddIDInternal(attr, value, &id); if (res < 0) { xmlVErrMemory(ctxt); } diff --git a/xmlreader.c b/xmlreader.c index 02931245..f6e3ad21 100644 --- a/xmlreader.c +++ b/xmlreader.c @@ -222,7 +222,17 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) { if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children); - DICT_FREE(cur->name); + if (cur->id != NULL) { + /* + * Operating in streaming mode, attr is gonna disappear + */ + cur->id->attr = NULL; + cur->id->name = cur->name; + cur->name = NULL; + } else { + DICT_FREE(cur->name); + } + if ((reader != NULL) && (reader->ctxt != NULL) && (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) { cur->next = reader->ctxt->freeAttrs; diff --git a/xmlschemas.c b/xmlschemas.c index bca6b745..7c211f1f 100644 --- a/xmlschemas.c +++ b/xmlschemas.c @@ -5898,8 +5898,8 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) * NOTE: the IDness might have already be declared in the DTD */ if (attr->atype != XML_ATTRIBUTE_ID) { - xmlIDPtr res; xmlChar *strip; + int res; /* * TODO: Use xmlSchemaStrip here; it's not exported at this @@ -5910,8 +5910,10 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) xmlFree((xmlChar *) value); value = strip; } - res = xmlAddID(NULL, attr->doc, value, attr); - if (res == NULL) { + res = xmlAddIDSafe(attr, value); + if (res < 0) { + xmlSchemaPErrMemory(ctxt); + } else if (res == 0) { ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, @@ -5919,8 +5921,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), NULL, NULL, "Duplicate value '%s' of simple " "type 'xs:ID'", value, NULL); - } else - attr->atype = XML_ATTRIBUTE_ID; + } } } else if (ret > 0) { ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; diff --git a/xmlschemastypes.c b/xmlschemastypes.c index 0d42c9d5..60f3d37f 100644 --- a/xmlschemastypes.c +++ b/xmlschemastypes.c @@ -2964,19 +2964,19 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, * NOTE: the IDness might have already be declared in the DTD */ if (attr->atype != XML_ATTRIBUTE_ID) { - xmlIDPtr res; xmlChar *strip; + int res; strip = xmlSchemaStrip(value); if (strip != NULL) { - res = xmlAddID(NULL, node->doc, strip, attr); + res = xmlAddIDSafe(attr, strip); xmlFree(strip); } else - res = xmlAddID(NULL, node->doc, value, attr); - if (res == NULL) { + res = xmlAddIDSafe(attr, value); + if (res < 0) { + goto error; + } else if (res == 0) { ret = 2; - } else { - attr->atype = XML_ATTRIBUTE_ID; } } }