fixing a number of issues raised by xml:id but more generally related to
* SAX2.c tree.c valid.c: fixing a number of issues raised by xml:id
but more generally related to attributes and ID handling, fixes
#314358 among other things
Daniel
diff --git a/tree.c b/tree.c
index 1da8400..3031d50 100644
--- a/tree.c
+++ b/tree.c
@@ -297,6 +297,7 @@
*
* returns NULL if it is not a Qualified Name, otherwise, update len
* with the lenght in byte of the prefix and return a pointer
+ * to the start of the name without the prefix
*/
const xmlChar *
@@ -1723,80 +1724,87 @@
}
#endif /* LIBXML_TREE_ENABLED */
-static xmlAttrPtr xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
- const xmlChar *name, const xmlChar *value, int eatname) {
+static xmlAttrPtr
+xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
+ const xmlChar * name, const xmlChar * value,
+ int eatname)
+{
xmlAttrPtr cur;
xmlDocPtr doc = NULL;
if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
- if (eatname == 1)
- xmlFree((xmlChar *) name);
- return(NULL);
- }
+ if (eatname == 1)
+ xmlFree((xmlChar *) name);
+ return (NULL);
+ }
/*
* Allocate a new property and fill the fields.
*/
cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
if (cur == NULL) {
- if (eatname == 1)
- xmlFree((xmlChar *) name);
- xmlTreeErrMemory("building attribute");
- return(NULL);
+ if (eatname == 1)
+ xmlFree((xmlChar *) name);
+ xmlTreeErrMemory("building attribute");
+ return (NULL);
}
memset(cur, 0, sizeof(xmlAttr));
cur->type = XML_ATTRIBUTE_NODE;
- cur->parent = node;
+ cur->parent = node;
if (node != NULL) {
- doc = node->doc;
- cur->doc = doc;
+ doc = node->doc;
+ cur->doc = doc;
}
- cur->ns = ns;
+ cur->ns = ns;
- if (eatname == 0) {
- if ((doc != NULL) && (doc->dict != NULL))
- cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
- else
- cur->name = xmlStrdup(name);
- } else
- cur->name = name;
+ if (eatname == 0) {
+ if ((doc != NULL) && (doc->dict != NULL))
+ cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
+ else
+ cur->name = xmlStrdup(name);
+ } else
+ cur->name = name;
if (value != NULL) {
- xmlChar *buffer;
- xmlNodePtr tmp;
+ xmlChar *buffer;
+ xmlNodePtr tmp;
- buffer = xmlEncodeEntitiesReentrant(doc, value);
- cur->children = xmlStringGetNodeList(doc, buffer);
- cur->last = NULL;
- tmp = cur->children;
- while (tmp != NULL) {
- tmp->parent = (xmlNodePtr) cur;
- if (tmp->next == NULL)
- cur->last = tmp;
- tmp = tmp->next;
- }
- xmlFree(buffer);
- }
+ buffer = xmlEncodeEntitiesReentrant(doc, value);
+ cur->children = xmlStringGetNodeList(doc, buffer);
+ cur->last = NULL;
+ tmp = cur->children;
+ while (tmp != NULL) {
+ tmp->parent = (xmlNodePtr) cur;
+ if (tmp->next == NULL)
+ cur->last = tmp;
+ tmp = tmp->next;
+ }
+ xmlFree(buffer);
+ }
/*
* Add it at the end to preserve parsing order ...
*/
if (node != NULL) {
- if (node->properties == NULL) {
- node->properties = cur;
- } else {
- xmlAttrPtr prev = node->properties;
+ if (node->properties == NULL) {
+ node->properties = cur;
+ } else {
+ xmlAttrPtr prev = node->properties;
- while (prev->next != NULL) prev = prev->next;
- prev->next = cur;
- cur->prev = prev;
- }
+ while (prev->next != NULL)
+ prev = prev->next;
+ prev->next = cur;
+ cur->prev = prev;
+ }
}
+ if (xmlIsID((node == NULL) ? NULL : node->doc, node, cur) == 1)
+ xmlAddID(NULL, node->doc, value, cur);
+
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
- xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
- return(cur);
+ xmlRegisterNodeDefaultValue((xmlNodePtr) cur);
+ return (cur);
}
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
@@ -6316,16 +6324,36 @@
xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
xmlAttrPtr prop;
xmlDocPtr doc;
+ int len;
+ const xmlChar *nqname;
if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE))
return(NULL);
+
+ /*
+ * handle QNames
+ */
+ nqname = xmlSplitQName3(name, &len);
+ if (nqname != NULL) {
+ xmlNsPtr ns;
+ xmlChar *prefix = xmlStrndup(name, len);
+ ns = xmlSearchNs(node->doc, node, prefix);
+ if (prefix != NULL)
+ xmlFree(prefix);
+ if (ns != NULL)
+ return(xmlSetNsProp(node, ns, nqname, value));
+ }
+
doc = node->doc;
prop = node->properties;
while (prop != NULL) {
if ((xmlStrEqual(prop->name, name)) &&
(prop->ns == NULL)){
xmlNodePtr oldprop = prop->children;
+ int id = xmlIsID(node->doc, node, prop);
+ if (id == 1)
+ xmlRemoveID(node->doc, prop);
prop->children = NULL;
prop->last = NULL;
if (value != NULL) {
@@ -6348,6 +6376,8 @@
}
if (oldprop != NULL)
xmlFreeNodeList(oldprop);
+ if (id)
+ xmlAddID(NULL, node->doc, value, prop);
return(prop);
}
prop = prop->next;
@@ -6390,6 +6420,10 @@
*/
if ((xmlStrEqual(prop->name, name)) &&
(prop->ns != NULL) && (xmlStrEqual(prop->ns->href, ns->href))) {
+ int id = xmlIsID(node->doc, node, prop);
+
+ if (id == 1)
+ xmlRemoveID(node->doc, prop);
if (prop->children != NULL)
xmlFreeNodeList(prop->children);
prop->children = NULL;
@@ -6411,6 +6445,8 @@
}
xmlFree(buffer);
}
+ if (id)
+ xmlAddID(NULL, node->doc, value, prop);
return(prop);
}
prop = prop->next;