summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2002-01-24 16:05:41 +0000
committerDaniel Veillard <veillard@src.gnome.org>2002-01-24 16:05:41 +0000
commitbd227ae9dbdaf95cc594b57b5c5c82c9dc87227f (patch)
treed6b6920fe6e3902dccef546e301c7cd3990a27c6
parent3606581dcd45fbabfa95ce3565918d0c7e407633 (diff)
downloadlibxml2-bd227ae9dbdaf95cc594b57b5c5c82c9dc87227f.tar.gz
more fixes from Petr Kozelka for attribute handling in the tree API to
* tree.c: more fixes from Petr Kozelka for attribute handling in the tree API to align the semantic with DOM. Daniel
-rw-r--r--ChangeLog5
-rw-r--r--tree.c116
2 files changed, 103 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index d67a9c8e..1bfeac91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Jan 24 17:04:04 CET 2002 Daniel Veillard <daniel@veillard.com>
+
+ * tree.c: more fixes from Petr Kozelka for attribute handling
+ in the tree API to align the semantic with DOM.
+
Thu Jan 24 16:00:53 CET 2002 Daniel Veillard <daniel@veillard.com>
* valid.c tree.c entities.c: another set of patches from
diff --git a/tree.c b/tree.c
index 50a7e1ee..b4ebf8b0 100644
--- a/tree.c
+++ b/tree.c
@@ -1931,12 +1931,14 @@ xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
* @cur: the child node
* @elem: the new node
*
- * Add a new element @elem as the next siblings of @cur
- * If the new element was already inserted in a document it is
+ * Add a new node @elem as the next sibling of @cur
+ * If the new node was already inserted in a document it is
* first unlinked from its existing context.
* As a result of text merging @elem may be freed.
+ * If the new node is ATTRIBUTE, it is added into properties instead of children.
+ * If there is an attribute with equal name, it is first destroyed.
*
- * Returns the new element or NULL in case of error.
+ * Returns the new node or NULL in case of error.
*/
xmlNodePtr
xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
@@ -1984,6 +1986,18 @@ xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
xmlFreeNode(elem);
return(cur->next);
}
+ } else if (elem->type == XML_ATTRIBUTE_NODE) {
+ /* check if an attribute with the same name exists */
+ xmlAttrPtr attr;
+
+ if (elem->ns == NULL)
+ attr = xmlHasProp(cur->parent, elem->name);
+ else
+ attr = xmlHasNsProp(cur->parent, elem->name, elem->ns->href);
+ if ((attr != NULL) && (attr != (xmlAttrPtr) elem)) {
+ /* different instance, destroy it (attributes must be unique) */
+ xmlFreeProp(attr);
+ }
}
if (elem->doc != cur->doc) {
@@ -1995,7 +2009,7 @@ xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
cur->next = elem;
if (elem->next != NULL)
elem->next->prev = elem;
- if ((elem->parent != NULL) && (elem->parent->last == cur))
+ if ((elem->parent != NULL) && (elem->parent->last == cur) && (elem->type != XML_ATTRIBUTE_NODE))
elem->parent->last = elem;
return(elem);
}
@@ -2005,12 +2019,14 @@ xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
* @cur: the child node
* @elem: the new node
*
- * Add a new element @elem as the previous siblings of @cur
+ * Add a new node @elem as the previous sibling of @cur
* merging adjacent TEXT nodes (@elem may be freed)
- * If the new element was already inserted in a document it is
+ * If the new node was already inserted in a document it is
* first unlinked from its existing context.
+ * If the new node is ATTRIBUTE, it is added into properties instead of children.
+ * If there is an attribute with equal name, it is first destroyed.
*
- * Returns the new element or NULL in case of error.
+ * Returns the new node or NULL in case of error.
*/
xmlNodePtr
xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
@@ -2057,6 +2073,18 @@ xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
xmlFreeNode(elem);
return(cur->prev);
}
+ } else if (elem->type == XML_ATTRIBUTE_NODE) {
+ /* check if an attribute with the same name exists */
+ xmlAttrPtr attr;
+
+ if (elem->ns == NULL)
+ attr = xmlHasProp(cur->parent, elem->name);
+ else
+ attr = xmlHasNsProp(cur->parent, elem->name, elem->ns->href);
+ if ((attr != NULL) && (attr != (xmlAttrPtr) elem)) {
+ /* different instance, destroy it (attributes must be unique) */
+ xmlFreeProp(attr);
+ }
}
if (elem->doc != cur->doc) {
@@ -2068,8 +2096,17 @@ xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
cur->prev = elem;
if (elem->prev != NULL)
elem->prev->next = elem;
- if ((elem->parent != NULL) && (elem->parent->children == cur))
- elem->parent->children = elem;
+ if (elem->parent != NULL) {
+ if (elem->type == XML_ATTRIBUTE_NODE) {
+ if (elem->parent->properties == (xmlAttrPtr) cur) {
+ elem->parent->properties = (xmlAttrPtr) elem;
+ }
+ } else {
+ if (elem->parent->children == cur) {
+ elem->parent->children = elem;
+ }
+ }
+ }
return(elem);
}
@@ -2233,8 +2270,13 @@ xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
* @parent: the parent node
* @cur: the child node
*
- * Add a new child element, to @parent, at the end of the child list
+ * Add a new node to @parent, at the end of the child (or property) list
* merging adjacent TEXT nodes (in which case @cur is freed)
+ * If the new node was already inserted in a document it is
+ * first unlinked from its existing context.
+ * If the new node is ATTRIBUTE, it is added into properties instead of children.
+ * If there is an attribute with equal name, it is first destroyed.
+ *
* Returns the child or NULL in case of error.
*/
xmlNodePtr
@@ -2305,16 +2347,40 @@ xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
xmlFreeNode(cur);
return(parent);
}
- if (parent->children == NULL) {
- parent->children = cur;
- parent->last = cur;
+ if (cur->type == XML_ATTRIBUTE_NODE) {
+ if (parent->properties == NULL) {
+ parent->properties = (xmlAttrPtr) cur;
+ } else {
+ /* check if an attribute with the same name exists */
+ xmlAttrPtr lastattr;
+
+ if (cur->ns == NULL)
+ lastattr = xmlHasProp(parent, cur->name);
+ else
+ lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href);
+ if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur)) {
+ /* different instance, destroy it (attributes must be unique) */
+ xmlFreeProp(lastattr);
+ }
+ /* find the end */
+ lastattr = parent->properties;
+ while (lastattr->next != NULL) {
+ lastattr = lastattr->next;
+ }
+ lastattr->next = (xmlAttrPtr) cur;
+ ((xmlAttrPtr) cur)->prev = lastattr;
+ }
} else {
- prev = parent->last;
- prev->next = cur;
- cur->prev = prev;
- parent->last = cur;
+ if (parent->children == NULL) {
+ parent->children = cur;
+ parent->last = cur;
+ } else {
+ prev = parent->last;
+ prev->next = cur;
+ cur->prev = prev;
+ parent->last = cur;
+ }
}
-
return(cur);
}
@@ -2570,6 +2636,20 @@ xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
#endif
return(old);
}
+ if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) {
+#ifdef DEBUG_TREE
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlReplaceNode : Trying to replace attribute node with other node type\n");
+#endif
+ return(old);
+ }
+ if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) {
+#ifdef DEBUG_TREE
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
+#endif
+ return(old);
+ }
xmlUnlinkNode(cur);
cur->doc = old->doc;
cur->parent = old->parent;