Discussion:
[xquery-talk] Doing 'base-uri "{$base-uri}";' fails
Andreas Mixich
2018-05-01 16:55:14 UTC
Permalink
Hello,

Since the application I am writing can be installed on other hosts, the
`base-uri` must be configurable to that foreign host. I want to solve
this with a library module, that keeps domain specific configuration
separate to the user and which gets imported where needed.

Test case:

declare namespace cfg = "ns:cfg";
declare base-uri "{$cfg:base-uri}";
declare variable $cfg:base-uri := "file:/S:/projects/xqfr/src/fragments/";

let $file := doc("xhtml5-page.xhtml")
return $file

Doing this test case, both Saxon and BaseX try to find the file in the
directory of their executable installation

[FODC0002] Resource 'C:/Program Files (x86)/BaseX/xhtml5-page.xhtml'
does not exist.

When using it in a module context, with Saxon I get:

Invalid URI config.xqm: Invalid base URI: Illegal character in scheme
name at index 0: {$cfg:base-uri}: {$cfg:base-uri}

Googling it, it appears to be Java itself, throwing the error message.
Thus the {$base-uri} may get passed verbatim, but when used outside of
the module context, it somehow gets caught, but without a signal.

Long story short: Is there a way to achieve what I want? Is there a
reason against hoisting variables in XQuery, that get 'declared'?

Would it make sense to file an enhancement request on 'www.w3.org/Bugs' ?
--
Goody Bye, Minden jót, Mit freundlichen Grüßen,
Andreas Mixich
_______________________________________________
talk@
Michael Kay
2018-05-01 17:35:43 UTC
Permalink
Saxon allows you to set the static base URI when you compile a query using the API

XQueryCompiler.setBaseURI()

The base URI doesn't have to have any particular relationship with the location of the query source code. However, the same base URI is used for compile time actions such as importing modules and schemas, and for run-time actions such as the doc() function, so this has limited usefulness.

The XQuery 3.1 spec allows more flexibility than this. §2.1.1 says:

If the value of the Static Base URI is based on the location of the query module (in the terminology of [RFC3986] <https://www.w3.org/TR/xquery-31/#RFC3986>, the URI used to retrieve the encapsulating entity), then the implementation may use different values for the Static Base URI during static analysis and during dynamic evaluation. This might be necessary, for example, if a query consisting of several modules is compiled, and the resulting object code is distributed to a different location for execution. It would then be inappropriate to use the same location when resolving import module declarations as when retrieving source documents using the fn:doc function. If an implementation uses different values for the Static Base URI during static analysis and during dynamic evaluation, then it is implementation-defined which of the two values is used for particular operations that rely on the Static Base URI; for example, it is implementation-defined which value is used for resolving collation URIs.

Saxon uses some of that flexibility for XSLT (where compiled stylesheets may now be deployed to a different location that the source code -- which is why that clause was introduced). But transportable compiled code is not yet available for XQuery.

In practice the way that most people achieve what you are looking for is to set a URIResolver for use by the doc() function. Your URIResolver can resolve the supplied relative URI against any base URI of its choosing. You can also use OASIS catalogs for complete freedom in redirecting requests.

What the spec doesn't offer is the ability to have a parameterized "declare base URI" declaration within the query itself. Might be a nice feature, but there are plenty of other ways of achieving the required effect.

Michael Kay
Saxonica
Post by Andreas Mixich
Hello,
Since the application I am writing can be installed on other hosts, the
`base-uri` must be configurable to that foreign host. I want to solve
this with a library module, that keeps domain specific configuration
separate to the user and which gets imported where needed.
declare namespace cfg = "ns:cfg";
declare base-uri "{$cfg:base-uri}";
declare variable $cfg:base-uri := "file:/S:/projects/xqfr/src/fragments/";
let $file := doc("xhtml5-page.xhtml")
return $file
Doing this test case, both Saxon and BaseX try to find the file in the
directory of their executable installation
[FODC0002] Resource 'C:/Program Files (x86)/BaseX/xhtml5-page.xhtml'
does not exist.
Invalid URI config.xqm: Invalid base URI: Illegal character in scheme
name at index 0: {$cfg:base-uri}: {$cfg:base-uri}
Googling it, it appears to be Java itself, throwing the error message.
Thus the {$base-uri} may get passed verbatim, but when used outside of
the module context, it somehow gets caught, but without a signal.
Long story short: Is there a way to achieve what I want? Is there a
reason against hoisting variables in XQuery, that get 'declared'?
Would it make sense to file an enhancement request on 'www.w3.org/Bugs' ?
--
Goody Bye, Minden jót, Mit freundlichen GrÌßen,
Andreas Mixich
_______________________________________________
http://x-query.com/mailman/listinfo/talk
Andreas Mixich
2018-05-01 19:41:32 UTC
Permalink
Hello Michael,

thank you for your clarification. I would prefer the catalog way, but
according to the Saxon documentation on XML catalogs it states

The catalog is NOT currently used for non-XML resources, *including
query modules*, unparsed text files, collations, and collections.

It seems, BaseX does not use catalogs at this point either, only on
document imports into the database.

I may end up by adding a build script/installer, that does a string
search & replace with a user-supplied value for the base-uri.
--
Goody Bye, Minden jót, Mit freundlichen Grüßen,
Andreas Mixich
_______________________________________________
***@x-query.com
http://x-query.com/mailm
Loading...