Hi Christian,
Thank you for investigating. I'll update the methods in my query module as you 
suggested.
Best regards,
Johannes

-----Ursprüngliche Nachricht-----
Von: Christian Grün [mailto:christian.gr...@gmail.com] 
Gesendet: Donnerstag, 25. Mai 2017 16:43
An: Johannes Echterhoff <echterh...@interactive-instruments.de>
Cc: BaseX <basex-talk@mailman.uni-konstanz.de>
Betreff: Re: AW: [basex-talk] Evaluating XPath within custom QueryModule

Hi Johannes,

To find the weak spot, I decided to further simplify your example (I have 
attached the result).

It’s good to use the internal BaseX value types as Java function argument, such 
as Value or ANode. If you use Object, the function input will be copied and 
converted to a standard Java type, which is a DOM element in this case 
(represented by BXElem). This node will be a full copy of the original node, 
without its ancestors (otherwise, it would get huge if you work with large 
databases).

Hope this helps,
Christian



On Tue, May 23, 2017 at 4:03 PM, Johannes Echterhoff 
<echterh...@interactive-instruments.de> wrote:
> Hi Christian,
>
> Here you are (I hope this is sufficient, actual file content can be 
> found further down below):
>
> ·         Test.java – A simple QueryModule
>
> ·         Test.xq – The query I execute from within a UnitTest
>
> ·         Test.xml – The XML that is queried (in my test, it was either
> located in C:/BaseXTest or directly accessible in Test.xq – see 
> Test.xq for further details)
>
> ·         UnitTest – code I used to run the whole test (tested with BaseX
> Versions 8.5.3 and 8.6)
>
> What I noticed: If I do NOT load the XML document from an external 
> file, everything works as expected. Then I get this result:
>
>
>
> indirectly: "4979"
>
> on element: "4979"
>
> on element: "4979"
>
> on element: "4979"
>
> <test>
>
>   <result id="Element_1" attributeX="4979"/>
>
>   <result id="Element_2" attributeX="4979"/>
>
>   <result id="Element_3" attributeX="4979"/>
>
>   <result id="SubElement_1" attributeX="4979"/>
>
> </test>
>
>
>
> If the document IS loaded from an external file (which is what I tried 
> first), I get the following – incorrect - result:
>
>
>
> empty: empty-sequence()
>
> on element: "4979"
>
> on element: "4979"
>
> empty: empty-sequence()
>
> <test>
>
>   <result id="Element_1" attributeX=""/>
>
>   <result id="Element_2" attributeX="4979"/>
>
>   <result id="Element_3" attributeX="4979"/>
>
>   <result id="SubElement_1" attributeX=""/>
>
> </test>
>
>
>
> Here, something appears to be wrong when evaluating parent elements.
>
>
>
> Best regards,
>
> Johannes
>
>
>
>
>
>
>
> ---------- Test.java
>
>
>
> import org.basex.api.dom.BXElem;
>
> import org.basex.core.Context;
>
> import org.basex.query.QueryException;
>
> import org.basex.query.QueryModule;
>
> import org.basex.query.QueryProcessor;
>
> import org.basex.query.value.Value;
>
> import org.basex.query.value.node.ANode;
>
> import org.basex.query.value.seq.Empty;
>
>
>
> public class Test extends QueryModule {
>
>
>
>                 public Value determineAttributeX(Value element) throws 
> QueryException {
>
>
>
>                                 String query = "declare namespace nsx 
> = 'http://www.example.org/X';declare variable $elmt external; "
>
>                                                                 + "let 
> $elementWithAttributeX := $elmt/ancestor-or-self::*[@attributeX or 
> nsx:boundedBy/*/@attributeX][1] "
>
>                                                                 + 
> "return if
> (empty($elementWithAttributeX)) then trace((),'empty: ') "
>
>                                                                 + 
> "else
> if($elementWithAttributeX/@attributeX) then 
> trace($elementWithAttributeX/data(@attributeX),'on element: ') else "
>
>                                                                 +
> "trace($elementWithAttributeX/nsx:boundedBy/*/data(@attributeX),'indirectly:
> ')";
>
>
>
>                                 Context ctx = queryContext.context;
>
>
>
>                                 try (QueryProcessor qp = new 
> QueryProcessor(query, ctx)) {
>
>
>
>                                                 // Bind to context:
>
>                                                 qp.bind("elmt", 
> element);
>
>                                                 qp.context(element);
>
>
>
>                                                 Value value = 
> qp.value();
>
>
>
>                                                 return value;
>
>                                 }
>
>                 }
>
>
>
>                 public Value parse(Object arg) throws QueryException {
>
>
>
>                                 if (arg instanceof ANode) {
>
>
>
>                                                 ANode node = (ANode) 
> arg;
>
>
>
>                                                 Value attributeX = 
> determineAttributeX(node);
>
>                                                 return attributeX;
>
>
>
>                                 } else if (arg instanceof BXElem) {
>
>
>
>                                                 BXElem tmp = (BXElem) 
> arg;
>
>                                                 ANode node = 
> tmp.getNode();
>
>
>
>                                                 Value attributeX = 
> determineAttributeX(node);
>
>                                                 return attributeX;
>
>
>
>                                 } else {
>
>
>
>                                                 return Empty.SEQ;
>
>                                 }
>
>                 }
>
> }
>
>
>
>
>
> ----------- Test.xq:
>
>
>
> import module namespace mod = 'Test';
>
>
>
> declare namespace nsx = 'http://www.example.org/X';
>
> declare namespace nsy = 'http://www.example.org/Y';
>
>
>
> let $doc := doc('C:/BaseXTest/Test.xml')
>
> (:let $doc := <nsy:Collection
>
> xmlns:nsx='http://www.example.org/X' xmlns:nsy='http://www.example.org/Y'
>
> xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
>
> <nsx:boundedBy>
>
>   <nsx:OtherElement
>
>    attributeX='4979'/>
>
> </nsx:boundedBy>
>
> <nsy:member>
>
>   <nsx:Element
>
>    id='Element_1'>
>
>    <nsx:other>a b c</nsx:other>
>
>   </nsx:Element>
>
> </nsy:member>
>
> <nsy:member>
>
>   <nsx:Element
>
>    id='Element_2'
>
>    attributeX='4979'>
>
>    <nsx:other>a b c</nsx:other>
>
>   </nsx:Element>
>
> </nsy:member>
>
> <nsy:member>
>
>   <nsx:Element
>
>    id='Element_3'
>
>    attributeX='4979'>
>
>    <nsx:SubElement
>
>     id='SubElement_1'/>
>
>   </nsx:Element>
>
> </nsy:member>
>
> </nsy:Collection>:)
>
>
>
> let $elements := $doc//*[@id]
>
> return
>
> <test>
>
>   {
>
>    for $elmt in $elements
>
>   let $r := mod:parse($elmt)
>
>    return
>
>     <result
>
>      id='{$elmt/@id}'
>
>      attributeX='{$r}'/>
>
>   }
>
> </test>
>
>
>
>
>
>
>
> ---------- Test.xml:
>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
>
> <nsy:Collection xmlns:nsx="http://www.example.org/X";
> xmlns:nsy="http://www.example.org/Y";
>
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
>
> <nsx:boundedBy>
>
>   <nsx:OtherElement attributeX="4979"/>
>
> </nsx:boundedBy>
>
> <nsy:member>
>
>   <nsx:Element id="Element_1">
>
>    <nsx:other>a b c</nsx:other>
>
>   </nsx:Element>
>
> </nsy:member>
>
> <nsy:member>
>
>   <nsx:Element id="Element_2" attributeX="4979">
>
>    <nsx:other>a b c</nsx:other>
>
>   </nsx:Element>
>
> </nsy:member>
>
> <nsy:member>
>
>   <nsx:Element id="Element_3" attributeX="4979">
>
>    <nsx:SubElement id="SubElement_1"/>
>
>   </nsx:Element>
>
> </nsy:member>
>
> </nsy:Collection>
>
>
>
>
>
> ---------- UnitTest:
>
>
>
> import java.io.IOException;
>
> import java.nio.file.Files;
>
> import java.nio.file.Paths;
>
>
>
> import org.basex.core.BaseXException;
>
> import org.basex.core.Context;
>
> import org.basex.core.cmd.XQuery;
>
> import org.basex.query.QueryException;
>
>
>
> public final class ExecuteTestQuery {
>
>
>
>                 /** Database context. */
>
>                 private static Context context = new Context();
>
>
>
>                 /**
>
>                 * Runs the example code.
>
>                 * @param args (ignored) command-line arguments
>
>                 * @throws IOException if an error occurs while 
> serializing the results
>
>                 * @throws QueryException if an error occurs while 
> evaluating the query
>
>                 * @throws BaseXException if a database command fails
>
>                 */
>
>                 public static void main(final String[] args) throws 
> IOException, QueryException {
>
>
>
>                                 String xq = 
> "src/test/resources/test.xq";
>
>
>
>                                 // Evaluate the specified XQuery
>
>                                 String query = new 
> String(Files.readAllBytes(Paths.get(xq)));
>
>
>
>                                 XQuery xquery = new XQuery(query);
>
>
>
>                                 String result = 
> xquery.execute(context);
>
>
>
>                                 System.out.println(result);
>
>                 }
>
> }
>
>
>
> Von: Christian Grün [mailto:christian.gr...@gmail.com]
> Gesendet: Dienstag, 23. Mai 2017 14:25
> An: Johannes Echterhoff <echterh...@interactive-instruments.de>
> Cc: BaseX <basex-talk@mailman.uni-konstanz.de>
> Betreff: Re: AW: [basex-talk] Evaluating XPath within custom 
> QueryModule
>
>
>
> Could you please provide me with a little, seld-contained example?
>
>
>
> Thanks in advance,
>
> Christian
>
>
>
>
>
> Am 23.05.2017 14:14 schrieb "Johannes Echterhoff"
> <echterh...@interactive-instruments.de>:
>
> Hi Christian,
> Thank you. This is very useful.
> One issue, though: in my test, it looks like the ancestors of the 
> element that is processed by the query are not available/accessible. 
> What am I missing?
> Best regards,
> Johannes
>
>
> -----Ursprüngliche Nachricht-----
> Von: Christian Grün [mailto:christian.gr...@gmail.com]
> Gesendet: Dienstag, 23. Mai 2017 12:43
> An: Johannes Echterhoff <echterh...@interactive-instruments.de>
> Cc: basex-talk@mailman.uni-konstanz.de
> Betreff: Re: [basex-talk] Evaluating XPath within custom QueryModule
>
> Hi Johannes,
>
> Welcome to the list.
>
>> However, I wonder if it is possible to evaluate the expression also 
>> within the query module itself, i.e. when method “parse” is called. 
>> Is there a way to do so?
>
> Absolutely. You find some examples in [1].
>
> If you your class extends the QueryModule class – which is always 
> recommendable – a function could look as follows:
>
>   import org.basex.core.Context;
>   import org.basex.query.QueryModule;
>   import org.basex.query.QueryProcessor;
>   import org.basex.query.value.Value;
>
>   public class Module extends QueryModule {
>     public Value elementName(Value elem) throws Exception {
>       // Your query
>       String query =
>         "declare variable $elem external;" +
>         "name($elem), (: element bound to variable :)" +
>         "name(.) (: element bound to context :)";
>
>       Context ctx = queryContext.context;
>       QueryProcessor qp = new QueryProcessor(query, ctx);
>       // Bind to context:
>       qp.bind("elem", elem);
>       qp.context(elem);
>       Value value = qp.value();
>
>       return value;
>     }
>   }
>
> Hope this helps,
> Christian
>
> [1]
> https://github.com/BaseXdb/basex/blob/master/basex-examples/src/main/j
> ava/org/basex/examples/local/RunQueries.java

Reply via email to