diff --git a/ChangeLog b/ChangeLog index 5b908cad..77e33b46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Fri Sep 12 11:43:12 CEST 2003 Daniel Veillard + + * tree.c: applied speedup to xmlSearchNs() as suggested by + Luca Padovani. Cleaned up xmlSearchNsByHref() in the process + applying the same trick. + Fri Sep 12 01:36:20 CEST 2003 Daniel Veillard * parser.c parserInternals.c tree.c include/libxml/parser.h diff --git a/tree.c b/tree.c index ba3cbf2c..b3eea54e 100644 --- a/tree.c +++ b/tree.c @@ -5274,12 +5274,66 @@ xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) { return(cur); cur = cur->next; } + cur = node->ns; + if (cur != NULL) { + if ((cur->prefix == NULL) && (nameSpace == NULL) && + (cur->href != NULL)) + return(cur); + if ((cur->prefix != NULL) && (nameSpace != NULL) && + (cur->href != NULL) && + (xmlStrEqual(cur->prefix, nameSpace))) + return(cur); + } } node = node->parent; } return(NULL); } +/** + * xmlNsInScope: + * @doc: the document + * @node: the current node + * @ancestor: the ancestor carrying the namespace + * @prefix: the namespace prefix + * + * Verify that the given namespace held on @ancestor is still in scope + * on node. + * + * Returns 1 if true, 0 if false and -1 in case of error. + */ +static int +xmlNsInScope(xmlDocPtr doc, xmlNodePtr node, xmlNodePtr ancestor, + const xmlChar * prefix) +{ + xmlNsPtr tst; + + while ((node != NULL) && (node != ancestor)) { + if ((node->type == XML_ENTITY_REF_NODE) || + (node->type == XML_ENTITY_NODE) || + (node->type == XML_ENTITY_DECL)) + return (-1); + if (node->type == XML_ELEMENT_NODE) { + tst = node->nsDef; + while (tst != NULL) { + if ((tst->prefix == NULL) + && (prefix == NULL)) + return (0); + if ((tst->prefix != NULL) + && (prefix != NULL) + && (xmlStrEqual(tst->prefix, prefix))) + return (0); + tst = tst->next; + } + } + node = node->parent; + } + if (node != ancestor) + return (-1); + return (1); +} + + /** * xmlSearchNsByHref: * @doc: the document @@ -5291,84 +5345,82 @@ xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) { * Returns the namespace pointer or NULL. */ xmlNsPtr -xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) { +xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href) +{ xmlNsPtr cur; xmlNodePtr orig = node; - if ((node == NULL) || (href == NULL)) return(NULL); + if ((node == NULL) || (href == NULL)) + return (NULL); if (xmlStrEqual(href, XML_XML_NAMESPACE)) { - /* - * Only the document can hold the XML spec namespace. - */ - 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) { - xmlGenericError(xmlGenericErrorContext, - "xmlSearchNs : malloc failed\n"); - 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) { - xmlGenericError(xmlGenericErrorContext, - "xmlSearchNsByHref : malloc failed\n"); - return(NULL); - } - memset(doc->oldNs, 0, sizeof(xmlNs)); - doc->oldNs->type = XML_LOCAL_NAMESPACE; + /* + * Only the document can hold the XML spec namespace. + */ + 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) { + xmlGenericError(xmlGenericErrorContext, + "xmlSearchNs : malloc failed\n"); + 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) { + xmlGenericError(xmlGenericErrorContext, + "xmlSearchNsByHref : malloc failed\n"); + 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); + doc->oldNs->href = xmlStrdup(XML_XML_NAMESPACE); + doc->oldNs->prefix = xmlStrdup((const xmlChar *) "xml"); + } + return (doc->oldNs); } while (node != NULL) { - cur = node->nsDef; - while (cur != NULL) { - if ((cur->href != NULL) && (href != NULL) && - (xmlStrEqual(cur->href, href))) { - /* - * Check that the prefix is not shadowed between orig and node - */ - xmlNodePtr check = orig; - xmlNsPtr tst; - - while (check != node) { - tst = check->nsDef; - while (tst != NULL) { - if ((tst->prefix == NULL) && (cur->prefix == NULL)) - goto shadowed; - if ((tst->prefix != NULL) && (cur->prefix != NULL) && - (xmlStrEqual(tst->prefix, cur->prefix))) - goto shadowed; - tst = tst->next; - } - check = check->parent; - } - return(cur); - } -shadowed: - cur = cur->next; - } - node = node->parent; + 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->href != NULL) && (href != NULL) && + (xmlStrEqual(cur->href, href))) { + if (xmlNsInScope(doc, orig, node, cur->href) == 1) + return (cur); + } + cur = cur->next; + } + cur = node->ns; + if (cur != NULL) { + if ((cur->href != NULL) && (href != NULL) && + (xmlStrEqual(cur->href, href))) { + if (xmlNsInScope(doc, orig, node, cur->href) == 1) + return (cur); + } + } + } + node = node->parent; } - return(NULL); + return (NULL); } /**