Dear BaseX team,
perhaps you have a recommendation concerning the use of the file module.
The issue at hand is this. The function file:list (like any function in the file module, per EXPath specification) resolves relative paths against the current working directory. But the fn:doc function, on the other hand, resolves (per default) relative URIs against the static base URI of the containing XQuery module.
If an application receives relative directories as external parameters and then obtains file names via file:list - how can one access the listed files, not knowing what the current working is, thus not knowing how to resolve those relative paths? As far as I can see, neither XQuery nor the file module offer a way how to learn the current working directory.
One way out would be this pattern: avoid passing to file:list relative paths as supplied from without; but pass to the function always the result of resolving any relative paths against the static base URI of the tool. And, of course, specify your application to resolve relative paths against the tool URI, rather than against the working directory.
It is a bit awkward to ask the user to specify relative paths against the tool location, but the only alternative which I now see would be to ask the user to supply the working directory explicitly.
But perhaps I overlook something? Do you have a better solution to the general problem?
Kind regards, Hans-Juergen
Dear Hans-Jürgen,
This is how you can list all files in the directory of your query file:
let $dir := file:parent(static-base-uri()) for $file in file:list($dir) return $dir || $file
And this is how you can find out the current working directory:
file:parent('.')
Does this help? Christian
On Tue, Feb 18, 2014 at 10:38 AM, Hans-Juergen Rennau hrennau@yahoo.de wrote:
Dear BaseX team,
perhaps you have a recommendation concerning the use of the file module.
The issue at hand is this. The function file:list (like any function in the file module, per EXPath specification) resolves relative paths against the current working directory. But the fn:doc function, on the other hand, resolves (per default) relative URIs against the static base URI of the containing XQuery module.
If an application receives relative directories as external parameters and then obtains file names via file:list - how can one access the listed files, not knowing what the current working is, thus not knowing how to resolve those relative paths? As far as I can see, neither XQuery nor the file module offer a way how to learn the current working directory.
One way out would be this pattern: avoid passing to file:list relative paths as supplied from without; but pass to the function always the result of resolving any relative paths against the static base URI of the tool. And, of course, specify your application to resolve relative paths against the tool URI, rather than against the working directory.
It is a bit awkward to ask the user to specify relative paths against the tool location, but the only alternative which I now see would be to ask the user to supply the working directory explicitly.
But perhaps I overlook something? Do you have a better solution to the general problem?
Kind regards, Hans-Juergen
BaseX-Talk mailing list BaseX-Talk@mailman.uni-konstanz.de https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk
Oh, this greatly helped indeed! I was not aware of file:parent.
I conclude that an application which expects external input for both, fn:doc and file:list, has the choice between two ways of providing consistent resolution of relative paths:
(a) "always resolve against tool location": when using file:list, resolve relative paths against the static URI of the tool (fn:resolve-uri($rpath)), and when using fn:doc, use relative paths unchanged. (b) "always resolve against current directory": when using file:list, use relative paths unchanged, and when using fn:doc, resolve relative paths against the current directory: doc(resolve-uri($rpath, replace(file:parent('.'),'\','/')))
Great.
One REMARK. On a Windows system, file:parent returns a path with backslashes. When supplying this as second argument to fn:resolve-uri, an error occurs:
resolve-uri('abc.xml',file:parent('.')) => [FORG0002] URI argument is invalid: "C:\user\ptools".
One has to manually replace the backslashes by forward slashes: resolve-uri('abc.xml',replace(file:parent('.'),'\','/'))
This is a little pitfall, as the function's rejection of backslash is not necessarily expected. (By the way, Saxon behaves exactly the same.)
Once more, thanks a lot! Hans-Juergen
-------------------------------------------- Christian Grün christian.gruen@gmail.com schrieb am Di, 18.2.2014:
Betreff: Re: [basex-talk] Sought: a pattern of file:list usage An: "Hans-Juergen Rennau" hrennau@yahoo.de CC: "BaseX" basex-talk@mailman.uni-konstanz.de Datum: Dienstag, 18. Februar, 2014 11:07 Uhr
Dear Hans-Jürgen,
This is how you can list all files in the directory of your query file:
let $dir := file:parent(static-base-uri()) for $file in file:list($dir) return $dir || $file
And this is how you can find out the current working directory:
file:parent('.')
Does this help? Christian
On a Windows system, file:parent returns a path with backslashes. When supplying this as second argument to fn:resolve-uri, an error occurs:
resolve-uri('abc.xml',file:parent('.')) => [FORG0002] URI argument is invalid: "C:\user\ptools".
This should help:
resolve-uri('abc.xml', file:path-to-uri(file:parent('.')))
By the way, I think that we should some more examples both in the File Module spec. and in our Wiki..
Once more, thanks a lot!
You are welcome! Christian
I correct myself - probably one should use file:path-to-uri(file:parent('.'))
rather than replace(file:parent('.'),'\', '/')
in order to make the result of file:parent('.') usable in fn:resolve-uri.
Come to think of it - maybe a convenience function 'file:current-dir()' (= file:parent('.')) would be worthwhile, considering the importance of the current directory.
Cheers, Hans-Juergen
-------------------------------------------- Hans-Juergen Rennau hrennau@yahoo.de schrieb am Di, 18.2.2014:
Betreff: Re: [basex-talk] Sought: a pattern of file:list usage An: "Christian Grün" christian.gruen@gmail.com CC: "BaseX" basex-talk@mailman.uni-konstanz.de Datum: Dienstag, 18. Februar, 2014 12:38 Uhr
Oh, this greatly helped indeed! I was not aware of file:parent.
I conclude that an application which expects external input for both, fn:doc and file:list, has the choice between two ways of providing consistent resolution of relative paths:
(a) "always resolve against tool location": when using file:list, resolve relative paths against the static URI of the tool (fn:resolve-uri($rpath)), and when using fn:doc, use relative paths unchanged. (b) "always resolve against current directory": when using file:list, use relative paths unchanged, and when using fn:doc, resolve relative paths against the current directory: doc(resolve-uri($rpath, replace(file:parent('.'),'\','/')))
Great.
One REMARK. On a Windows system, file:parent returns a path with backslashes. When supplying this as second argument to fn:resolve-uri, an error occurs:
resolve-uri('abc.xml',file:parent('.')) => [FORG0002] URI argument is invalid: "C:\user\ptools".
One has to manually replace the backslashes by forward slashes: resolve-uri('abc.xml',replace(file:parent('.'),'\','/'))
This is a little pitfall, as the function's rejection of backslash is not necessarily expected. (By the way, Saxon behaves exactly the same.)
Once more, thanks a lot! Hans-Juergen
Come to think of it - maybe a convenience function 'file:current-dir()' (= file:parent('.')) would be worthwhile, considering the importance of the current directory.
True; maybe we could add even two functions...
file:current-dir() file:base-dir()
...as in many cases it's also interesting to find paths relative to the query file directory. Would that make sense to you? I am not quite sure if all static base URIs can be resolved to local file paths, though.
Christian
This makes very much sense to me, as these two functions deliver exactly the two alternatives for normalization (current working dir and tool dir).
Concerning static base URIs - I think you are right that it would not be guaranteed to be usable for resolving resource names - e.g. when the tool resides in a database. But on the other hand, whenever the containing module is a file, the static base URI shoud be set and should be usable for resolution.
I think there would not be any problem involved in base-dir. The function spec might adapt the words used for fn:resolve-uri:
"Resolving a URI does not dereference it. This is merely a syntactic operation on two strings."
e.g. like this: "The function result is not necessarily usable for resolving relative paths. It is merely the outcome of applying a syntactic operation to the static base URI."
Cheers, Hans-Juergen
-------------------------------------------- Christian Grün christian.gruen@gmail.com schrieb am Di, 18.2.2014:
Betreff: Re: [basex-talk] Sought: a pattern of file:list usage An: "Hans-Juergen Rennau" hrennau@yahoo.de CC: "BaseX" basex-talk@mailman.uni-konstanz.de Datum: Dienstag, 18. Februar, 2014 13:03 Uhr
Come to think of it - maybe a
convenience function 'file:current-dir()' (= file:parent('.')) would be worthwhile, considering the importance of the current directory.
True; maybe we could add even two functions...
file:current-dir() file:base-dir()
...as in many cases it's also interesting to find paths relative to the query file directory. Would that make sense to you? I am not quite sure if all static base URIs can be resolved to local file paths, though.
Christian
Helpful input! I'll propose it to the EXPath list.
Christian
On Tue, Feb 18, 2014 at 1:29 PM, Hans-Juergen Rennau hrennau@yahoo.de wrote:
This makes very much sense to me, as these two functions deliver exactly the two alternatives for normalization (current working dir and tool dir).
Concerning static base URIs - I think you are right that it would not be guaranteed to be usable for resolving resource names - e.g. when the tool resides in a database. But on the other hand, whenever the containing module is a file, the static base URI shoud be set and should be usable for resolution.
I think there would not be any problem involved in base-dir. The function spec might adapt the words used for fn:resolve-uri:
"Resolving a URI does not dereference it. This is merely a syntactic operation on two strings."
e.g. like this: "The function result is not necessarily usable for resolving relative paths. It is merely the outcome of applying a syntactic operation to the static base URI."
Cheers, Hans-Juergen
Christian Grün christian.gruen@gmail.com schrieb am Di, 18.2.2014:
Betreff: Re: [basex-talk] Sought: a pattern of file:list usage An: "Hans-Juergen Rennau" hrennau@yahoo.de CC: "BaseX" basex-talk@mailman.uni-konstanz.de Datum: Dienstag, 18. Februar, 2014 13:03 Uhr
Come to think of it - maybe a
convenience function 'file:current-dir()' (= file:parent('.')) would be worthwhile, considering the importance of the current directory.
True; maybe we could add even two functions...
file:current-dir() file:base-dir()
...as in many cases it's also interesting to find paths relative to the query file directory. Would that make sense to you? I am not quite sure if all static base URIs can be resolved to local file paths, though.
Christian
basex-talk@mailman.uni-konstanz.de