[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [xml] redicting parts of trees



Hi,

> Von: cazic gmx net
> Datum: Mon, 16 May 2005 13:59:34 +0200 (MEST)

[...]

> I attached a first sketch for an adopt function. It tries the "oldNs"

I did not. But now.

[...]

Kasimier
static int
xmlDOMWrapAdoptNode(void *ctxt, xmlDocPtr sourceDoc, xmlDocPtr destDoc,
		xmlNodePtr node, xmlNodePtr parent, int unlink)
{
    int ret = 0;
    xmlNodePtr cur, curElem, par;
    xmlNsPtr *nsList = NULL;
    int nbNs, sizeNs, sameDict;
    xmlNsPtr ns;

    if (node == NULL)
	return(-1);
    switch (node->type) {
	case XML_DOCUMENT_NODE:
        case XML_HTML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
        case XML_DOCB_DOCUMENT_NODE:
#endif
        case XML_DOCUMENT_TYPE_NODE:
        case XML_NOTATION_NODE:
        case XML_DTD_NODE:
        case XML_ELEMENT_DECL:
        case XML_ATTRIBUTE_DECL:
        case XML_ENTITY_DECL:
	case XML_ENTITY_NODE:
	    return (-1);
	default:
	    break;
    }       
    sameDict = ((sourceDoc->dict == destDoc->dict) &&
	(destDoc->dict != NULL)) ? 1 : 0;
    cur = node;
    /*
    * TODO: Unlink.
    */    
    while (cur != NULL) {
	switch (cur->type) {
	    case XML_ELEMENT_NODE:
		curElem = cur;
		/* No break on purpose. */
	    case XML_ATTRIBUTE_NODE:
		/*
		* Adopt the localName.
		*/
		if (! sameDict) {
		    if (destDoc->dict)
			cur->name = xmlDictLookup(destDoc->dict, cur->name, -1);
		    else if (sourceDoc->dict)
			cur->name = BAD_CAST xmlStrdup(cur->name); 
		    /*
		    * TODO: Are namespace declarations ever in a dict?
		    */
		}
		/*
		* Adopt out-of-scope namespace declarations.
		*/
		if (cur->ns != NULL) {
		    int i, j;
		    /*		
		    * Did we come across this declaration already?
		    */
		    if (nsList != NULL) {
			for (i = 0, j = 0; i < nbNs; i++, j += 2) {
			    if (nsList[j] == cur->ns) {
			    /*
			    * If the entry is NULL, then the ns declaration
			    * is in scope.
				*/
				if (nsList[++j] != NULL)
				    cur->ns = nsList[j];
				goto ns_adopt_done;
			    }
			}
		    }
		    if (ctxt == NULL) {
			/*
			* Default behaviour: lookup if not in scope; if so,
			* then pick or add a ns decl. using oldNs of xmlDoc.
			*/
			/*
			* Is the namespace declaration in scope?
			*/
			if (curElem != NULL) {
			    par = curElem;
			    do {
				if ((par->type == XML_ELEMENT_NODE) &&
				    (par->nsDef != NULL)) {
				    ns = par->nsDef;
				    do {
					if (ns == cur->ns) {
					    /*
					    * In scope; add a mapping.
					    */
					    ns = NULL;
					    goto ns_add_mapping;
					}
					ns = ns->next;
				    } while (ns != NULL);
				}
				par = par->parent;
			    } while (par != node);
			}
			/*
			* No luck, the namespace will be out of scope if the
			* node is unlinked; anchor it temporarily on the
			* xmlDoc.
			*/						
			ns = destDoc->oldNs;
			while (ns != NULL) {
			    if ((((ns->prefix == NULL) &&
				  (cur->ns->prefix == NULL)) ||
				((ns->prefix != NULL) &&
				 xmlStrEqual(ns->prefix, cur->ns->prefix))) &&
				xmlStrEqual(ns->href, cur->ns->href)) {

				goto ns_add_mapping;
			    }
			    if (ns->next == NULL)
				break;
			    ns = ns->next;
			}
			/*
			* Again, no luck; add a namespace declaration to oldNs.
			*/
			if (ns == NULL) {
			    /*
			    * Libxml2 expects the XML namespace to be
			    * in oldNs.
			    */
			    ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
			    if (ns == NULL) {
				xmlTreeErrMemory(
				    "allocating temporary namespace");
				goto internal_error;
			    }
			    memset(ns, 0, sizeof(xmlNs));
			    ns->type = XML_LOCAL_NAMESPACE;
			    ns->href = xmlStrdup(XML_XML_NAMESPACE); 
			    ns->prefix = xmlStrdup(
				(const xmlChar *)"xml");
			    destDoc->oldNs = ns;
			}
			ns->next = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
			if (ns->next == NULL) {
			    xmlTreeErrMemory(
				"allocating temporary namespace");
			    goto internal_error;
			}
			ns = ns->next;

			memset(ns, 0, sizeof(xmlNs));
			ns->type = XML_LOCAL_NAMESPACE;	
			if (cur->ns->prefix != NULL)
			    ns->prefix = xmlStrdup(cur->ns->prefix);
			ns->href = xmlStrdup(cur->ns->href);
		    } else {
			/*
			* User-defined behaviour.
			*/
#if 0
			ctxt->aquireNsDecl(ctxt, cur->ns, &ns);
#endif
		    }
		    
ns_add_mapping:
		    if (nsList == NULL) {
			nsList = (xmlNsPtr *) xmlMalloc(10 *
			    sizeof(xmlNsPtr));
			if (nsList == NULL) {
			    xmlTreeErrMemory(
				"allocating namespace map");
			    goto internal_error;
			}
			nbNs = 0;
			sizeNs = 5;
		    } else if (nbNs >= sizeNs) {
			sizeNs *= 2;
			nsList = (xmlNsPtr *) xmlRealloc(nsList,
			    sizeNs * 2 * sizeof(xmlNsPtr));
			if (nsList == NULL) {
			    xmlTreeErrMemory(
				"re-allocating namespace map");
			    goto internal_error;
			}
		    }
		    nsList[nbNs *2] = cur->ns;
		    nsList[nbNs *2 +1] = ns;
		    nbNs++;
		    if (ns != NULL)
			cur->ns = ns;
		}

ns_adopt_done:
		cur->doc = destDoc;
		if (cur->type == XML_ELEMENT_NODE) {
		    cur->psvi = NULL;
		    cur->line = 0;
		    cur->extra = 0;
		    /*
		    * Attributes.
		    */
		    if (cur->properties != NULL) {
			cur = (xmlNodePtr) cur->properties;
			continue;
		    }
		} else {
		    ((xmlAttrPtr) cur)->atype = 0;
		    ((xmlAttrPtr) cur)->psvi = 0;
		}

		break;
	    case XML_TEXT_NODE:
	    case XML_CDATA_SECTION_NODE:
		/*
		* TODO: When to adopt the content?
		*/
		goto internal_error;
		break;
	    case XML_XINCLUDE_START:
	    case XML_XINCLUDE_END:
		/* TODO */
		goto internal_error;
		break;
	    case XML_ENTITY_REF_NODE:
		/*
		* TODO: Remove entity child nodes.
		*/
		goto internal_error;
		break;
	    case XML_ENTITY_NODE:
	    case XML_NOTATION_NODE:
		/*
		* TODO: Remove those nodes.
		*/
		goto internal_error;
		break;	    
	    case XML_PI_NODE:
	    case XML_COMMENT_NODE:
		/*
		* TODO: Adopt something?
		*/
		goto internal_error;
		break;
	    case XML_DOCUMENT_FRAG_NODE:
		break;
	    default:
		break;
	}
	/*
	* Walk the brach.
	*/
	if (cur->children != NULL) {
	    cur = cur->children;
	    continue;
	}

next_sibling:
	if (cur == node)
	    break;
	if (cur->next != NULL)
	    cur = cur->next;
	else {
	    cur = cur->parent;
	    goto next_sibling;
	}
    }

    return (ret);

internal_error:
    if (nsList != NULL)
	xmlFree(nsList);
    return (-1);
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]