summaryrefslogtreecommitdiff
path: root/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'tree.c')
-rw-r--r--tree.c668
1 files changed, 395 insertions, 273 deletions
diff --git a/tree.c b/tree.c
index d382e29..d5b9fec 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 *
@@ -337,7 +345,7 @@ xmlSplitQName3(const xmlChar *name, int *len) {
#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
-#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED)
+#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED)
/**
* xmlValidateNCName:
* @value: the value to check
@@ -1015,6 +1023,42 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
(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
@@ -4236,7 +4280,7 @@ xmlGetNodePath(xmlNodePtr node)
const char *sep;
const char *name;
char nametemp[100];
- int occur = 0;
+ int occur = 0, generic;
if (node == NULL)
return (NULL);
@@ -4267,17 +4311,23 @@ xmlGetNodePath(xmlNodePtr node)
sep = "/";
next = NULL;
} else if (cur->type == XML_ELEMENT_NODE) {
+ generic = 0;
sep = "/";
name = (const char *) cur->name;
if (cur->ns) {
- if (cur->ns->prefix != NULL)
+ if (cur->ns->prefix != NULL) {
snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
(char *)cur->ns->prefix, (char *)cur->name);
- else
- snprintf(nametemp, sizeof(nametemp) - 1, "%s",
- (char *)cur->name);
- nametemp[sizeof(nametemp) - 1] = 0;
- name = nametemp;
+ nametemp[sizeof(nametemp) - 1] = 0;
+ name = nametemp;
+ } else {
+ /*
+ * We cannot express named elements in the default
+ * namespace, so use "*".
+ */
+ generic = 1;
+ name = "*";
+ }
}
next = cur->parent;
@@ -4288,10 +4338,11 @@ xmlGetNodePath(xmlNodePtr node)
tmp = cur->prev;
while (tmp != NULL) {
if ((tmp->type == XML_ELEMENT_NODE) &&
- (xmlStrEqual(cur->name, tmp->name)) &&
- ((tmp->ns == cur->ns) ||
- ((tmp->ns != NULL) && (cur->ns != NULL) &&
- (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))
+ (generic ||
+ (xmlStrEqual(cur->name, tmp->name) &&
+ ((tmp->ns == cur->ns) ||
+ ((tmp->ns != NULL) && (cur->ns != NULL) &&
+ (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
occur++;
tmp = tmp->prev;
}
@@ -4299,10 +4350,11 @@ xmlGetNodePath(xmlNodePtr node)
tmp = cur->next;
while (tmp != NULL && occur == 0) {
if ((tmp->type == XML_ELEMENT_NODE) &&
- (xmlStrEqual(cur->name, tmp->name)) &&
- ((tmp->ns == cur->ns) ||
- ((tmp->ns != NULL) && (cur->ns != NULL) &&
- (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))
+ (generic ||
+ (xmlStrEqual(cur->name, tmp->name) &&
+ ((tmp->ns == cur->ns) ||
+ ((tmp->ns != NULL) && (cur->ns != NULL) &&
+ (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
occur++;
tmp = tmp->next;
}
@@ -4482,12 +4534,13 @@ xmlDocGetRootElement(xmlDocPtr doc) {
/**
* xmlDocSetRootElement:
* @doc: the document
- * @root: the new document root element
+ * @root: the new document root element, if root is NULL no action is taken,
+ * to remove a node from a document use xmlUnlinkNode(root) instead.
*
* Set the root element of the document (doc->children is a list
* containing possibly comments, PIs, etc ...).
*
- * Returns the old root element if any was found
+ * Returns the old root element if any was found, NULL if root was NULL
*/
xmlNodePtr
xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
@@ -4748,6 +4801,7 @@ xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
void
xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
xmlNsPtr ns;
+ const xmlChar* fixed;
if (cur == NULL) return;
switch(cur->type) {
@@ -4783,7 +4837,7 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
if (uri == NULL)
doc->URL = NULL;
else
- doc->URL = xmlStrdup(uri);
+ doc->URL = xmlPathToURI(uri);
return;
}
}
@@ -4791,7 +4845,13 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
if (ns == NULL)
return;
- xmlSetNsProp(cur, ns, BAD_CAST "base", uri);
+ fixed = xmlPathToURI(uri);
+ if (fixed != NULL) {
+ xmlSetNsProp(cur, ns, BAD_CAST "base", fixed);
+ xmlFree(fixed);
+ } else {
+ xmlSetNsProp(cur, ns, BAD_CAST "base", uri);
+ }
}
#endif /* LIBXML_TREE_ENABLED */
@@ -5055,16 +5115,8 @@ xmlNodeGetContent(xmlNodePtr cur)
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)
@@ -5403,7 +5455,7 @@ xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
return(first);
}
-#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED)
+#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
/**
* xmlGetNsList:
* @doc: the document
@@ -5467,6 +5519,38 @@ xmlGetNsList(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node)
}
#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
@@ -5516,22 +5600,13 @@ xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
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) ||
@@ -5658,22 +5733,13 @@ xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
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) {
@@ -5871,73 +5937,75 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
/*
* now check for namespace hold by attributes on the node.
*/
- attr = node->properties;
- while (attr != NULL) {
- if (attr->ns != NULL) {
- /*
- * initialize the cache if needed
- */
- if (sizeCache == 0) {
- sizeCache = 10;
- oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
- sizeof(xmlNsPtr));
- if (oldNs == NULL) {
- xmlTreeErrMemory("fixing namespaces");
- return(-1);
- }
- newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
- sizeof(xmlNsPtr));
- if (newNs == NULL) {
- xmlTreeErrMemory("fixing namespaces");
- xmlFree(oldNs);
- return(-1);
- }
- }
- for (i = 0;i < nbCache;i++) {
- if (oldNs[i] == attr->ns) {
- attr->ns = newNs[i];
- break;
- }
- }
- if (i == nbCache) {
+ if (node->type == XML_ELEMENT_NODE) {
+ attr = node->properties;
+ while (attr != NULL) {
+ if (attr->ns != NULL) {
/*
- * OK we need to recreate a new namespace definition
+ * initialize the cache if needed
*/
- n = xmlNewReconciliedNs(doc, tree, attr->ns);
- if (n != NULL) { /* :-( what if else ??? */
+ if (sizeCache == 0) {
+ sizeCache = 10;
+ oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
+ sizeof(xmlNsPtr));
+ if (oldNs == NULL) {
+ xmlTreeErrMemory("fixing namespaces");
+ return(-1);
+ }
+ newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
+ sizeof(xmlNsPtr));
+ if (newNs == NULL) {
+ xmlTreeErrMemory("fixing namespaces");
+ xmlFree(oldNs);
+ return(-1);
+ }
+ }
+ for (i = 0;i < nbCache;i++) {
+ if (oldNs[i] == attr->ns) {
+ attr->ns = newNs[i];
+ break;
+ }
+ }
+ if (i == nbCache) {
/*
- * check if we need to grow the cache buffers.
+ * OK we need to recreate a new namespace definition
*/
- if (sizeCache <= nbCache) {
- sizeCache *= 2;
- oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
- sizeof(xmlNsPtr));
- if (oldNs == NULL) {
- xmlTreeErrMemory("fixing namespaces");
- xmlFree(newNs);
- return(-1);
- }
- newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
- sizeof(xmlNsPtr));
- if (newNs == NULL) {
- xmlTreeErrMemory("fixing namespaces");
- xmlFree(oldNs);
- return(-1);
+ n = xmlNewReconciliedNs(doc, tree, attr->ns);
+ if (n != NULL) { /* :-( what if else ??? */
+ /*
+ * check if we need to grow the cache buffers.
+ */
+ if (sizeCache <= nbCache) {
+ sizeCache *= 2;
+ oldNs = (xmlNsPtr *) xmlRealloc(oldNs,
+ sizeCache * sizeof(xmlNsPtr));
+ if (oldNs == NULL) {
+ xmlTreeErrMemory("fixing namespaces");
+ xmlFree(newNs);
+ return(-1);
+ }
+ newNs = (xmlNsPtr *) xmlRealloc(newNs,
+ sizeCache * sizeof(xmlNsPtr));
+ if (newNs == NULL) {
+ xmlTreeErrMemory("fixing namespaces");
+ xmlFree(oldNs);
+ return(-1);
+ }
}
+ newNs[nbCache] = n;
+ oldNs[nbCache++] = attr->ns;
+ attr->ns = n;
}
- newNs[nbCache] = n;
- oldNs[nbCache++] = attr->ns;
- attr->ns = n;
}
}
+ attr = attr->next;
}
- attr = attr->next;
}
/*
* Browse the full subtree, deep first
*/
- if (node->children != NULL && node->type != XML_ENTITY_REF_NODE) {
+ if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
/* deep first */
node = node->children;
} else if ((node != tree) && (node->next != NULL)) {
@@ -6096,7 +6164,7 @@ xmlGetPropNodeValueInternal(xmlAttrPtr prop)
* 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)))
{
@@ -6471,7 +6539,9 @@ xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
if (node == NULL) return(-1);
if ((node->type != XML_TEXT_NODE) &&
- (node->type != XML_CDATA_SECTION_NODE)) {
+ (node->type != XML_CDATA_SECTION_NODE) &&
+ (node->type != XML_COMMENT_NODE) &&
+ (node->type != XML_PI_NODE)) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlTextConcat: node is not text nor CDATA\n");
@@ -7153,41 +7223,6 @@ xmlSetCompressMode(int 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_XML -2
#define XML_TREE_NSMAP_DOC -3
@@ -7261,7 +7296,6 @@ xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)
/*
* 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
@@ -7269,7 +7303,7 @@ xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)
* 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;
@@ -7344,38 +7378,6 @@ xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position, /* xmlNsMapItemPtr *cur
}
/*
-* 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
@@ -7419,6 +7421,46 @@ xmlDOMWrapStoreNs(xmlDocPtr doc,
}
/*
+* 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
@@ -7586,7 +7628,8 @@ xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number,
* 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.
@@ -7817,7 +7860,6 @@ xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node,
* @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.
@@ -7939,10 +7981,10 @@ ns_next_prefix:
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;
}
}
@@ -7954,7 +7996,6 @@ ns_next_prefix:
* @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)
@@ -8001,7 +8042,8 @@ xmlDOMWrapNSNormAquireNormalizedNs(xmlDocPtr doc,
* 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.
@@ -8102,7 +8144,8 @@ typedef enum {
* 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.
*/
@@ -8120,7 +8163,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
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;
@@ -8160,7 +8203,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
/*
* 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) &&
@@ -8366,6 +8409,8 @@ exit:
* 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
@@ -8383,7 +8428,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
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;
@@ -8396,8 +8441,29 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
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.
@@ -8429,23 +8495,28 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
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)
*/
@@ -8453,7 +8524,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
* 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) ||
@@ -8472,27 +8543,26 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
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)) {
@@ -8502,21 +8572,20 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
}
}
/*
- * 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 {
@@ -8560,7 +8629,9 @@ ns_end:
*/
if ((sourceDoc != NULL) &&
(((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID))
+ {
xmlRemoveID(sourceDoc, (xmlAttrPtr) cur);
+ }
((xmlAttrPtr) cur)->atype = 0;
((xmlAttrPtr) cur)->psvi = NULL;
}
@@ -8615,7 +8686,8 @@ leave_node:
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?
*/
@@ -8640,7 +8712,11 @@ leave_node:
}
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;
}
@@ -8655,8 +8731,20 @@ exit:
/*
* 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);
}
@@ -8673,9 +8761,9 @@ exit:
*
* 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.
@@ -8683,11 +8771,7 @@ exit:
* 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,
@@ -8713,10 +8797,15 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
/* 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);
@@ -8740,6 +8829,13 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
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;
@@ -8758,23 +8854,25 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
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));
@@ -8798,12 +8896,13 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
*/
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;
@@ -8816,28 +8915,31 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
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) {
@@ -8875,7 +8977,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
*/
cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
if (cloneNs == NULL) {
- xmlTreeErrMemory("xmlDOMWrapCloneBranch(): "
+ xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
"allocating namespace");
return(-1);
}
@@ -8890,7 +8992,14 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
*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?
*/
@@ -8926,8 +9035,10 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
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? */
@@ -8954,15 +9065,13 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
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;
@@ -9003,15 +9112,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.
*/
-#if 0
- ctxt->aquireNsDecl(ctxt, cur->ns, &ns);
-#endif
+ ns = ctxt->getNsForNodeFunc(ctxt, cur,
+ cur->ns->href, cur->ns->prefix);
/*
* Add user's mapping.
*/
@@ -9028,6 +9136,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
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)
@@ -9043,7 +9152,8 @@ end_ns_reference:
* Handle ID attributes.
*/
if ((clone->type == XML_ATTRIBUTE_NODE) &&
- (clone->parent != NULL)) {
+ (clone->parent != NULL))
+ {
if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) {
xmlChar *idVal;
@@ -9061,7 +9171,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.
@@ -9153,8 +9263,20 @@ exit:
/*
* 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?
@@ -9303,7 +9425,7 @@ internal_error:
* 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,