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