1

I have an exist-db .xql page where I am wrapping three other .xql pages via xi:include:

(:==========
Declare namespaces
==========:)
declare namespace mwjl = "http://minorworksoflydgate.net/mwjl";
declare namespace m = "http://minorworksofjohnlydgate.net/model";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace xi = "http://www.w3.org/2001/XInclude";

(:==========
Declare global variables to path
==========:)
declare variable $exist:root as xs:string := 
    request:get-parameter("exist:root", "xmldb:exist:///db/apps");
declare variable $exist:controller as xs:string := 
    request:get-parameter("exist:controller", "/mwjl-app");
declare variable $path-to-data as xs:string := 
    $exist:root || $exist:controller || '/data';
declare variable $docPath as xs:string := "paratext/Lydgate_Main.xml";

(:===
Declare variable
===:)
declare variable $work := doc("/db/apps/mwjl-app/data/" || $docPath);
declare variable $TEI as element(tei:TEI)+ := $work/tei:TEI;

<m:page>
    <xi:include href="/db/apps/mwjl-app/modules/header.xql"/>
    <xi:include href="/db/apps/mwjl-app/modules/body.xql"/>
    <xi:include href="/db/apps/mwjl-app/modules/footer.xql"/>
</m:page>

I would like to pass the variable $docPath to the three xi:include's, but when I format the xi:include as follows (for the footer, for example): <xi:include href="/db/apps/mwjl-app/modules/footer.xql?docPath={$docPath}"/>it ceases to produce results. If put a request:get-parameter statement on the target .xqls and include a fallback (so something like declare variable $docPath as xs:string := request:get-parameter('docPath','fallback') on the target xqls) it generates the fallback fine, so it's obvious to me that the function works. I'm just not forming my href correctly in the xi:include statements in the requesting code. But everything I've read suggests this should be how it's formed and I cannot for the life of me figure out where I'm going wrong. Am I mistaken that this is possible in eXist-db, and if I'm not how do I format the xi:include statement?

medievalmatt
  • 427
  • 2
  • 12

1 Answers1

1

I would suggest applying the fn:encode-for-uri() function to the $docPath variable:

<xi:include href="/db/apps/mwjl-app/modules/footer.xql?docPath={encode-for-uri($docPath)}"/>

This function encodes any reserved characters in the supplied string by replacing them with their percent-encoded form. So paratext/Lydgate_Main.xml becomes paratext%2FLydgate_Main.xml.

If this doesn't do the trick (sorry, I haven't tested it), I'd suggest adding logging to the target queries, e.g.:

util:log("INFO", "docPath: " || request:get-parameter('docPath', 'no docPath parameter received'))

... which will be visible in your exist.log file when you next call your main query. (And then, if you could add a comment to this reply with, I'll update my suggestion accordingly.)

Joe Wicentowski
  • 5,159
  • 16
  • 26
  • I had tried encode-for-uri before but didn't get much luck with it. I readded it in as you suggested and it still ran into a problem, so I added the util:log line to footer.xql. It didn't result in anything being logged, but if I attempt to view the app from the web instead of from within exide I get a 400 error on EXistServlet and the following message (truncated): err:XPDY0002 Variable $request is not bound to an Java object. [at line 46, column 42, source: /db/apps/mwjl-app/modules/footer.xql]. Request:get parameter does work elsewhere in the .xql global variables, though. – medievalmatt Jul 28 '22 at 17:05
  • Ok, I'm not sure what I did but it started resolving with the "no docPath parameter received" fallback message rather than simply showing nothing or throwing the 400 error. I'm still not getting anything in the logs. Just to confirm, this syntax is correct, yes? I've split it up in two places so I could see the results. declare variable $docPath := request:get-parameter('docPath', 'no docPath parameter received',false()); {$docPath|| util:log("INFO", "docPath: " || $docPath)} Is there a configuration setting I need to change for logging? – medievalmatt Jul 28 '22 at 18:32
  • I installed the package on a Windows version of eXist and got the log result. It's 2022-07-28 18:53:41,415 [qtp1457521818-236] INFO (LogFunction.java [writeLog]:205) - (Line: 45 /db/apps/mwjl-app/modules/footer.xql) docPath: no docPath parameter received. Thanks for putting up with all of this, by the way. – medievalmatt Jul 28 '22 at 18:59
  • Ah, judging by the error message it appears that eXist treats the xincludes (whose URLs are relative) as internal requests, not HTTP requests. Thus there is HTTP context for the request:get-parameter function. Can you either (a) switch to absolute URLs including scheme and domain, which *might* trigger an HTTP context or (b) rework your included queries to be library modules, with functions that take the parameters you want to pass to them? I think module imports are more robust and better supported in eXist than internal xincludes. – Joe Wicentowski Jul 28 '22 at 19:04
  • Throwing it into an absolute URL did the trick. If you want to write it up in your answer I'll be happy to mark it as working. Out of curiosity, what are the pros and cons of setting them up as library modules vs. the absolute URL? – medievalmatt Jul 28 '22 at 19:33