Quoting Daniel Veillard <[EMAIL PROTECTED]>:
> On Tue, Feb 21, 2006 at 12:53:32PM +1300, Andrew Miller wrote:
> > Quoting Daniel Veillard <[EMAIL PROTECTED]>:
> > > I don't understand the patch especially the node->doc != doc test, please
> > elaborate, thanks !
> >
> > The first check tests for cases where it doesn't make sense to search for
> the
> > namespace, and sets the ns to NULL in those cases. If the prefix is NULL,
> it is
> > clearly not sensible to search for a match by prefix(remember namespace is
> > defined if we get to that code). The document equality check is there
> because
> > prefixes from one document don't make sense in another document.
>
> Hum, that copy operation try to preserve the prefix as far as I remember,
> you are not changing that, aren't you ?
I agree it might be worth trying the prefix, and then performing an
equality test on the namespaceURI, and only setting ns to NULL if they don't
match. That way, we avoid creating two entries with the same prefix and
namespace where we only need one.
>From DOM Level 2 Core specification:
"As far as the DOM is concerned, special attributes used for declaring XML
namespaces are still exposed and can be manipulated just like any other
attribute. However, nodes are permanently bound to namespace URIs as they get
created. Consequently, moving a node within a document, using the DOM, in no
case results in a change of its namespace prefix or namespace URI. Similarly,
creating a node with a namespace prefix and namespace URI, or changing the
namespace prefix of a node, does not result in any addition, removal, or
modification of any special attributes for declaring the appropriate XML
namespaces. Namespace validation is not enforced; the DOM application is
responsible. In particular, since the mapping between prefixes and namespace
URIs is not enforced, in general, the resulting document cannot be serialized
naively. For example, applications may have to declare every namespace in use
when serializing a document."
So I think that the correct behaviour is to search by namespace and prefix
everywhere. If we don't find a match with the same namespace and prefix, we
create a new namespace object(even if there is another entry with the same
prefix or same URI, but not both the same). This means we can have two
identical prefixes with the same URI, and it is only at serialisation time that
we do anything about it.
I have attached an updated patch that adds a function to search by both
namespace and prefix, and uses this instead of the document equality check. I
think that there are probably a number of other places we should be using it as
well, but I don't have the time to go through and fix them all now. I have run
it through my gdome based test program, as well as the libxml2 regression tests
and the part of the CellML API testsuite I have implemented so far(which is
based on an XML API layered on top of gdome, and uses namespaces in a way which
hit the bug before). No tests which previously passed have failed.
>
> > I added the root->parent->type == XML_ELEMENT_NODE check into the while
> loop
> > because xmlNewNs seems to want an element, and otherwise we traverse past
> the
> > document element and get the document.
>
> Okay that makes sense.
>
> Daniel
Best regards,
Andrew Miller
----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.
diff -udr libxml2-2.6.23-pristine/include/libxml/tree.h libxml2-2.6.23/include/libxml/tree.h
--- libxml2-2.6.23-pristine/include/libxml/tree.h 2005-08-22 21:14:24.000000000 +1200
+++ libxml2-2.6.23/include/libxml/tree.h 2006-02-22 10:55:43.363837631 +1300
@@ -871,6 +871,12 @@
xmlSearchNsByHref (xmlDocPtr doc,
xmlNodePtr node,
const xmlChar *href);
+XMLPUBFUN xmlNsPtr XMLCALL
+ xmlSearchNsByHrefAndPrefix (xmlDocPtr doc,
+ xmlNodePtr node,
+ const xmlChar *prefix,
+ const xmlChar *href);
+
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED)
XMLPUBFUN xmlNsPtr * XMLCALL
xmlGetNsList (xmlDocPtr doc,
diff -udr libxml2-2.6.23-pristine/tree.c libxml2-2.6.23/tree.c
--- libxml2-2.6.23-pristine/tree.c 2005-12-23 03:57:41.000000000 +1300
+++ libxml2-2.6.23/tree.c 2006-02-22 10:58:39.479674117 +1300
@@ -3872,20 +3872,33 @@
if (node->ns != NULL) {
xmlNsPtr ns;
- ns = xmlSearchNs(doc, ret, node->ns->prefix);
+ if (node->ns->prefix == NULL)
+ ns = NULL;
+ else
+ {
+ ns = xmlSearchNsByHrefAndPrefix(doc, ret, node->ns->prefix,
+ node->ns->href);
+ }
if (ns == NULL) {
/*
* Humm, we are copying an element whose namespace is defined
* out of the new tree scope. Search it in the original tree
* and add it at the top of the new tree
*/
- ns = xmlSearchNs(node->doc, node, node->ns->prefix);
+ ns = xmlSearchNsByHrefAndPrefix(node->doc, node, node->ns->prefix,
+ node->ns->href);
if (ns != NULL) {
xmlNodePtr root = ret;
- while (root->parent != NULL) root = root->parent;
+ while (root->parent != NULL &&
+ root->parent->type == XML_ELEMENT_NODE)
+ root = root->parent;
ret->ns = xmlNewNs(root, ns->href, ns->prefix);
}
+ else
+ {
+ ret->ns = xmlNewNs(ret, node->ns->href, node->ns->prefix);
+ }
} else {
/*
* reference the existing namespace definition in our own tree.
@@ -5474,6 +5487,104 @@
* Returns the namespace pointer or NULL.
*/
xmlNsPtr
+xmlSearchNsByHrefAndPrefix(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace, const xmlChar *href) {
+
+ xmlNsPtr cur;
+ xmlNodePtr orig = node;
+
+ if (node == NULL) return(NULL);
+ if ((nameSpace != NULL) &&
+ (xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) {
+ if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
+ /*
+ * The XML-1.0 namespace is normally held on the root
+ * element. In this case exceptionally create it on the
+ * node element.
+ */
+ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
+ if (cur == NULL) {
+ xmlTreeErrMemory("searching namespace");
+ return(NULL);
+ }
+ memset(cur, 0, sizeof(xmlNs));
+ cur->type = XML_LOCAL_NAMESPACE;
+ cur->href = xmlStrdup(XML_XML_NAMESPACE);
+ cur->prefix = xmlStrdup((const xmlChar *)"xml");
+ cur->next = node->nsDef;
+ node->nsDef = cur;
+ return(cur);
+ }
+ 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);
+ }
+ while (node != NULL) {
+ if ((node->type == XML_ENTITY_REF_NODE) ||
+ (node->type == XML_ENTITY_NODE) ||
+ (node->type == XML_ENTITY_DECL))
+ return(NULL);
+ if (node->type == XML_ELEMENT_NODE) {
+ cur = node->nsDef;
+ while (cur != NULL) {
+ if ((cur->prefix == NULL) && (nameSpace == NULL) &&
+ (cur->href != NULL) && xmlStrEqual(cur->href, href))
+ return(cur);
+ if ((cur->prefix != NULL) && (nameSpace != NULL) &&
+ (cur->href != NULL) && (href != NULL) &&
+ (xmlStrEqual(cur->prefix, nameSpace)) &&
+ (xmlStrEqual(cur->href, href)))
+ return(cur);
+ cur = cur->next;
+ }
+ if (orig != node) {
+ cur = node->ns;
+ if (cur != NULL) {
+ if ((cur->prefix == NULL) && (nameSpace == NULL) &&
+ (cur->href != NULL) && xmlStrEqual(cur->href, href))
+ return(cur);
+ if ((cur->prefix != NULL) && (nameSpace != NULL) &&
+ (cur->href != NULL) &&
+ (xmlStrEqual(cur->prefix, nameSpace) &&
+ (xmlStrEqual(cur->href, href))))
+ return(cur);
+ }
+ }
+ }
+ node = node->parent;
+ }
+ return(NULL);
+}
+
+/**
+ * xmlSearchNs:
+ * @doc: the document
+ * @node: the current node
+ * @nameSpace: the namespace prefix
+ *
+ * Search a Ns registered under a given name space for a document.
+ * recurse on the parents until it finds the defined namespace
+ * or return NULL otherwise.
+ * @nameSpace can be NULL, this is a search for the default namespace.
+ * We don't allow to cross entities boundaries. If you don't declare
+ * the namespace within those you will be in troubles !!! A warning
+ * is generated to cover this case.
+ *
+ * Returns the namespace pointer or NULL.
+ */
+xmlNsPtr
xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
xmlNsPtr cur;
_______________________________________________
xml mailing list, project page http://xmlsoft.org/
[email protected]
http://mail.gnome.org/mailman/listinfo/xml