9

I store my entities in the eXist XML database and I use a file name (resource id) as an ID of an entity.

Example:

String xquery = "for $movie in collection('/db/movie')//movie "
    + "return $movie";

After executing this query I retrieve org.xmldb.api.base.Resource instance whose content I use to create an entity. When I want to set an id of this entity, I do it like this:

dvd.setId(rs.getId());

The problem is that if I execute query like this:

String xquery = "for $dvd in collection('/db/dvd')//dvd "
        + "return <dvd>"
        + "{$dvd/title}"
        + "{$dvd/type}"
        + "{"
        + "<content>"
        + " {"
        + " for $movie in $dvd/content//movie"
            + "     let $movieIn := doc(concat(\"/db/movie/\", $movie/@id))/movie"
        + "     return "
            + "                    <movie id=\"{$movie/@id}\">"
            + "                          {$movieIn/name}"
            + "                          {$movieIn/director}"
            + "                          {$movieIn/year}"
            + "                          {$movieIn/country}"
            + "                          {$movieIn/actors}"
            + "                          {$movieIn/genres}"
            + "                    </movie>"
        + " }"
        + "</content>"
        + "}"
        + "</dvd>";

rs.getId() returns null. I also tried method getDocumentId() from this class, but it returns null as well. Is there a way of making it return the id of the resource (which is the name of the file which the entity is stored in) ?

If it's not possible, is there a way (function or something) of getting the file name of the file which I'm working with (I mean, the database retrieves data from) with an XQuery query ?

I tried replacing this line:

+ "return <dvd>"

with this:

+ "return <dvd id=\"{$dvd}\">"

(so that I could get the name of the file from the attribute) but it doesn't return the file name.

Joe Wicentowski
  • 5,159
  • 16
  • 26
VaclavDedik
  • 1,960
  • 4
  • 20
  • 27

3 Answers3

13

Since you're using eXist-db, you can use the util:document-name() function:

util:document-name($dvd)
Joe Wicentowski
  • 5,159
  • 16
  • 26
11

You might be looking for fn:base-uri(). See here.

morja
  • 8,297
  • 2
  • 39
  • 59
  • Thanks ! Great. But if there is something that returns only the name of the file (not whole uri), let me know please. – VaclavDedik Jun 17 '11 at 13:41
  • You could probably do something like `fn:substring-after(fn:base-uri($dvd),fn:static-base-uri())`. Or another replace with `fn:replace()`. I dont know of a function that does it directly. – morja Jun 17 '11 at 14:03
  • I use fn:substring(fn:base-uri($dvd), 9) (because I know that the uri has always the same length) but thanks for the idea! – VaclavDedik Jun 17 '11 at 14:13
  • I'd suggest to use `document-uri( root( $dvd ) )` instead, it returns (as documented on that page) the same, but it prevents potentially issues with base attributes when present... – DiZzZz Sep 19 '14 at 07:29
0

fn:base-uri will return the whole URI rather than the last part of the URI, but you can use a regex solution combined with the fn:base-uri function for a solution that is not dependent on eXist-specific functions.

This particular regex trims the extension with \.\w+$ and captures the filename without extension in capture group 2

declare namespace db="http://basex.org/modules/db";
declare namespace file="http://expath.org/ns/file";
declare variable $path as xs:string external;

let $docs := collection($path)
for $doc in $docs
return
let $file := replace(fn:base-uri($doc),'^(.*/)(.*?)\.\w+$','$2')
return db:replace('13F', $file, $doc)

Alternatively for the whole filename with extension

  let $file := replace(fn:base-uri($doc),'^(.*/)(.*?\.\w+$)','$2')
Louis
  • 146,715
  • 28
  • 274
  • 320
conteh
  • 1,544
  • 1
  • 17
  • 39
  • Yeah the first answer doesn't actually give a method to get only the file name, rather the whole file path or uri. It's really not answering the question. [http://www.xqueryfunctions.com/xq/fn_base-uri.html] And the second is exist-db specific. This ones works with basexdb. I read this in the comments "But if there is something that returns only the name of the file (not whole uri), let me know please" I thought that's what was being asked and wasn't. – conteh Jul 01 '16 at 14:34
  • I've edited your answer to include the important parts of your comment into it because it is *very useful* for people who are just scanning answers. I saw the OP accepted the `fn:base-uri` answer and thought it did everything the OP wanted. I see now that the comments indicate otherwise. As you can see, people skip comments. – Louis Jul 01 '16 at 14:41
  • `return let $file := ` is invalid syntax in eXist 2.2, and your regular expressions won't work for files that have no extension (which is quite possible). – Louis Jul 01 '16 at 15:00
  • Thanks Louis, yeah I didn't put the full code there. I had just just put some partial code to show the regex mostly. The code there now works in basex. It saves a collection of xml documents in basex named by the filename without the extension. I haven't tested in on existdb but db:replace is a basex function I believe so would need adjusting on existdb. – conteh Jul 01 '16 at 17:25