From: Daniel Veillard Date: Sun, 16 May 2004 23:40:08 +0000 (+0000) Subject: fixing bug #134500 on namespace lookup for attribute which sometimes lead X-Git-Tag: v1.1.28~440 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=90d2dcdda9e33b818cfe9b3ee0d27023938e10ed;p=platform%2Fupstream%2Flibxslt.git fixing bug #134500 on namespace lookup for attribute which sometimes lead * libxslt/namespaces.c libxslt/namespaces.h libxslt/templates.c libxslt/transform.c: fixing bug #134500 on namespace lookup for attribute which sometimes lead to default namespace * tests/general/bug-150*, tests/docs/bug-150.xml, tests/general/Makefile.am, tests/docs/Makefile.am: added regression test for bug #134500 Daniel --- diff --git a/ChangeLog b/ChangeLog index e3d0d59..f1cd512 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Sun May 16 19:39:44 CEST 2004 Daniel Veillard + + * libxslt/namespaces.c libxslt/namespaces.h libxslt/templates.c + libxslt/transform.c: fixing bug #134500 on namespace lookup for + attribute which sometimes lead to default namespace + * tests/general/bug-150*, tests/docs/bug-150.xml, + tests/general/Makefile.am, tests/docs/Makefile.am: added + regression test for bug #134500 + Sun May 16 18:09:36 CEST 2004 Daniel Veillard * libexslt/date.h: fixing a small portability problem on Solaris diff --git a/libxslt/namespaces.c b/libxslt/namespaces.c index 1650ff9..8ed2bb2 100644 --- a/libxslt/namespaces.c +++ b/libxslt/namespaces.c @@ -121,6 +121,161 @@ error: } /** + * xsltNsInScope: + * @doc: the document + * @node: the current node + * @ancestor: the ancestor carrying the namespace + * @prefix: the namespace prefix + * + * Copy of xmlNsInScope which is not public ... + * + * Returns 1 if true, 0 if false and -1 in case of error. + */ +static int +xsltNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, 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); +} + +/** + * xsltSearchPlainNsByHref: + * @doc: the document + * @node: the current node + * @href: the namespace value + * + * Search a Ns aliasing a given URI and without a NULL prefix. + * Recurse on the parents until it finds + * the defined namespace or return NULL otherwise. + * Returns the namespace pointer or NULL. + */ +static xmlNsPtr +xsltSearchPlainNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href) +{ + xmlNsPtr cur; + xmlNodePtr orig = node; + + if ((node == NULL) || (href == NULL)) + return (NULL); + + 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->href != NULL) && (cur->prefix != NULL) && + (href != NULL) && (xmlStrEqual(cur->href, href))) { + if (xsltNsInScope(doc, orig, node, cur->href) == 1) + return (cur); + } + cur = cur->next; + } + if (orig != node) { + cur = node->ns; + if (cur != NULL) { + if ((cur->href != NULL) && (cur->prefix != NULL) && + (href != NULL) && (xmlStrEqual(cur->href, href))) { + if (xsltNsInScope(doc, orig, node, cur->href) == 1) + return (cur); + } + } + } + } + node = node->parent; + } + return (NULL); +} + +/** + * xsltGetPlainNamespace: + * @ctxt: a transformation context + * @cur: the input node + * @ns: the namespace + * @out: the output node (or its parent) + * + * Find the right namespace value for this prefix, if needed create + * and add a new namespace decalaration on the node + * Handle namespace aliases and make sure the prefix is not NULL, this + * is needed for attributes. + * + * Returns the namespace node to use or NULL + */ +xmlNsPtr +xsltGetPlainNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, + xmlNsPtr ns, xmlNodePtr out) { + xsltStylesheetPtr style; + xmlNsPtr ret; + const xmlChar *URI = NULL; /* the replacement URI */ + + if ((ctxt == NULL) || (cur == NULL) || (out == NULL) || (ns == NULL)) + return(NULL); + + style = ctxt->style; + while (style != NULL) { + if (style->nsAliases != NULL) + URI = (const xmlChar *) xmlHashLookup(style->nsAliases, ns->href); + if (URI != NULL) + break; + + style = xsltNextImport(style); + } + + if (URI == NULL) + URI = ns->href; + + if ((out->parent != NULL) && + (out->parent->type == XML_ELEMENT_NODE) && + (out->parent->ns != NULL) && + (out->parent->ns->prefix != NULL) && + (xmlStrEqual(out->parent->ns->href, URI))) + ret = out->parent->ns; + else { + if (ns->prefix != NULL) { + ret = xmlSearchNs(out->doc, out, ns->prefix); + if ((ret == NULL) || (!xmlStrEqual(ret->href, URI)) || + (ret->prefix == NULL)) { + ret = xsltSearchPlainNsByHref(out->doc, out, URI); + } + } else { + ret = xsltSearchPlainNsByHref(out->doc, out, URI); + } + } + + if (ret == NULL) { + if (out->type == XML_ELEMENT_NODE) + ret = xmlNewNs(out, URI, ns->prefix); + } + return(ret); +} + +/** * xsltGetSpecialNamespace: * @ctxt: a transformation context * @cur: the input node diff --git a/libxslt/namespaces.h b/libxslt/namespaces.h index bf70b46..c92eb1a 100644 --- a/libxslt/namespaces.h +++ b/libxslt/namespaces.h @@ -27,6 +27,11 @@ XSLTPUBFUN xmlNsPtr XSLTCALL xmlNsPtr ns, xmlNodePtr out); XSLTPUBFUN xmlNsPtr XSLTCALL + xsltGetPlainNamespace (xsltTransformContextPtr ctxt, + xmlNodePtr cur, + xmlNsPtr ns, + xmlNodePtr out); +XSLTPUBFUN xmlNsPtr XSLTCALL xsltGetSpecialNamespace (xsltTransformContextPtr ctxt, xmlNodePtr cur, const xmlChar *URI, diff --git a/libxslt/templates.c b/libxslt/templates.c index e38a068..a2af1b2 100644 --- a/libxslt/templates.c +++ b/libxslt/templates.c @@ -478,7 +478,7 @@ xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target, } else { /* create a new attribute */ if (cur->ns != NULL) - ns = xsltGetNamespace(ctxt, cur->parent, cur->ns, target); + ns = xsltGetPlainNamespace(ctxt, cur->parent, cur->ns, target); else ns = NULL; /* TODO output doc->dict, use xmlNewNsPropEatName() instead */ diff --git a/libxslt/transform.c b/libxslt/transform.c index 20ed119..f99c0f9 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -742,7 +742,7 @@ xsltCopyProp(xsltTransformContextPtr ctxt, xmlNodePtr target, return(NULL); if (attr->ns != NULL) { - ns = xsltGetNamespace(ctxt, attr->parent, attr->ns, target); + ns = xsltGetPlainNamespace(ctxt, attr->parent, attr->ns, target); } else { ns = NULL; } diff --git a/tests/docs/Makefile.am b/tests/docs/Makefile.am index e99d788..a0506eb 100644 --- a/tests/docs/Makefile.am +++ b/tests/docs/Makefile.am @@ -149,6 +149,7 @@ EXTRA_DIST = \ bug-147.xml \ bug-148.xml \ bug-149.xml \ + bug-150.xml \ character.xml \ array.xml \ items.xml diff --git a/tests/docs/bug-150.xml b/tests/docs/bug-150.xml new file mode 100644 index 0000000..69d62f2 --- /dev/null +++ b/tests/docs/bug-150.xml @@ -0,0 +1 @@ + diff --git a/tests/general/Makefile.am b/tests/general/Makefile.am index e8edbe9..452e97b 100644 --- a/tests/general/Makefile.am +++ b/tests/general/Makefile.am @@ -157,6 +157,7 @@ EXTRA_DIST = \ bug-147-4.imp bug-147-5.imp bug-147-6.imp \ bug-148.out bug-148.xsl \ bug-149.out bug-149.xsl \ + bug-150.out bug-150.xsl \ character.out character.xsl \ character2.out character2.xsl \ itemschoose.out itemschoose.xsl \ diff --git a/tests/general/bug-150.out b/tests/general/bug-150.out new file mode 100644 index 0000000..7a342d6 --- /dev/null +++ b/tests/general/bug-150.out @@ -0,0 +1,2 @@ + + diff --git a/tests/general/bug-150.xsl b/tests/general/bug-150.xsl new file mode 100644 index 0000000..e5ace1d --- /dev/null +++ b/tests/general/bug-150.xsl @@ -0,0 +1,9 @@ + + + + + + + +