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,

> 1) 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.

> 2) 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:

1. 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>

2. 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