1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-21 14:53:44 +03:00

Fixed a bug in xmlDOMWrapAdoptNode(); the tree traversal stopped if the

* tree.c include/libxml/tree.h: Fixed a bug in
  xmlDOMWrapAdoptNode(); the tree traversal stopped if the
  very first given node had an attribute node :-( This was due
  to a missed check in the traversal mechanism.
  Expanded the xmlDOMWrapCtxt: it now holds the namespace map
  used in xmlDOMWrapAdoptNode() and xmlDOMWrapCloneNode() for
  reusal; so the map-items don't need to be created for every
  cloning/adoption. Added a callback function to it for
  retrieval of xmlNsPtr to be set on node->ns; this is needed
  for my custom handling of ns-references in my DOM wrapper.
  Substituted code which created the XML namespace decl on
  the doc for a call to xmlTreeEnsureXMLDecl(). Removed
  those nastly "warnigns" from the docs of the clone/adopt
  functions; they work fine on my side.
This commit is contained in:
Kasimier T. Buchcik
2006-06-16 19:46:26 +00:00
parent 1d0f7ad610
commit 978039bbd8
3 changed files with 364 additions and 198 deletions

View File

@@ -1,3 +1,20 @@
Fri Jun 16 21:37:44 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
* tree.c include/libxml/tree.h: Fixed a bug in
xmlDOMWrapAdoptNode(); the tree traversal stopped if the
very first given node had an attribute node :-( This was due
to a missed check in the traversal mechanism.
Expanded the xmlDOMWrapCtxt: it now holds the namespace map
used in xmlDOMWrapAdoptNode() and xmlDOMWrapCloneNode() for
reusal; so the map-items don't need to be created for every
cloning/adoption. Added a callback function to it for
retrieval of xmlNsPtr to be set on node->ns; this is needed
for my custom handling of ns-references in my DOM wrapper.
Substituted code which created the XML namespace decl on
the doc for a call to xmlTreeEnsureXMLDecl(). Removed
those nastly "warnigns" from the docs of the clone/adopt
functions; they work fine on my side.
Mon Jun 12 13:23:11 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net> Mon Jun 12 13:23:11 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
* result/pattern/namespaces: Adjusted the result of a * result/pattern/namespaces: Adjusted the result of a

View File

@@ -54,6 +54,15 @@ typedef xmlEntity *xmlEntityPtr;
*/ */
#define BASE_BUFFER_SIZE 4096 #define BASE_BUFFER_SIZE 4096
/**
* LIBXML_NAMESPACE_DICT:
*
* Defines experimental behaviour:
* 1) xmlNs gets an additional field @context (a xmlDoc)
* 2) when creating a tree, xmlNs->href is stored in the dict of xmlDoc.
*/
/* #define LIBXML_NAMESPACE_DICT */
/** /**
* xmlBufferAllocationScheme: * xmlBufferAllocationScheme:
* *
@@ -342,6 +351,7 @@ struct _xmlNs {
const xmlChar *href; /* URL for the namespace */ const xmlChar *href; /* URL for the namespace */
const xmlChar *prefix; /* prefix for the namespace */ const xmlChar *prefix; /* prefix for the namespace */
void *_private; /* application data */ void *_private; /* application data */
struct _xmlDoc *context; /* normally an xmlDoc */
}; };
/** /**
@@ -508,10 +518,47 @@ struct _xmlDoc {
void *psvi; /* for type/PSVI informations */ void *psvi; /* for type/PSVI informations */
}; };
typedef struct _xmlDOMWrapCtxt xmlDOMWrapCtxt; typedef struct _xmlDOMWrapCtxt xmlDOMWrapCtxt;
typedef xmlDOMWrapCtxt *xmlDOMWrapCtxtPtr; typedef xmlDOMWrapCtxt *xmlDOMWrapCtxtPtr;
/**
* xmlDOMWrapAcquireNsFunction:
* @ctxt: a DOM wrapper context
* @node: the context node (element or attribute)
* @nsName: the requested namespace name
* @nsPrefix: the requested namespace prefix
*
* A function called to acquire namespaces (xmlNs) from the wrapper.
*
* Returns an xmlNsPtr or NULL in case of an error.
*/
typedef xmlNsPtr (*xmlDOMWrapAcquireNsFunction) (xmlDOMWrapCtxtPtr ctxt,
xmlNodePtr node,
const xmlChar *nsName,
const xmlChar *nsPrefix);
/**
* xmlDOMWrapCtxt:
*
* Context for DOM wrapper-operations.
*/
struct _xmlDOMWrapCtxt { struct _xmlDOMWrapCtxt {
void * _private; void * _private;
/*
* The type of this context, just in case we need specialized
* contexts in the future.
*/
int type;
/*
* Internal namespace map used for various operations.
*/
void * namespaceMap;
/*
* Use this one to acquire an xmlNsPtr intended for node->ns.
* (Note that this is not intended for elem->nsDef).
*/
xmlDOMWrapAcquireNsFunction getNsForNodeFunc;
}; };
/** /**

498
tree.c
View File

@@ -43,8 +43,16 @@
int __xmlRegisterCallbacks = 0; int __xmlRegisterCallbacks = 0;
/************************************************************************
* *
* Forward declarations *
* *
************************************************************************/
xmlNsPtr xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns); xmlNsPtr xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns);
static xmlChar* xmlGetPropNodeValueInternal(xmlAttrPtr prop);
/************************************************************************ /************************************************************************
* * * *
* Tree memory error handler * * Tree memory error handler *
@@ -1015,6 +1023,42 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
(xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
xmlFree((char *)(str)); xmlFree((char *)(str));
/**
* DICT_COPY:
* @str: a string
*
* Copy a string using a "dict" dictionnary in the current scope,
* if availabe.
*/
#define DICT_COPY(str, cpy) \
if (str) { \
if (dict) { \
if (xmlDictOwns(dict, (const xmlChar *)(str))) \
cpy = (xmlChar *) (str); \
else \
cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
} else \
cpy = xmlStrdup((const xmlChar *)(str)); }
/**
* DICT_CONST_COPY:
* @str: a string
*
* Copy a string using a "dict" dictionnary in the current scope,
* if availabe.
*/
#define DICT_CONST_COPY(str, cpy) \
if (str) { \
if (dict) { \
if (xmlDictOwns(dict, (const xmlChar *)(str))) \
cpy = (const xmlChar *) (str); \
else \
cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
} else \
cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
/** /**
* xmlFreeDtd: * xmlFreeDtd:
* @cur: the DTD structure to free up * @cur: the DTD structure to free up
@@ -5063,16 +5107,8 @@ xmlNodeGetContent(xmlNodePtr cur)
xmlBufferFree(buffer); xmlBufferFree(buffer);
return (ret); return (ret);
} }
case XML_ATTRIBUTE_NODE:{ case XML_ATTRIBUTE_NODE:
xmlAttrPtr attr = (xmlAttrPtr) cur; return(xmlGetPropNodeValueInternal((xmlAttrPtr) cur));
if (attr->parent != NULL)
return (xmlNodeListGetString
(attr->parent->doc, attr->children, 1));
else
return (xmlNodeListGetString(NULL, attr->children, 1));
break;
}
case XML_COMMENT_NODE: case XML_COMMENT_NODE:
case XML_PI_NODE: case XML_PI_NODE:
if (cur->content != NULL) if (cur->content != NULL)
@@ -5475,6 +5511,38 @@ xmlGetNsList(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node)
} }
#endif /* LIBXML_TREE_ENABLED */ #endif /* LIBXML_TREE_ENABLED */
/*
* 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);
}
}
/** /**
* xmlSearchNs: * xmlSearchNs:
* @doc: the document * @doc: the document
@@ -5524,22 +5592,13 @@ xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
if (doc == NULL) if (doc == NULL)
return(NULL); return(NULL);
} }
if (doc->oldNs == NULL) { /*
/* * Return the XML namespace declaration held by the doc.
* Allocate a new Namespace and fill the fields. */
*/ if (doc->oldNs == NULL)
doc->oldNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); return(xmlTreeEnsureXMLDecl(doc));
if (doc->oldNs == NULL) { else
xmlTreeErrMemory("searching namespace"); return(doc->oldNs);
return(NULL);
}
memset(doc->oldNs, 0, sizeof(xmlNs));
doc->oldNs->type = XML_LOCAL_NAMESPACE;
doc->oldNs->href = xmlStrdup(XML_XML_NAMESPACE);
doc->oldNs->prefix = xmlStrdup((const xmlChar *)"xml");
}
return(doc->oldNs);
} }
while (node != NULL) { while (node != NULL) {
if ((node->type == XML_ENTITY_REF_NODE) || if ((node->type == XML_ENTITY_REF_NODE) ||
@@ -5666,22 +5725,13 @@ xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
if (doc == NULL) if (doc == NULL)
return(NULL); return(NULL);
} }
if (doc->oldNs == NULL) { /*
/* * Return the XML namespace declaration held by the doc.
* Allocate a new Namespace and fill the fields. */
*/ if (doc->oldNs == NULL)
doc->oldNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); return(xmlTreeEnsureXMLDecl(doc));
if (doc->oldNs == NULL) { else
xmlTreeErrMemory("searching namespace"); return(doc->oldNs);
return (NULL);
}
memset(doc->oldNs, 0, sizeof(xmlNs));
doc->oldNs->type = XML_LOCAL_NAMESPACE;
doc->oldNs->href = xmlStrdup(XML_XML_NAMESPACE);
doc->oldNs->prefix = xmlStrdup((const xmlChar *) "xml");
}
return (doc->oldNs);
} }
is_attr = (node->type == XML_ATTRIBUTE_NODE); is_attr = (node->type == XML_ATTRIBUTE_NODE);
while (node != NULL) { while (node != NULL) {
@@ -6104,7 +6154,7 @@ xmlGetPropNodeValueInternal(xmlAttrPtr prop)
* TODO: Do we really always want that? * TODO: Do we really always want that?
*/ */
if (prop->children != NULL) { if (prop->children != NULL) {
if ((prop->children == prop->last) && if ((prop->children->next == NULL) &&
((prop->children->type == XML_TEXT_NODE) || ((prop->children->type == XML_TEXT_NODE) ||
(prop->children->type == XML_CDATA_SECTION_NODE))) (prop->children->type == XML_CDATA_SECTION_NODE)))
{ {
@@ -7161,41 +7211,6 @@ xmlSetCompressMode(int mode) {
else xmlCompressMode = mode; else xmlCompressMode = mode;
} }
/*
* xmlDOMWrapNewCtxt:
*
* Allocates and initializes a new DOM-wrapper context.
*
* Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal errror.
*/
xmlDOMWrapCtxtPtr
xmlDOMWrapNewCtxt(void)
{
xmlDOMWrapCtxtPtr ret;
ret = xmlMalloc(sizeof(xmlDOMWrapCtxt));
if (ret == NULL) {
xmlTreeErrMemory("allocating DOM-wrapper context");
return (NULL);
}
memset(ret, 0, sizeof(xmlDOMWrapCtxt));
return (ret);
}
/*
* xmlDOMWrapFreeCtxt:
* @ctxt: the DOM-wrapper context
*
* Frees the DOM-wrapper context.
*/
void
xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt)
{
if (ctxt == NULL)
return;
xmlFree(ctxt);
}
#define XML_TREE_NSMAP_PARENT -1 #define XML_TREE_NSMAP_PARENT -1
#define XML_TREE_NSMAP_XML -2 #define XML_TREE_NSMAP_XML -2
#define XML_TREE_NSMAP_DOC -3 #define XML_TREE_NSMAP_DOC -3
@@ -7269,7 +7284,6 @@ xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)
/* /*
* xmlDOMWrapNsMapAddItem: * xmlDOMWrapNsMapAddItem:
* @map: the ns-map * @map: the ns-map
* @cur: the current map entry to append a new entry to
* @oldNs: the old ns-struct * @oldNs: the old ns-struct
* @newNs: the new ns-struct * @newNs: the new ns-struct
* @depth: depth and ns-kind information * @depth: depth and ns-kind information
@@ -7277,7 +7291,7 @@ xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)
* Adds an ns-mapping item. * Adds an ns-mapping item.
*/ */
static xmlNsMapItemPtr static xmlNsMapItemPtr
xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position, /* xmlNsMapItemPtr *cur, */ xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position,
xmlNsPtr oldNs, xmlNsPtr newNs, int depth) xmlNsPtr oldNs, xmlNsPtr newNs, int depth)
{ {
xmlNsMapItemPtr ret; xmlNsMapItemPtr ret;
@@ -7351,38 +7365,6 @@ xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position, /* xmlNsMapItemPtr *cur
return (ret); return (ret);
} }
/*
* 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);
}
}
/* /*
* xmlDOMWrapStoreNs: * xmlDOMWrapStoreNs:
* @doc: the doc * @doc: the doc
@@ -7426,6 +7408,46 @@ xmlDOMWrapStoreNs(xmlDocPtr doc,
return (ns->next); return (ns->next);
} }
/*
* xmlDOMWrapNewCtxt:
*
* Allocates and initializes a new DOM-wrapper context.
*
* Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal errror.
*/
xmlDOMWrapCtxtPtr
xmlDOMWrapNewCtxt(void)
{
xmlDOMWrapCtxtPtr ret;
ret = xmlMalloc(sizeof(xmlDOMWrapCtxt));
if (ret == NULL) {
xmlTreeErrMemory("allocating DOM-wrapper context");
return (NULL);
}
memset(ret, 0, sizeof(xmlDOMWrapCtxt));
return (ret);
}
/*
* xmlDOMWrapFreeCtxt:
* @ctxt: the DOM-wrapper context
*
* Frees the DOM-wrapper context.
*/
void
xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt)
{
if (ctxt == NULL)
return;
if (ctxt->namespaceMap != NULL)
xmlDOMWrapNsMapFree((xmlNsMapPtr) ctxt->namespaceMap);
/*
* TODO: Store the namespace map in the context.
*/
xmlFree(ctxt);
}
/* /*
* xmlTreeLookupNsListByPrefix: * xmlTreeLookupNsListByPrefix:
* @nsList: a list of ns-structs * @nsList: a list of ns-structs
@@ -7594,7 +7616,8 @@ xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number,
* This will substitute ns-references to node->nsDef for * This will substitute ns-references to node->nsDef for
* ns-references to doc->oldNs, thus ensuring the removed * ns-references to doc->oldNs, thus ensuring the removed
* branch to be autark wrt ns-references. * branch to be autark wrt ns-references.
* WARNING: This function is in a experimental state. *
* NOTE: This function was not intensively tested.
* *
* Returns 0 on success, 1 if the node is not supported, * Returns 0 on success, 1 if the node is not supported,
* -1 on API and internal errors. * -1 on API and internal errors.
@@ -7825,7 +7848,6 @@ xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node,
* @node: the start node * @node: the start node
* @prefix: the searched namespace prefix * @prefix: the searched namespace prefix
* @retNs: the resulting ns-decl * @retNs: the resulting ns-decl
* @prefixed: if the found ns-decl must have a prefix (for attributes)
* *
* Dynamically searches for a ns-declaration which matches * Dynamically searches for a ns-declaration which matches
* the given @nsName in the ancestor-or-self axis of @node. * the given @nsName in the ancestor-or-self axis of @node.
@@ -7947,10 +7969,10 @@ ns_next_prefix:
return (NULL); return (NULL);
if (prefix == NULL) { if (prefix == NULL) {
snprintf((char *) buf, sizeof(buf), snprintf((char *) buf, sizeof(buf),
"default%d", counter); "ns_%d", counter);
} else } else
snprintf((char *) buf, sizeof(buf), snprintf((char *) buf, sizeof(buf),
"%.30s%d", (char *)prefix, counter); "%.30s_%d", (char *)prefix, counter);
pref = BAD_CAST buf; pref = BAD_CAST buf;
} }
} }
@@ -7962,7 +7984,6 @@ ns_next_prefix:
* @ns: the ns-struct to use for the search * @ns: the ns-struct to use for the search
* @retNs: the found/created ns-struct * @retNs: the found/created ns-struct
* @nsMap: the ns-map * @nsMap: the ns-map
* @topmi: the last ns-map entry
* @depth: the current tree depth * @depth: the current tree depth
* @ancestorsOnly: search in ancestor ns-decls only * @ancestorsOnly: search in ancestor ns-decls only
* @prefixed: if the searched ns-decl must have a prefix (for attributes) * @prefixed: if the searched ns-decl must have a prefix (for attributes)
@@ -8009,7 +8030,8 @@ xmlDOMWrapNSNormAquireNormalizedNs(xmlDocPtr doc,
* If the search should be done in ancestors only and no * If the search should be done in ancestors only and no
* @elem (the first ancestor) was specified, then skip the search. * @elem (the first ancestor) was specified, then skip the search.
*/ */
if ((! (ancestorsOnly && (elem == NULL))) && (XML_NSMAP_NOTEMPTY(*nsMap))) if ((XML_NSMAP_NOTEMPTY(*nsMap)) &&
(! (ancestorsOnly && (elem == NULL))))
{ {
/* /*
* Try to find an equal ns-name in in-scope ns-decls. * Try to find an equal ns-name in in-scope ns-decls.
@@ -8110,7 +8132,8 @@ typedef enum {
* ns-decls where needed. Note that, since prefixes of already existent * ns-decls where needed. Note that, since prefixes of already existent
* ns-decls can be shadowed by this process, it could break QNames in * ns-decls can be shadowed by this process, it could break QNames in
* attribute values or element content. * attribute values or element content.
* WARNING: This function is in a experimental state. *
* NOTE: This function was not intensively tested.
* *
* Returns 0 if succeeded, -1 otherwise and on API/internal errors. * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
*/ */
@@ -8128,7 +8151,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
xmlNsMapItemPtr /* topmi = NULL, */ mi; xmlNsMapItemPtr /* topmi = NULL, */ mi;
/* @ancestorsOnly should be set by an option flag. */ /* @ancestorsOnly should be set by an option flag. */
int ancestorsOnly = 0; int ancestorsOnly = 0;
int optRemoveDedundantNS = int optRemoveRedundantNS =
((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0; ((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0;
xmlNsPtr *listRedund = NULL; xmlNsPtr *listRedund = NULL;
int sizeRedund = 0, nbRedund = 0, ret, i, j; int sizeRedund = 0, nbRedund = 0, ret, i, j;
@@ -8168,7 +8191,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
/* /*
* Lookup the ns ancestor-axis for equal ns-decls in scope. * Lookup the ns ancestor-axis for equal ns-decls in scope.
*/ */
if (optRemoveDedundantNS && XML_NSMAP_NOTEMPTY(nsMap)) { if (optRemoveRedundantNS && XML_NSMAP_NOTEMPTY(nsMap)) {
XML_NSMAP_FOREACH(nsMap, mi) { XML_NSMAP_FOREACH(nsMap, mi) {
if ((mi->depth >= XML_TREE_NSMAP_PARENT) && if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
(mi->shadowDepth == -1) && (mi->shadowDepth == -1) &&
@@ -8374,6 +8397,8 @@ exit:
* shadowed by this process, it could break QNames in attribute * shadowed by this process, it could break QNames in attribute
* values or element content. * values or element content.
* *
* NOTE: This function was not intensively tested.
*
* Returns 0 if succeeded, -1 otherwise and on API/internal errors. * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
*/ */
static int static int
@@ -8391,7 +8416,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
xmlNsPtr ns = NULL; xmlNsPtr ns = NULL;
int depth = -1, adoptStr = 1; int depth = -1, adoptStr = 1;
/* gather @parent's ns-decls. */ /* gather @parent's ns-decls. */
int parnsdone = 0; int parnsdone;
/* @ancestorsOnly should be set per option. */ /* @ancestorsOnly should be set per option. */
int ancestorsOnly = 0; int ancestorsOnly = 0;
@@ -8404,8 +8429,29 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
else else
adoptStr = 1; adoptStr = 1;
/*
* Get the ns-map from the context if available.
*/
if (ctxt)
nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
/*
* Disable search for ns-decls in the parent-axis of the
* desination element, if:
* 1) there's no destination parent
* 2) custom ns-reference handling is used
*/
if ((destParent == NULL) ||
(ctxt && ctxt->getNsForNodeFunc))
{
parnsdone = 1;
} else
parnsdone = 0;
cur = node; cur = node;
while (cur != NULL) { while (cur != NULL) {
/*
* Paranoid source-doc sanity check.
*/
if (cur->doc != sourceDoc) { if (cur->doc != sourceDoc) {
/* /*
* We'll assume XIncluded nodes if the doc differs. * We'll assume XIncluded nodes if the doc differs.
@@ -8437,23 +8483,28 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
curElem = cur; curElem = cur;
depth++; depth++;
/* /*
* Namespace declarations. * Namespace declarations.
* - ns->href and ns->prefix are never in the dict, so
* we need not move the values over to the destination dict.
* - Note that for custom handling of ns-references,
* the ns-decls need not be stored in the ns-map,
* since they won't be referenced by node->ns.
*/ */
if ((ctxt == NULL) && (cur->nsDef != NULL)) { if ((cur->nsDef) &&
((ctxt == NULL) || (ctxt->getNsForNodeFunc == NULL)))
{
if (! parnsdone) { if (! parnsdone) {
if (destParent && (ctxt == NULL)) { /*
/* * Gather @parent's in-scope ns-decls.
* Gather @parent's in-scope ns-decls. */
*/ if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1)
destParent) == -1) goto internal_error;
goto internal_error;
}
parnsdone = 1; parnsdone = 1;
} }
for (ns = cur->nsDef; ns != NULL; ns = ns->next) { for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
/* /*
* ns->prefix and ns->href seem not to be in the dict. * NOTE: ns->prefix and ns->href are never in the dict.
* XML_TREE_ADOPT_STR(ns->prefix) * XML_TREE_ADOPT_STR(ns->prefix)
* XML_TREE_ADOPT_STR(ns->href) * XML_TREE_ADOPT_STR(ns->href)
*/ */
@@ -8461,7 +8512,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
* Does it shadow any ns-decl? * Does it shadow any ns-decl?
*/ */
if (XML_NSMAP_NOTEMPTY(nsMap)) { if (XML_NSMAP_NOTEMPTY(nsMap)) {
XML_NSMAP_FOREACH(nsMap, mi) { XML_NSMAP_FOREACH(nsMap, mi) {
if ((mi->depth >= XML_TREE_NSMAP_PARENT) && if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
(mi->shadowDepth == -1) && (mi->shadowDepth == -1) &&
((ns->prefix == mi->newNs->prefix) || ((ns->prefix == mi->newNs->prefix) ||
@@ -8480,27 +8531,26 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
goto internal_error; goto internal_error;
} }
} }
/* No break on purpose. */ /* No break on purpose. */
case XML_ATTRIBUTE_NODE: case XML_ATTRIBUTE_NODE:
/* No namespace, no fun. */
if (cur->ns == NULL) if (cur->ns == NULL)
goto ns_end; goto ns_end;
if (! parnsdone) { if (! parnsdone) {
if (destParent && (ctxt == NULL)) { if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1)
destParent) == -1) goto internal_error;
goto internal_error;
}
parnsdone = 1; parnsdone = 1;
} }
/* /*
* Adopt ns-references. * Adopt ns-references.
*/ */
if (XML_NSMAP_NOTEMPTY(nsMap)) { if (XML_NSMAP_NOTEMPTY(nsMap)) {
/* /*
* Search for a mapping. * Search for a mapping.
*/ */
XML_NSMAP_FOREACH(nsMap, mi) { XML_NSMAP_FOREACH(nsMap, mi) {
if ((mi->shadowDepth == -1) && if ((mi->shadowDepth == -1) &&
(cur->ns == mi->oldNs)) { (cur->ns == mi->oldNs)) {
@@ -8510,21 +8560,20 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
} }
} }
/* /*
* Start searching for an in-scope ns-decl. * No matching namespace in scope. We need a new one.
*/ */
if (ctxt != NULL) { if ((ctxt) && (ctxt->getNsForNodeFunc)) {
/* /*
* User-defined behaviour. * User-defined behaviour.
*/ */
#if 0 ns = ctxt->getNsForNodeFunc(ctxt, cur,
ctxt->aquireNsDecl(ctxt, cur->ns, &ns); cur->ns->href, cur->ns->prefix);
#endif
/* /*
* Insert mapping if ns is available; it's the users fault * Insert mapping if ns is available; it's the users fault
* if not. * if not.
*/ */
if (xmlDOMWrapNsMapAddItem(&nsMap, -1, if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL) cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
goto internal_error; goto internal_error;
cur->ns = ns; cur->ns = ns;
} else { } else {
@@ -8568,7 +8617,9 @@ ns_end:
*/ */
if ((sourceDoc != NULL) && if ((sourceDoc != NULL) &&
(((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID)) (((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID))
{
xmlRemoveID(sourceDoc, (xmlAttrPtr) cur); xmlRemoveID(sourceDoc, (xmlAttrPtr) cur);
}
((xmlAttrPtr) cur)->atype = 0; ((xmlAttrPtr) cur)->atype = 0;
((xmlAttrPtr) cur)->psvi = NULL; ((xmlAttrPtr) cur)->psvi = NULL;
} }
@@ -8623,7 +8674,8 @@ leave_node:
break; break;
if ((cur->type == XML_ELEMENT_NODE) || if ((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_XINCLUDE_START) || (cur->type == XML_XINCLUDE_START) ||
(cur->type == XML_XINCLUDE_END)) { (cur->type == XML_XINCLUDE_END))
{
/* /*
* TODO: Do we expect nsDefs on XML_XINCLUDE_START? * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
*/ */
@@ -8648,7 +8700,11 @@ leave_node:
} }
if (cur->next != NULL) if (cur->next != NULL)
cur = cur->next; cur = cur->next;
else { else if ((cur->type == XML_ATTRIBUTE_NODE) &&
(cur->parent->children != NULL))
{
cur = cur->parent->children;
} else {
cur = cur->parent; cur = cur->parent;
goto leave_node; goto leave_node;
} }
@@ -8663,8 +8719,20 @@ exit:
/* /*
* Cleanup. * Cleanup.
*/ */
if (nsMap != NULL) if (nsMap != NULL) {
xmlDOMWrapNsMapFree(nsMap); if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
/*
* Just cleanup the map but don't free.
*/
if (nsMap->first) {
if (nsMap->pool)
nsMap->last->next = nsMap->pool;
nsMap->pool = nsMap->first;
nsMap->first = NULL;
}
} else
xmlDOMWrapNsMapFree(nsMap);
}
return(ret); return(ret);
} }
@@ -8681,9 +8749,9 @@ exit:
* *
* References of out-of scope ns-decls are remapped to point to @destDoc: * References of out-of scope ns-decls are remapped to point to @destDoc:
* 1) If @destParent is given, then nsDef entries on element-nodes are used * 1) If @destParent is given, then nsDef entries on element-nodes are used
* 2) If *no* @destParent is given, then @destDoc->oldNs entries are used * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.
* This is the case when you have an unliked node and just want to move it * This is the case when you don't know already where the cloned branch
* to the context of * will be added to.
* *
* If @destParent is given, it ensures that the tree is namespace * If @destParent is given, it ensures that the tree is namespace
* wellformed by creating additional ns-decls where needed. * wellformed by creating additional ns-decls where needed.
@@ -8691,11 +8759,7 @@ exit:
* shadowed by this process, it could break QNames in attribute * shadowed by this process, it could break QNames in attribute
* values or element content. * values or element content.
* TODO: * TODO:
* 1) Support dicts * 1) What to do with XInclude? Currently this returns an error for XInclude.
* Optimize string adoption for equal or none dicts.
* 2) XInclude
* WARNING: This function is in a experimental state and should only be currently
* only be used to test it.
* *
* Returns 0 if the operation succeeded, * Returns 0 if the operation succeeded,
* 1 if a node of unsupported (or not yet supported) type was given, * 1 if a node of unsupported (or not yet supported) type was given,
@@ -8721,10 +8785,15 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
/* int adoptStr = 1; */ /* int adoptStr = 1; */
/* gather @parent's ns-decls. */ /* gather @parent's ns-decls. */
int parnsdone = 0; int parnsdone = 0;
/* @ancestorsOnly should be set per option. */ /*
* @ancestorsOnly:
* TODO: @ancestorsOnly should be set per option.
*
*/
int ancestorsOnly = 0; int ancestorsOnly = 0;
xmlNodePtr resultClone = NULL, clone = NULL, parentClone = NULL, prevClone = NULL; xmlNodePtr resultClone = NULL, clone = NULL, parentClone = NULL, prevClone = NULL;
xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL; xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL;
xmlDictPtr dict; /* The destination dict */
if ((node == NULL) || (resNode == NULL) || (destDoc == NULL)) if ((node == NULL) || (resNode == NULL) || (destDoc == NULL))
return(-1); return(-1);
@@ -8748,6 +8817,13 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
if (sourceDoc == NULL) if (sourceDoc == NULL)
return (-1); return (-1);
dict = destDoc->dict;
/*
* Reuse the namespace map of the context.
*/
if (ctxt)
nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
*resNode = NULL; *resNode = NULL;
cur = node; cur = node;
@@ -8766,23 +8842,25 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
switch (cur->type) { switch (cur->type) {
case XML_XINCLUDE_START: case XML_XINCLUDE_START:
case XML_XINCLUDE_END: case XML_XINCLUDE_END:
/* TODO: What to do with XInclude? */ /*
* TODO: What to do with XInclude?
*/
goto internal_error; goto internal_error;
break; break;
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_ELEMENT_NODE: case XML_ELEMENT_NODE:
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_COMMENT_NODE:
case XML_PI_NODE:
case XML_DOCUMENT_FRAG_NODE: case XML_DOCUMENT_FRAG_NODE:
case XML_ENTITY_REF_NODE: case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE: case XML_ENTITY_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
/* /*
* Nodes of xmlNode structure. * Nodes of xmlNode structure.
*/ */
clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
if (clone == NULL) { if (clone == NULL) {
xmlTreeErrMemory("xmlDOMWrapCloneBranch(): allocating a node"); xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
goto internal_error; goto internal_error;
} }
memset(clone, 0, sizeof(xmlNode)); memset(clone, 0, sizeof(xmlNode));
@@ -8806,12 +8884,13 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
*/ */
clone = (xmlNodePtr) xmlMalloc(sizeof(xmlAttr)); clone = (xmlNodePtr) xmlMalloc(sizeof(xmlAttr));
if (clone == NULL) { if (clone == NULL) {
xmlTreeErrMemory("xmlDOMWrapCloneBranch(): allocating an attr-node"); xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
goto internal_error; goto internal_error;
} }
memset(clone, 0, sizeof(xmlAttr)); memset(clone, 0, sizeof(xmlAttr));
/* /*
* Set hierachical links. * Set hierachical links.
* TODO: Change this to add to the end of attributes.
*/ */
if (resultClone != NULL) { if (resultClone != NULL) {
clone->parent = parentClone; clone->parent = parentClone;
@@ -8824,28 +8903,31 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
resultClone = clone; resultClone = clone;
break; break;
default: default:
/* TODO */ /*
* TODO QUESTION: Any other nodes expected?
*/
goto internal_error; goto internal_error;
} }
clone->type = cur->type; clone->type = cur->type;
clone->doc = destDoc; clone->doc = destDoc;
/*
* Clone the name of the node if any.
*/
if (cur->name == xmlStringText) if (cur->name == xmlStringText)
clone->name = xmlStringText; clone->name = xmlStringText;
else if (cur->name == xmlStringTextNoenc) else if (cur->name == xmlStringTextNoenc)
/* /*
* TODO: xmlStringTextNoenc is never assigned to a node * NOTE: Although xmlStringTextNoenc is never assigned to a node
* in tree.c. * in tree.c, it might be set in Libxslt via
* "xsl:disable-output-escaping".
*/ */
clone->name = xmlStringTextNoenc; clone->name = xmlStringTextNoenc;
else if (cur->name == xmlStringComment) else if (cur->name == xmlStringComment)
clone->name = xmlStringComment; clone->name = xmlStringComment;
else if (cur->name != NULL) { else if (cur->name != NULL) {
if ((destDoc != NULL) && (destDoc->dict != NULL)) DICT_CONST_COPY(cur->name, clone->name);
clone->name = xmlDictLookup(destDoc->dict, cur->name, -1);
else
clone->name = xmlStrdup(cur->name);
} }
switch (cur->type) { switch (cur->type) {
@@ -8883,7 +8965,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
*/ */
cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
if (cloneNs == NULL) { if (cloneNs == NULL) {
xmlTreeErrMemory("xmlDOMWrapCloneBranch(): " xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
"allocating namespace"); "allocating namespace");
return(-1); return(-1);
} }
@@ -8898,7 +8980,14 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
*cloneNsDefSlot = cloneNs; *cloneNsDefSlot = cloneNs;
cloneNsDefSlot = &(cloneNs->next); cloneNsDefSlot = &(cloneNs->next);
if (ctxt == NULL) { /*
* Note that for custom handling of ns-references,
* the ns-decls need not be stored in the ns-map,
* since they won't be referenced by node->ns.
*/
if ((ctxt == NULL) ||
(ctxt->getNsForNodeFunc == NULL))
{
/* /*
* Does it shadow any ns-decl? * Does it shadow any ns-decl?
*/ */
@@ -8934,8 +9023,10 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
break; break;
case XML_TEXT_NODE: case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE: case XML_CDATA_SECTION_NODE:
if (cur->content) /*
clone->content = xmlStrdup(cur->content); * Note that this will also cover the values of attributes.
*/
DICT_COPY(cur->content, clone->content);
goto leave_node; goto leave_node;
case XML_ENTITY_NODE: case XML_ENTITY_NODE:
/* TODO: What to do here? */ /* TODO: What to do here? */
@@ -8962,15 +9053,13 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
clone->content = cur->content; clone->content = cur->content;
clone->children = cur->children; clone->children = cur->children;
clone->last = cur->last; clone->last = cur->last;
} }
goto leave_node; goto leave_node;
case XML_PI_NODE: case XML_PI_NODE:
if (cur->content) DICT_COPY(cur->content, clone->content);
clone->content = xmlStrdup(cur->content);
goto leave_node; goto leave_node;
case XML_COMMENT_NODE: case XML_COMMENT_NODE:
if (cur->content) DICT_COPY(cur->content, clone->content);
clone->content = xmlStrdup(cur->content);
goto leave_node; goto leave_node;
default: default:
goto internal_error; goto internal_error;
@@ -9011,15 +9100,14 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
} }
} }
/* /*
* Start searching for an in-scope ns-decl. * No matching namespace in scope. We need a new one.
*/ */
if (ctxt != NULL) { if ((ctxt != NULL) && (ctxt->getNsForNodeFunc != NULL)) {
/* /*
* User-defined behaviour. * User-defined behaviour.
*/ */
#if 0 ns = ctxt->getNsForNodeFunc(ctxt, cur,
ctxt->aquireNsDecl(ctxt, cur->ns, &ns); cur->ns->href, cur->ns->prefix);
#endif
/* /*
* Add user's mapping. * Add user's mapping.
*/ */
@@ -9036,6 +9124,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
destParent ? curElem : NULL, destParent ? curElem : NULL,
cur->ns, &ns, cur->ns, &ns,
&nsMap, depth, &nsMap, depth,
/* if we need to search only in the ancestor-axis */
ancestorsOnly, ancestorsOnly,
/* ns-decls must be prefixed for attributes. */ /* ns-decls must be prefixed for attributes. */
(cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1) (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
@@ -9051,7 +9140,8 @@ end_ns_reference:
* Handle ID attributes. * Handle ID attributes.
*/ */
if ((clone->type == XML_ATTRIBUTE_NODE) && if ((clone->type == XML_ATTRIBUTE_NODE) &&
(clone->parent != NULL)) { (clone->parent != NULL))
{
if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) { if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) {
xmlChar *idVal; xmlChar *idVal;
@@ -9069,7 +9159,7 @@ end_ns_reference:
} }
/* /*
** **
** The following will traversing the tree ************************ ** The following will traverse the tree **************************
** **
* *
* Walk the element's attributes before descending into child-nodes. * Walk the element's attributes before descending into child-nodes.
@@ -9161,8 +9251,20 @@ exit:
/* /*
* Cleanup. * Cleanup.
*/ */
if (nsMap != NULL) if (nsMap != NULL) {
xmlDOMWrapNsMapFree(nsMap); if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
/*
* Just cleanup the map but don't free.
*/
if (nsMap->first) {
if (nsMap->pool)
nsMap->last->next = nsMap->pool;
nsMap->pool = nsMap->first;
nsMap->first = NULL;
}
} else
xmlDOMWrapNsMapFree(nsMap);
}
/* /*
* TODO: Should we try a cleanup of the cloned node in case of a * TODO: Should we try a cleanup of the cloned node in case of a
* fatal error? * fatal error?
@@ -9311,7 +9413,7 @@ internal_error:
* Note that, since prefixes of already existent ns-decls can be * Note that, since prefixes of already existent ns-decls can be
* shadowed by this process, it could break QNames in attribute * shadowed by this process, it could break QNames in attribute
* values or element content. * values or element content.
* WARNING: This function is in a experimental state. * NOTE: This function was not intensively tested.
* *
* Returns 0 if the operation succeeded, * Returns 0 if the operation succeeded,
* 1 if a node of unsupported type was given, * 1 if a node of unsupported type was given,