Your example 2 does the job, thank you! Although I had to change the second-to-last line from
return file:write('data/'|| $page/@key || '.xml', $page,
to
return file:write('data/'|| $page/@key || '.xml', $new-part,
One last thing: if I want to specify the path to the input file on the command line, how do I then refer to it in the script? From the Command-Line Options page, it seems I can say
-i/my/path/to/input.xml
But what do I use in place of $input in that case? If I just remove "$input" from the script I get a "no context value bound" error if I say
-i/my/path/to/input.xml
or
-i/my/path/to/input.xml "/"
Thanks,
Michael
On Thu, May 26, 2016 at 11:21 PM, Christian Grün christian.gruen@gmail.com wrote:
Hi Michael,
- There'll be a new version of the input file arriving periodically, so
I'd
prefer to be able to do everything at the command line without having to create the database inside the GUI. Not sure of the best way to go about that.
Using the GUI was just an example. You can create new databases via commands (CREATE), XQuery (db:create) or our APIs. Please check out our documentation for more hints.
- In the GUI for now, I can perform the replace with the map, or I can
run
the for loop that writes out all the files. But I get an "Unexpected end
of
query" error when I try to do both, so what's the problem with my syntax?
In XQuery, multiple expressions can be separated with commas.
Note, however, that XQuery is a functional language; as such, it is not possible to first update items and then access them in the same query that easily. There are various alternatives to get around this limitation:
- Use a BaseX command script to run all operations [1]:
<commands> <create-db name='input'>...path/to/input.xml</create-db> <xquery><![CDATA[ let $map := ... ]]></xquery> <xquery> for $page in ... <xquery> </commands>
- Use copy/transform/return or update to do all updates in
main-memory [2] and pass them on to your file:write function. This could e.g. look as follows:
let $input := doc('input.xml') let $map := map:merge( for $part in $input//part return map:entry(string-join($part/partinfo/*, '/'), $part) ) for $page in $input//page let $new-part := $page update { for $partinfo in .//unit/partinfo let $part := $map(string-join($partinfo/*, '/')) return replace node $partinfo with element part { $part/node() } } return file:write('data/'|| $page/@key || '.xml', $page, map{ "omit-xml-declaration": "no" })
The good thing here is that your replace operations won’t need to be cached until the very end; they will directly be run on each page element (and not persisted on disk; but this is something you don’t need anyway it seems)
Christian
[1] http://docs.basex.org/wiki/Commands#Command_Scripts [2] http://docs.basex.org/wiki/XQuery_Update#Non-Updating_Expressions