On Thu, 2005-06-16 at 11:53 +0200, Kasimier Buchcik wrote:
> I'll attach an initial code for a wrapper "unlink" function. The main
I did not. Here it is.
Kasimier
/*
* xmlTreeEnsureXMLDecl:
* @doc: the doc
*
* Ensures that there is an XML namespace declaration on the doc.
*
* Returns the XML ns-struct or NULL on API and internal errors.
*/
static xmlNsPtr
xmlTreeEnsureXMLDecl(xmlDocPtr doc)
{
if (doc == NULL)
return (NULL);
if (doc->oldNs != NULL)
return (doc->oldNs);
{
xmlNsPtr ns;
ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
if (ns == NULL) {
xmlTreeErrMemory(
"allocating the XML namespace");
return (NULL);
}
memset(ns, 0, sizeof(xmlNs));
ns->type = XML_LOCAL_NAMESPACE;
ns->href = xmlStrdup(XML_XML_NAMESPACE);
ns->prefix = xmlStrdup((const xmlChar *)"xml");
doc->oldNs = ns;
return (ns);
}
}
/*
* xmlTreeAquireDocOldNs:
* @doc: the doc
* @nsName: the namespace name
* @prefix: the prefix
*
* Creates or reuses an xmlNs struct on doc->oldNs with
* the given prefix and namespace name.
*
* Returns the aquired ns struct or NULL in case of an API
* or internal error.
*/
static xmlNsPtr
xmlTreeAquireDocOldNs(xmlDocPtr doc,
const xmlChar *nsName,
const xmlChar *prefix)
{
xmlNsPtr ns;
if (doc == NULL)
return (NULL);
ns = xmlTreeEnsureXMLDecl(doc);
if (ns == NULL)
return (NULL);
if (ns->next != NULL) {
/* Reuse. */
ns = ns->next;
while (ns != NULL) {
if (((ns->prefix == prefix) ||
xmlStrEqual(ns->prefix, prefix)) &&
xmlStrEqual(ns->href, nsName)) {
return (ns);
}
if (ns->next == NULL)
break;
ns = ns->next;
}
}
/* Create. */
ns->next = xmlNewNs(NULL, NULL, NULL);
if (ns->next == NULL)
return (NULL);
ns = ns->next;
if (doc->dict) {
if (prefix != NULL)
ns->prefix = xmlDictLookup(doc->dict, prefix, -1);
ns->href = xmlDictLookup(doc->dict, nsName, -1);
} else {
if (prefix != NULL)
ns->prefix = BAD_CAST xmlStrdup(prefix);
ns->href = BAD_CAST xmlStrdup(nsName);
}
}
static int
xmlDOMWrapAddNsMapItem2(xmlNsPtr **list, int *size, int *number,
xmlNsPtr oldNs, xmlNsPtr newNs)
{
if (*list == NULL) {
*list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr));
if (*list == NULL) {
xmlTreeErrMemory("alloc ns map item");
return(-1);
}
*size = 3;
*number = 0;
} else if ((*number) >= (*size)) {
*size *= 2;
*list = (xmlNsPtr *) xmlRealloc(*list,
(*size) * 2 * sizeof(xmlNsPtr));
if (*list == NULL) {
xmlTreeErrMemory("realloc ns map item");
return(-1);
}
}
(*list)[2 * (*number)] = oldNs;
(*list)[2 * (*number) +1] = newNs;
(*number)++;
}
/*
* xmlDOMWrapRemoveNode:
*
* @doc: the doc
* @node: the node to be removed.
*
* Unlinks the given node from its owner.
* This will substitute ns-references to node->nsDef for
* ns-references to doc->oldNs, thus ensuring the removed
* branch to be autonomous of any other node in the doc
* wrt to ns-references.
*
* Returns 0 on success, 1 if the node is not supported,
* -1 on API and internal errors.
*/
static int
xmlDOMWrapRemoveNode(xmlDocPtr doc, xmlNodePtr node)
{
xmlNsPtr *list = NULL;
int sizeList, nbList, i, j;
xmlNsPtr ns;
if ((node == NULL) || (doc == NULL))
return (-1);
/* TODO: 0 or -1 ? */
if (node->parent == NULL)
return (0);
switch (node->type) {
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_ENTITY_REF_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
xmlUnlinkNode(node);
return (0);
case XML_ELEMENT_NODE:
case XML_ATTRIBUTE_NODE:
break;
default:
return (1);
}
xmlUnlinkNode(node);
/*
* Save out-of-scope ns-references in doc->oldNs.
*/
do {
switch (node->type) {
case XML_ELEMENT_NODE:
if (node->nsDef != NULL) {
ns = node->nsDef;
do {
if (xmlDOMWrapAddNsMapItem2(&list, &sizeList,
&nbList, ns, ns) == -1)
goto internal_error;
} while (ns != NULL);
}
/* No break on purpose. */
case XML_ATTRIBUTE_NODE:
if (node->ns != NULL) {
/*
* Find a mapping.
*/
if (list != NULL) {
for (i = 0, j = 0; i < nbList; i++, j += 2) {
if (node->ns == list[j]) {
node->ns = list[++j];
goto next_node;
}
}
}
/*
* Search in doc's oldNs.
*/
if (doc->oldNs != NULL) {
ns = doc->oldNs;
do {
if (node->ns == ns)
goto next_node;
ns = ns->next;
} while (ns != NULL);
}
/*
* Add to doc's oldNs.
*/
ns = xmlTreeAquireDocOldNs(doc, node->ns->href,
node->ns->prefix);
if (ns == NULL)
goto internal_error;
/*
* Add mapping.
*/
if (xmlDOMWrapAddNsMapItem2(&list, &sizeList,
&nbList, node->ns, ns) == -1)
goto internal_error;
node->ns = ns;
}
break;
default:
goto next_sibling;
}
next_node:
if ((node->type == XML_ELEMENT_NODE) &&
(node->children != NULL)) {
node = node->children;
continue;
}
next_sibling:
if (node == NULL)
break;
if (node->next != NULL)
node = node->next;
else {
node = node->parent;
goto next_sibling;
}
} while (node != NULL);
if (list != NULL)
xmlFree(list);
return (0);
internal_error:
if (list != NULL)
xmlFree(list);
return (-1);
}
_______________________________________________
xml mailing list, project page http://xmlsoft.org/
xml@gnome.org
http://mail.gnome.org/mailman/listinfo/xml