diff --git a/ChangeLog b/ChangeLog index 7767ed7e2fe241edc922eeb2c1e167f43c8184e6_Q2hhbmdlTG9n..b3ad0d686d07b559675fb012a35d6d7a29b92491_Q2hhbmdlTG9n 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Tue Jan 14 14:23:47 CET 2003 Daniel Veillard <daniel@veillard.com> + + * libxslt/functions.c: fixed #101502 by applying and cleaning up + the associated patch from Daniel Stodden. + * tests/documents/Makefile.am tests/documents/fragment*: added a + specific test. + Mon Jan 13 23:25:59 CET 2003 Daniel Veillard <daniel@veillard.com> * libxslt/extensions.c libxslt/transform.c: fixing bug #101602 diff --git a/libxslt/functions.c b/libxslt/functions.c index 7767ed7e2fe241edc922eeb2c1e167f43c8184e6_bGlieHNsdC9mdW5jdGlvbnMuYw==..b3ad0d686d07b559675fb012a35d6d7a29b92491_bGlieHNsdC9mdW5jdGlvbnMuYw== 100644 --- a/libxslt/functions.c +++ b/libxslt/functions.c @@ -32,6 +32,7 @@ #include <libxml/xpathInternals.h> #include <libxml/parserInternals.h> #include <libxml/uri.h> +#include <libxml/xpointer.h> #include "xslt.h" #include "xsltInternals.h" #include "xsltutils.h" @@ -97,6 +98,112 @@ * * ************************************************************************/ +static void +xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI) +{ + xsltTransformContextPtr tctxt; + xmlURIPtr uri; + xmlChar *fragment; + xsltDocumentPtr xsltdoc; + xmlDocPtr doc; + xmlXPathContextPtr xptrctxt; + xmlXPathObjectPtr object; + + tctxt = xsltXPathGetTransformContext(ctxt); + if (tctxt == NULL) { + xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, + "document() : internal error tctxt == NULL\n"); + valuePush(ctxt, xmlXPathNewNodeSet(NULL)); + return; + } + + uri = xmlParseURI((const char *) URI); + if (uri == NULL) { + xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, + "document() : failed to parse URI\n"); + valuePush(ctxt, xmlXPathNewNodeSet(NULL)); + return; + } + + /* + * check for and remove fragment identifier + */ + fragment = uri->fragment; + if (fragment != NULL) { + uri->fragment = NULL; + URI = xmlSaveUri(uri); + xsltdoc = xsltLoadDocument(tctxt, URI); + xmlFree(URI); + } else + xsltdoc = xsltLoadDocument(tctxt, URI); + xmlFreeURI(uri); + + if (xsltdoc == NULL) { + if ((URI == NULL) || + (URI[0] = '#') || + (xmlStrEqual(tctxt->style->doc->URL, URI))) { + doc = tctxt->style->doc; + } else { + valuePush(ctxt, xmlXPathNewNodeSet(NULL)); + + if (fragment != NULL) + xmlFree(fragment); + + return; + } + } + doc = xsltdoc->doc; + + if ( fragment == NULL ) { + valuePush(ctxt, + xmlXPathNewNodeSet((xmlNodePtr) doc)); + return; + } + + /* use XPointer of HTML location for fragment ID */ + + xptrctxt = xmlXPtrNewContext(doc, NULL, NULL); + if (xptrctxt == NULL) { + xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, + "document() : internal error xptrctxt == NULL\n"); + goto out_fragment; + } + + object = xmlXPtrEval(fragment, xptrctxt); + xmlFree(fragment); + xmlXPathFreeContext(xptrctxt); + + if (object == NULL) + goto out_fragment; + + switch (object->type) { + case XPATH_NODESET: + break; + case XPATH_UNDEFINED: + case XPATH_BOOLEAN: + case XPATH_NUMBER: + case XPATH_STRING: + case XPATH_POINT: + case XPATH_USERS: + case XPATH_XSLT_TREE: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, + "document() : XPointer does not select a node set: #%s\n", + fragment); + goto out_object; + } + + valuePush(ctxt, object); + return; + +out_object: + xmlXPathFreeObject(object); + +out_fragment: + valuePush(ctxt, xmlXPathNewNodeSet(NULL)); +} + /** * xsltDocumentFunction: * @ctxt: the XPath Parser context @@ -108,7 +215,6 @@ void xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs) { - xsltDocumentPtr doc; xmlXPathObjectPtr obj, obj2 = NULL; xmlChar *base = NULL, *URI; @@ -215,32 +321,9 @@ if (URI == NULL) { valuePush(ctxt, xmlXPathNewNodeSet(NULL)); } else { - xsltTransformContextPtr tctxt; - - tctxt = xsltXPathGetTransformContext(ctxt); - if (tctxt == NULL) { - xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, - "document() : internal error tctxt == NULL\n"); - valuePush(ctxt, xmlXPathNewNodeSet(NULL)); - } else { - doc = xsltLoadDocument(tctxt, URI); - if (doc == NULL) { - if ((xmlStrEqual(URI, BAD_CAST "")) || - (xmlStrEqual(tctxt->style->doc->URL, URI))) { - valuePush(ctxt, xmlXPathNewNodeSet( - (xmlNodePtr)tctxt->style->doc)); - } else { - valuePush(ctxt, xmlXPathNewNodeSet(NULL)); - } - } else { - /* TODO: use XPointer of HTML location for fragment ID */ - /* pbm #xxx can lead to location sets, not nodesets :-) */ - valuePush(ctxt, - xmlXPathNewNodeSet((xmlNodePtr) doc->doc)); - } - } - xmlFree(URI); - } + xsltDocumentFunctionLoadDocument( ctxt, URI ); + xmlFree(URI); + } } xmlXPathFreeObject(obj); if (obj2 != NULL) diff --git a/tests/documents/Makefile.am b/tests/documents/Makefile.am index 7767ed7e2fe241edc922eeb2c1e167f43c8184e6_dGVzdHMvZG9jdW1lbnRzL01ha2VmaWxlLmFt..b3ad0d686d07b559675fb012a35d6d7a29b92491_dGVzdHMvZG9jdW1lbnRzL01ha2VmaWxlLmFt 100644 --- a/tests/documents/Makefile.am +++ b/tests/documents/Makefile.am @@ -30,4 +30,8 @@ diff $(srcdir)/message.result result; \ grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" || true;\ rm -f result) + @($(CHECKER) $(top_builddir)/xsltproc/xsltproc $(srcdir)/fragment.xsl $(srcdir)/fragment.xml > result 2>&1 ; \ + diff $(srcdir)/fragment.result result; \ + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" || true;\ + rm -f result) diff --git a/tests/documents/fragment.result b/tests/documents/fragment.result new file mode 100644 index 0000000000000000000000000000000000000000..b3ad0d686d07b559675fb012a35d6d7a29b92491_dGVzdHMvZG9jdW1lbnRzL2ZyYWdtZW50LnJlc3VsdA== --- /dev/null +++ b/tests/documents/fragment.result @@ -0,0 +1,2 @@ +<?xml version="1.0"?> +<doc><p>hello</p></doc> diff --git a/tests/documents/fragment.xml b/tests/documents/fragment.xml new file mode 100644 index 0000000000000000000000000000000000000000..b3ad0d686d07b559675fb012a35d6d7a29b92491_dGVzdHMvZG9jdW1lbnRzL2ZyYWdtZW50LnhtbA== --- /dev/null +++ b/tests/documents/fragment.xml @@ -0,0 +1,1 @@ +<doc/> diff --git a/tests/documents/fragment.xsl b/tests/documents/fragment.xsl new file mode 100644 index 0000000000000000000000000000000000000000..b3ad0d686d07b559675fb012a35d6d7a29b92491_dGVzdHMvZG9jdW1lbnRzL2ZyYWdtZW50LnhzbA== --- /dev/null +++ b/tests/documents/fragment.xsl @@ -0,0 +1,12 @@ +<?xml version="1.0"?> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + version="1.0"> + +<xsl:template match="/"> + <doc> + <xsl:copy-of select="document('fragment2.xml#xpointer(//p[1])')"/> + </doc> +</xsl:template> + +</xsl:stylesheet> + diff --git a/tests/documents/fragment2.xml b/tests/documents/fragment2.xml new file mode 100644 index 0000000000000000000000000000000000000000..b3ad0d686d07b559675fb012a35d6d7a29b92491_dGVzdHMvZG9jdW1lbnRzL2ZyYWdtZW50Mi54bWw= --- /dev/null +++ b/tests/documents/fragment2.xml @@ -0,0 +1,3 @@ +<test><doc><p>hello</p> +<title>foo</title> +<p>goodbye</p></doc></test>