0
votes

For posterity, I managed to suss out the correct organization of commands do do what I wish. the goal is to process an xml file before including it in an existing database. The correct code snippet for such is below, followed by my original question and incorrect code.

declare variable $filename external;

(: find timestamp in filename :)
(: get package and file into variables :)
let $mydoc    := doc($filename)
let $datetime := file:last-modified($filename)
let $package  := substring-before($mydoc/testrun/testsuite/@name/data(), ".")
let $file     := substring-after($mydoc/testrun/testsuite/@name/data(), ".")

(: add file to database :)
(: insert package, file, and timestamp attributes to every testcase :)
return
  copy $mycopy := $mydoc
  modify (for $testcase in $mycopy//testcase
                    return insert nodes
                  (attribute package {$package}, 
                   attribute file {$file},
                   attribute xs:datetime {$datetime})
                                     into $testcase)
   return
     (db:replace("TestResults", file:name($filename), $mycopy)),
   (db:flush("TestResults"))

I am attempting to bring junit files into BaseX. I am scraping the file update timestamp to use to update test cases in order to filter later tests by time. I am also marking up test cases with the java package and file that was run. A sample junit file is below

<testrun>
  <testsuite name="package.file">
    <testcase>bogus</testcase>
  </testsuite>
</testrun>

My XQuery is below. I am attempting to read in a new junit output file, update the test cases, then add the whole thing to the database. It seems that due to the XQUF rules, I can only update elements BEFORE I add files to the database. I assume that $mydoc is an in memory database of the one document that I am updating. The current error is that the query parser can't find the return statement. I know it is not a formatting error due to my editor. If there is a cleaner way to do this then please let me know, I am new to xml and xquery and basex. Thank you

declare variable $filename external;
(: find timestamp in filename :)
(: get package and file into variables :)
let $mydoc    := doc($filename)
let $datetime := file:last-modified($filename)
let $package  := substring-before($mydoc/testrun/testsuite/@name/data(), ".")
let $file     := substring-after($mydoc/testrun/testsuite/@name/data(), ".")

(: add file to database :)
(:
 : so you cant insert a new document into a database and then update its newly added elements, so create a doc first? edit it? then add that?
 :)

(: insert package, file, and timestamp attributes to every testcase :)
for $testcase in $mydoc//testcase
insert nodes
    (attribute package {$package},
     attribute file {$file},
     attribute xs:datetime {$datetime}) into $testcase

return (db:replace("TestResults", $filename, $mydoc),
        db:flush("TestResults"))


(: db:replace("TestResults", $filename, $mydoc) :)
(:
 : return db:replace("TestResults", $filename, $mydoc)
 :)
(:
 : return db:replace{. , $mydoc}
 :)
1
insert isn't in that set of keywords expected to exist inside a FLWOR expression (which is, of course, expected to end in return. It's not a let, a where, etc... so this looks like a straightforward complaint that the parser is seeing non-FLWOR syntax without the FLWOR being properly ended first.Charles Duffy
Granted, I'm pretty rusty here, so I'm open to correction, but I'd expect you to put your FLWOR inside your update expression, not the other way around.Charles Duffy
I'd mark your answer correct if you could have submitted one, but thank you it seems like that is the problem in this caseJoshua

1 Answers

1
votes

After "for $x in XXXX" you either need another FLWOR clause, or a "return expression". You can't just have an expression.

The XQuery syntax, especially the update syntax, is a bit awkward in this respect. It tries to look English-like, but sometimes fails. "Return" looks like an imperative command, so you expect to be able to substitute a different imperative, like "insert nodes"; but this is all an illusion. You can write "for $x in XXX return insert nodes ...." despite the fact that it doesn't read like English.