Cleanup of the API, more work done on the tree generation, Daniel.
diff --git a/tree.c b/tree.c
index b358a5d..aae8dbe 100644
--- a/tree.c
+++ b/tree.c
@@ -356,6 +356,77 @@
}
/**
+ * xmlStringLenGetNodeList:
+ * @doc: the document
+ * @value: the value of the text
+ * @int len: the length of the string value
+ *
+ * Parse the value string and build the node list associated. Should
+ * produce a flat tree with only TEXTs and ENTITY_REFs.
+ * return values: a pointer to the first child
+ */
+xmlNodePtr
+xmlStringLenGetNodeList(xmlDocPtr doc, const CHAR *value, int len) {
+ xmlNodePtr ret = NULL, last = NULL;
+ xmlNodePtr node;
+ CHAR *val;
+ const CHAR *cur = value;
+ const CHAR *q;
+
+ if (value == NULL) return(NULL);
+
+ q = cur;
+ while ((*cur != 0) && (cur - value < len)) {
+ if (*cur == '&') {
+ if (cur != q) {
+ node = xmlNewDocTextLen(doc, q, cur - q);
+ if (node == NULL) return(ret);
+ if (last == NULL)
+ last = ret = node;
+ else {
+ last->next = node;
+ last = node;
+ }
+ }
+ cur++;
+ q = cur;
+ while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
+ if ((*cur == 0) || (cur - value >= len)) {
+ fprintf(stderr,
+ "xmlStringGetNodeList: unterminated entity %30s\n", q);
+ return(ret);
+ }
+ if (cur != q) {
+ val = xmlStrndup(q, cur - q);
+ node = xmlNewReference(doc, val);
+ if (node == NULL) return(ret);
+ if (last == NULL)
+ last = ret = node;
+ else {
+ last->next = node;
+ last = node;
+ }
+ free(val);
+ }
+ cur++;
+ q = cur;
+ } else
+ cur++;
+ }
+ if (cur != q) {
+ node = xmlNewDocTextLen(doc, q, cur - q);
+ if (node == NULL) return(ret);
+ if (last == NULL)
+ last = ret = node;
+ else {
+ last->next = node;
+ last = node;
+ }
+ }
+ return(ret);
+}
+
+/**
* xmlStringGetNodeList:
* @doc: the document
* @value: the value of the attribute
@@ -1095,6 +1166,28 @@
free(cur);
}
+/**
+ * xmlUnlinkNode:
+ * @cur: the node
+ *
+ * Unlink a node from it's current context, the node is not freed
+ */
+void
+xmlUnlinkNode(xmlNodePtr cur) {
+ if (cur == NULL) {
+ fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
+ return;
+ }
+ if ((cur->parent != NULL) && (cur->parent->childs == cur))
+ cur->parent->childs = cur->next;
+ if (cur->next != NULL)
+ cur->next->prev = cur->prev;
+ if (cur->prev != NULL)
+ cur->prev->next = cur->next;
+ cur->next = cur->prev = NULL;
+ cur->parent = NULL;
+}
+
/************************************************************************
* *
* Content access functions *
@@ -1102,6 +1195,42 @@
************************************************************************/
/**
+ * xmlNodeGetContent:
+ * @cur: the node being read
+ *
+ * Read the value of a node, this can be either the text carried
+ * directly by this node if it's a TEXT node or the aggregate string
+ * of the values carried by this node child's (TEXT and ENTITY_REF).
+ * Entity references are substitued.
+ * Return value: a new CHAR * or NULL if no content is available.
+ */
+CHAR *
+xmlNodeGetContent(xmlNodePtr cur) {
+ if (cur == NULL) return(NULL);
+ switch (cur->type) {
+ case XML_DOCUMENT_FRAG_NODE:
+ case XML_ELEMENT_NODE:
+ return(xmlNodeListGetString(cur->doc, cur->childs, 1));
+ break;
+ case XML_ATTRIBUTE_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_ENTITY_REF_NODE:
+ case XML_ENTITY_NODE:
+ case XML_PI_NODE:
+ case XML_COMMENT_NODE:
+ case XML_DOCUMENT_NODE:
+ case XML_DOCUMENT_TYPE_NODE:
+ case XML_NOTATION_NODE:
+ return(NULL);
+ case XML_TEXT_NODE:
+ if (cur->content != NULL)
+ return(xmlStrdup(cur->content));
+ return(NULL);
+ }
+ return(NULL);
+}
+
+/**
* xmlNodeSetContent:
* @cur: the node being modified
* @content: the new value of the content
@@ -1114,11 +1243,36 @@
fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
return;
}
- if (cur->content != NULL) free(cur->content);
- if (content != NULL)
- cur->content = xmlStrdup(content);
- else
- cur->content = NULL;
+ switch (cur->type) {
+ case XML_DOCUMENT_FRAG_NODE:
+ case XML_ELEMENT_NODE:
+ if (cur->content != NULL) {
+ free(cur->content);
+ cur->content = NULL;
+ }
+ if (cur->childs != NULL) xmlFreeNode(cur->childs);
+ cur->childs = xmlStringGetNodeList(cur->doc, content);
+ break;
+ case XML_ATTRIBUTE_NODE:
+ break;
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_ENTITY_REF_NODE:
+ case XML_ENTITY_NODE:
+ case XML_PI_NODE:
+ case XML_COMMENT_NODE:
+ if (cur->content != NULL) free(cur->content);
+ if (cur->childs != NULL) xmlFreeNode(cur->childs);
+ if (content != NULL)
+ cur->content = xmlStrdup(content);
+ else
+ cur->content = NULL;
+ case XML_DOCUMENT_NODE:
+ case XML_DOCUMENT_TYPE_NODE:
+ break;
+ case XML_NOTATION_NODE:
+ break;
+ }
}
/**
@@ -1132,30 +1286,44 @@
void
xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
if (cur == NULL) {
- fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
+ fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
return;
}
- if (cur->content != NULL) free(cur->content);
- if (content != NULL)
- cur->content = xmlStrndup(content, len);
- else
- cur->content = NULL;
-}
-
-/**
- * xmlNodeAddContent:
- * @cur: the node being modified
- * @content: extra content
- *
- * Append the extra substring to the node content.
- */
-void
-xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
- if (cur == NULL) {
- fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
- return;
+ switch (cur->type) {
+ case XML_DOCUMENT_FRAG_NODE:
+ case XML_ELEMENT_NODE:
+ if (cur->content != NULL) {
+ free(cur->content);
+ cur->content = NULL;
+ }
+ if (cur->childs != NULL) xmlFreeNode(cur->childs);
+ cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
+ break;
+ case XML_ATTRIBUTE_NODE:
+ break;
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_ENTITY_REF_NODE:
+ case XML_ENTITY_NODE:
+ case XML_PI_NODE:
+ case XML_COMMENT_NODE:
+ if (cur->content != NULL) free(cur->content);
+ if (cur->childs != NULL) xmlFreeNode(cur->childs);
+ if (content != NULL)
+ cur->content = xmlStrndup(content, len);
+ else
+ cur->content = NULL;
+ case XML_DOCUMENT_NODE:
+ case XML_DOCUMENT_TYPE_NODE:
+ break;
+ case XML_NOTATION_NODE:
+ if (cur->content != NULL) free(cur->content);
+ if (content != NULL)
+ cur->content = xmlStrndup(content, len);
+ else
+ cur->content = NULL;
+ break;
}
- cur->content = xmlStrcat(cur->content, content);
}
/**
@@ -1169,10 +1337,95 @@
void
xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
if (cur == NULL) {
+ fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
+ return;
+ }
+ if (len <= 0) return;
+ switch (cur->type) {
+ case XML_DOCUMENT_FRAG_NODE:
+ case XML_ELEMENT_NODE: {
+ xmlNodePtr last = NULL, new;
+
+ if (cur->childs != NULL) {
+ last = cur->childs;
+ while (last->next != NULL) last = last->next;
+ } else {
+ if (cur->content != NULL) {
+ cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
+ free(cur->content);
+ cur->content = NULL;
+ if (cur->childs != NULL) {
+ last = cur->childs;
+ while (last->next != NULL) last = last->next;
+ }
+ }
+ }
+ new = xmlStringLenGetNodeList(cur->doc, content, len);
+ if (new != NULL) {
+ xmlAddChild(cur, new);
+ if ((last != NULL) && (last->next == new))
+ xmlTextMerge(last, new);
+ }
+ break;
+ }
+ case XML_ATTRIBUTE_NODE:
+ break;
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_ENTITY_REF_NODE:
+ case XML_ENTITY_NODE:
+ case XML_PI_NODE:
+ case XML_COMMENT_NODE:
+ if (content != NULL)
+ cur->content = xmlStrncat(cur->content, content, len);
+ case XML_DOCUMENT_NODE:
+ case XML_DOCUMENT_TYPE_NODE:
+ break;
+ case XML_NOTATION_NODE:
+ if (content != NULL)
+ cur->content = xmlStrncat(cur->content, content, len);
+ break;
+ }
+}
+
+/**
+ * xmlNodeAddContent:
+ * @cur: the node being modified
+ * @content: extra content
+ *
+ * Append the extra substring to the node content.
+ */
+void
+xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
+ int len;
+
+ if (cur == NULL) {
fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
return;
}
- cur->content = xmlStrncat(cur->content, content, len);
+ if (content == NULL) return;
+ len = xmlStrlen(content);
+ xmlNodeAddContentLen(cur, content, len);
+}
+
+/**
+ * xmlTextMerge:
+ * @first: the first text node
+ * @second: the second text node being merged
+ *
+ * Merge two text nodes into one
+ * Return values: the first text node augmented
+ */
+xmlNodePtr
+xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
+ if (first == NULL) return(second);
+ if (second == NULL) return(first);
+ if (first->type != XML_TEXT_NODE) return(first);
+ if (second->type != XML_TEXT_NODE) return(first);
+ xmlNodeAddContent(first, second->content);
+ xmlUnlinkNode(second);
+ xmlFreeNode(second);
+ return(first);
}
/**