Juan Zacarias has proposed merging lp:~zorba-coders/zorba/xqxq-url-resolver into lp:zorba/xqxq-module.
Requested reviews: Matthias Brantner (matthias-brantner) Chris Hillery (ceejatec) Related bugs: Bug #903797 in Zorba: "XQXQ feature request: custom schema uri resolver" https://bugs.launchpad.net/zorba/+bug/903797 For more details, see: https://code.launchpad.net/~zorba-coders/zorba/xqxq-url-resolver/+merge/123604 -- https://code.launchpad.net/~zorba-coders/zorba/xqxq-url-resolver/+merge/123604 Your team Zorba Coders is subscribed to branch lp:zorba/xqxq-module.
=== modified file 'src/xqxq.xq' --- src/xqxq.xq 2012-04-11 09:50:05 +0000 +++ src/xqxq.xq 2012-09-10 17:28:35 +0000 @@ -56,6 +56,60 @@ xs:anyURI external; (:~ + : The function prepares a given XQuery program for execution. + : If the program was successfully compiled, the function returns an + : identifier as xs:anyURI. This URI can be passed to other functions + : of this module (e.g. to actually evaluate the program). The URI + : is opaque and its lilfetime is bound by the lifetime of the XQuery + : program that invoked this function. Further reference or uses + : of the identifier lead to unexpected results. + : + : Important notes regarding the second parameter of the function. + : + : The second parameter is the xs:QName of a function describing the new url + : resolver. The url resolver function described must recive 2 parameters. + : A $namespace as xs:string that will contain the url to be resolved. + : A $data-entity as xs:string that will contain the type of resolving needed + : this can be 2 values "module" and "schema". + : The function described must return an empty sequence when the specified $namespace + : or $data-entity are not the ones to be resolved. + : + : Example: + : + : declare namespace resolver = 'http://www.zorba-xquery.com/modules/xqxq/url-resolver'; + : declare function resolver:url-resolver($namespace as xs:string, $entity as xs:string) + : { + : if($namespace = 'http://test.xq') + : then "module namespace test = 'http://test'; declare function test:foo(){'foo'};" + : else () + : }; + : + : The url resolver function's namespace, function's name, and parameters' naming are + : not restricted by the module. + : + : The url resolver function's return type is not restricted, it could be a string, a sequence, + : a node, etc. All the outputs types are to be serialized as a string. + : + : Successfully prepared queries need to be deleted by passing the resulting + : identifier to the xqxq:delete-query function of this module. + : + : @param $main-module-text the XQuery program that should be prepared. + : The program needs to be a XQuery main module. + : + : @param $function the xs:QName of a function that is going to be used + : as a url resolver. + : + : @return an identifier for the compiled program that can be passed + : as arguments to other functions of this module. + : + : @error any (static or type) error that may be raised during the compilation + : of the query. For example, err:XPST0003 if the given XQuery program could + : not be parsed. + :) +declare %an:sequential function xqxq:prepare-main-module($main-module-text as xs:string, $function as xs:QName) as + xs:anyURI external; + +(:~ : This function compiles a given XQuery library module. It can be used : to compile-check a module. : === modified file 'src/xqxq.xq.src/xqxq.cpp' --- src/xqxq.xq.src/xqxq.cpp 2011-11-30 21:57:52 +0000 +++ src/xqxq.xq.src/xqxq.cpp 2012-09-10 17:28:35 +0000 @@ -226,6 +226,80 @@ /******************************************************************************************* *******************************************************************************************/ + static void streamReleaser(std::istream* aStream) + { + delete aStream; + } + + Resource* + PrepareMainModuleFunction::XQXQURLResolver::resolveURL( + const String& aUrl, + EntityData const* aEntityData) + { + //Create entityData string to send to the new url resolver + String lDataKind; + switch (aEntityData->getKind()) + { + case EntityData::SCHEMA: + lDataKind = "schema"; + break; + case EntityData::MODULE: + lDataKind = "module"; + break; + default: + break; + } + + //construct the arguments for the url resolver + std::vector<ItemSequence_t> lArgs; + ItemSequence_t lSeq1 = new SingletonItemSequence(XQXQModule::getItemFactory()->createString(aUrl)); + ItemSequence_t lSeq2 = new SingletonItemSequence(XQXQModule::getItemFactory()->createString(lDataKind)); + lArgs.push_back(lSeq1); + lArgs.push_back(lSeq2); + + //invoke the function using the arguments generated and the QName of the function + ItemSequence_t lResult = theCtx->invoke(theFunction, lArgs); + + //Check if the result is an empty sequence by creating an Iterator, this is cheaper than serializing the result + //and then checking if it was empty. + Iterator_t lIter = lResult->getIterator(); + Item lItem; + lIter->open(); + lIter->next(lItem); + lIter->close(); + if (lItem.isNull()) + return NULL; + + //Serialize resulting sequence of the resolver + Zorba_SerializerOptions_t lOpt; + if (lItem.isNode()) + lOpt.ser_method = ZORBA_SERIALIZATION_METHOD_XML; + else + lOpt.ser_method = ZORBA_SERIALIZATION_METHOD_TEXT; + lOpt.omit_xml_declaration = ZORBA_OMIT_XML_DECLARATION_YES; + Serializer_t lSer = Serializer::createSerializer(lOpt); + std::stringstream lSerResult; + lSer->serialize(lResult, lSerResult); + + //return resource + return StreamResource::create(new std::istringstream(lSerResult.str()), &streamReleaser); + + /* + // we have only one module + if (aEntityData->getKind() == EntityData::MODULE && + aUrl == "http://www.zorba-xquery.com/modules/xqxq/test") + { + return StreamResource::create + (new std::istringstream + ("module namespace test = 'http://www.zorba-xquery.com/modules/xqxq/test'; " + "declare function test:foo() { 'foo' };"), &streamReleaser); + } + else { + return NULL; + } + */ + } + zorba::ItemSequence_t PrepareMainModuleFunction::evaluate( const Arguments_t& aArgs, @@ -233,6 +307,7 @@ const zorba::DynamicContext* aDctx) const { DynamicContext* lDynCtx = const_cast<DynamicContext*>(aDctx); + StaticContext_t lSctxChild = aSctx->createChildContext(); QueryMap* lQueryMap; if(!(lQueryMap = dynamic_cast<QueryMap*>(lDynCtx->getExternalFunctionParameter("xqxqQueryMap")))) @@ -247,9 +322,24 @@ XQuery_t lQuery; + StaticContext_t ltempSctx = lZorba->createStaticContext(); + XQXQURLResolver* lResolver = NULL; + + if ( aArgs.size() > 1 ) + { + Item lFunctionQname = getItemArgument(aArgs, 1); + + if (lSctxChild->containsFunction(lFunctionQname.getNamespace(), lFunctionQname.getLocalName(), 2)) + { + lResolver = new XQXQURLResolver(lFunctionQname, lSctxChild); + ltempSctx->registerURLResolver(lResolver); + } + + } + try { - lQuery = lZorba->compileQuery(lQueryString); + lQuery = lZorba->compileQuery(lQueryString, ltempSctx); } catch (XQueryException& xe) { @@ -273,6 +363,10 @@ String lUUID = getUUID(); lQueryMap->storeQuery(lUUID, lQuery); + + + if (lResolver) + delete lResolver; return ItemSequence_t(new SingletonItemSequence(XQXQModule::getItemFactory()->createAnyURI(lUUID))); } === modified file 'src/xqxq.xq.src/xqxq.h' --- src/xqxq.xq.src/xqxq.h 2011-11-28 23:55:59 +0000 +++ src/xqxq.xq.src/xqxq.h 2012-09-10 17:28:35 +0000 @@ -49,6 +49,7 @@ }; + class QueryMap : public ExternalFunctionParameter{ private: typedef std::map<String, XQuery_t> QueryMap_t; @@ -117,7 +118,7 @@ public: PrepareMainModuleFunction(const XQXQModule* aModule) : XQXQFunction(aModule) {} - virtual ~PrepareMainModuleFunction(){} + virtual ~PrepareMainModuleFunction(){ } virtual zorba::String getLocalName() const { return "prepare-main-module"; } @@ -127,12 +128,29 @@ const zorba::StaticContext*, const zorba::DynamicContext*) const; - protected: - static String - getUUID(); - - static String - S4(); + protected: + + class XQXQURLResolver : public URLResolver + { + protected: + Item theFunction; + StaticContext_t theCtx; + + public: + XQXQURLResolver(Item& aFunction, StaticContext_t& aSctx) : URLResolver(), theFunction(aFunction), theCtx(aSctx) {} + + virtual ~XQXQURLResolver(){ } + + virtual Resource* resolveURL(const String& aUrl, + EntityData const* aEntityData); + + }; + + static String + getUUID(); + + static String + S4(); }; === added file 'test/ExpQueryResults/xqxq/url-module-resolver.xml.res' --- test/ExpQueryResults/xqxq/url-module-resolver.xml.res 1970-01-01 00:00:00 +0000 +++ test/ExpQueryResults/xqxq/url-module-resolver.xml.res 2012-09-10 17:28:35 +0000 @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +foo === added file 'test/ExpQueryResults/xqxq/url-schema-module-resolver.xml.res' --- test/ExpQueryResults/xqxq/url-schema-module-resolver.xml.res 1970-01-01 00:00:00 +0000 +++ test/ExpQueryResults/xqxq/url-schema-module-resolver.xml.res 2012-09-10 17:28:35 +0000 @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<test:test xmlns:test="http://test"><test:subtest>a</test:subtest><test:subtest2>a</test:subtest2></test:test> === added file 'test/ExpQueryResults/xqxq/url-schema-resolver.xml.res' --- test/ExpQueryResults/xqxq/url-schema-resolver.xml.res 1970-01-01 00:00:00 +0000 +++ test/ExpQueryResults/xqxq/url-schema-resolver.xml.res 2012-09-10 17:28:35 +0000 @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<test:test xmlns:test="http://test"><test:subtest>a</test:subtest><test:subtest2>a</test:subtest2></test:test> === added file 'test/ExpQueryResults/xqxq/url-schema-resolver2.xml.res' --- test/ExpQueryResults/xqxq/url-schema-resolver2.xml.res 1970-01-01 00:00:00 +0000 +++ test/ExpQueryResults/xqxq/url-schema-resolver2.xml.res 2012-09-10 17:28:35 +0000 @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<test:test xmlns:test="http://test"><test:subtest>a</test:subtest><test:subtest2>a</test:subtest2></test:test> === added file 'test/Queries/xqxq/test.xsd' --- test/Queries/xqxq/test.xsd 1970-01-01 00:00:00 +0000 +++ test/Queries/xqxq/test.xsd 2012-09-10 17:28:35 +0000 @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" + targetNamespace="http://test" + xmlns="http://test" + elementFormDefault="qualified"> + <xs:element name="test"> + <xs:complexType> + <xs:sequence> + <xs:element name="subtest" type="xs:string"/> + <xs:element name="subtest2" type="xs:string"/> + </xs:sequence> + </xs:complexType> + </xs:element> +</xs:schema> \ No newline at end of file === added file 'test/Queries/xqxq/url-module-resolver.xq' --- test/Queries/xqxq/url-module-resolver.xq 1970-01-01 00:00:00 +0000 +++ test/Queries/xqxq/url-module-resolver.xq 2012-09-10 17:28:35 +0000 @@ -0,0 +1,11 @@ +import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq'; + +declare namespace resolver = 'http://www.zorba-xquery.com/modules/xqxq/url-resolver'; +declare function resolver:url-resolver($namespace as xs:string, $entity as xs:string) { + if($namespace = 'http://test.xq') + then "module namespace test = 'http://test'; declare function test:foo(){'foo'};" + else () +}; + +variable $queryID := xqxq:prepare-main-module("import module namespace test = 'http://test'; test:foo()", fn:QName('http://www.zorba-xquery.com/modules/xqxq/url-resolver', 'resolver:url-resolver')); +xqxq:evaluate($queryID) === added file 'test/Queries/xqxq/url-schema-module-resolver.xq' --- test/Queries/xqxq/url-schema-module-resolver.xq 1970-01-01 00:00:00 +0000 +++ test/Queries/xqxq/url-schema-module-resolver.xq 2012-09-10 17:28:35 +0000 @@ -0,0 +1,24 @@ +import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq'; + +declare namespace resolver = 'http://www.zorba-xquery.com/modules/xqxq/url-resolver'; +declare function resolver:url-resolver($namespace as xs:string, $entity as xs:string){ + if($entity = 'module') + then + if($namespace = 'http://test') + then + "module namespace test = 'http://test'; declare function test:foo(){<test:test><test:subtest>a</test:subtest><test:subtest2>a</test:subtest2></test:test>};" + else + () + else if ($entity = 'schema') + then + if($namespace = 'http://test') + then + doc('test.xsd') + else + () + else + () +}; + +variable $queryID := xqxq:prepare-main-module("import module namespace modtest = 'http://test'; import schema namespace test = 'http://test'; validate{let $x := modtest:foo() return $x}", fn:QName('http://www.zorba-xquery.com/modules/xqxq/url-resolver', 'resolver:url-resolver')); +xqxq:evaluate($queryID) \ No newline at end of file === added file 'test/Queries/xqxq/url-schema-resolver.xq' --- test/Queries/xqxq/url-schema-resolver.xq 1970-01-01 00:00:00 +0000 +++ test/Queries/xqxq/url-schema-resolver.xq 2012-09-10 17:28:35 +0000 @@ -0,0 +1,13 @@ +import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq'; + +declare namespace resolver = 'http://www.zorba-xquery.com/modules/xqxq/url-resolver'; +declare function resolver:url-resolver($namespace as xs:string, $entity as xs:string) { + if($namespace = 'http://test' and $entity = 'schema') + then + doc('test.xsd') + else + () +}; + +variable $queryID := xqxq:prepare-main-module("import schema namespace test = 'http://test'; validate {<test:test><test:subtest>a</test:subtest><test:subtest2>a</test:subtest2></test:test>}", fn:QName('http://www.zorba-xquery.com/modules/xqxq/url-resolver', 'resolver:url-resolver')); +xqxq:evaluate($queryID) === added file 'test/Queries/xqxq/url-schema-resolver2.xq' --- test/Queries/xqxq/url-schema-resolver2.xq 1970-01-01 00:00:00 +0000 +++ test/Queries/xqxq/url-schema-resolver2.xq 2012-09-10 17:28:35 +0000 @@ -0,0 +1,23 @@ +import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq'; + +import module namespace ddl = + "http://www.zorba-xquery.com/modules/store/dynamic/collections/w3c/ddl"; +import module namespace dml = + "http://www.zorba-xquery.com/modules/store/dynamic/collections/w3c/dml"; + +declare namespace resolver = 'http://www.zorba-xquery.com/modules/xqxq/url-resolver'; +declare function resolver:url-resolver($namespace as xs:string, $entity as xs:string) { + if ($entity = 'schema') + then + dml:collection("http://www.zorba-xquery.com/modules/xqxq")//xs:schema[@targetNamespace=$namespace] + else + () +}; + +declare variable $coll := "http://www.zorba-xquery.com/modules/xqxq"; +declare variable $schema := doc("test.xsd"); +ddl:create($coll); + +dml:apply-insert-nodes-first($coll, $schema); +variable $query-key := xqxq:prepare-main-module("import schema namespace test = 'http://test'; validate {<test:test><test:subtest>a</test:subtest><test:subtest2>a</test:subtest2></test:test>}", fn:QName('http://www.zorba-xquery.com/modules/xqxq/url-resolver', 'resolver:url-resolver')); +xqxq:evaluate($query-key) \ No newline at end of file
-- Mailing list: https://launchpad.net/~zorba-coders Post to : zorba-coders@lists.launchpad.net Unsubscribe : https://launchpad.net/~zorba-coders More help : https://help.launchpad.net/ListHelp