0

I'm looking to run arbitrary XQuery code from Java. Oracle gives this example:

    OXQDataSource ds = new OXQDataSource();
    XQConnection con = ds.getConnection();
    String query = "<hello-world>{1 + 1}</hello-world>";
    XQPreparedExpression expr = con.prepareExpression(query);
    XQSequence result = expr.executeQuery();

Should that not also be possible through BaseX? To my understanding, BaseX is quite compliant with XQuery.

From the CLI arbitrary XQuery code:

thufir@dur:~/basex$ 
thufir@dur:~/basex$ basex fetch.books.html.xq 
[warning] /usr/bin/basex: Unable to locate /usr/share/java/jing.jar in /usr/share/java
<html xmlns="http://www.w3.org/1999/xhtml" class="no-js" lang="en-us">
  <head>
    <title>
    All products | Books to Scrape - Sandbox
</title>
..        
    </body>
</html>thufir@dur:~/basex$ 
thufir@dur:~/basex$ 
thufir@dur:~/basex$ cat fetch.books.html.xq 


fetch:xml(
  'http://books.toscrape.com/',
  map {
    'parser': 'html',
    'htmlparser': map { 'nons': false() }
  }
)
thufir@dur:~/basex$ 

Other, non-proprietary XQuery code runs through BaseX as expected.

While this will populate the database:

package org.basex.examples.local;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.Properties;
import java.util.logging.Logger;
import org.basex.core.BaseXException;
import org.basex.core.Context;
import org.basex.core.Databases;
import org.basex.core.cmd.CreateDB;
import org.basex.core.cmd.List;
import org.basex.core.cmd.Set;
import org.basex.util.list.StringList;

public class Scraper {

    private static final Logger LOG = Logger.getLogger(App.class.getName());
    private Properties properties = new Properties();
    private URL url = null;
    private String databaseName = null;
    private Context context = null;
    private String parserType = null;

    private Scraper() {
    }

    public Scraper(Properties properties) {
        this.properties = properties;
        LOG.fine(properties.toString());
    }

    public void init() throws MalformedURLException {
        parserType = properties.getProperty("parserType");
        url = new URL(properties.getProperty(parserType + "URL"));
        databaseName = properties.getProperty("databaseName");
        context = new Context();
    }

    private void list() throws BaseXException {
        LOG.info(new List().execute(context));
    }

    private void drop() throws BaseXException {
        list();
        new Set("parser", parserType).execute(context);
        new CreateDB(databaseName, url.toString()).execute(context);
        list();
    }

    private void create() throws BaseXException {
        list();
        new Set("parser", parserType).execute(context);
        new CreateDB(databaseName, url.toString()).execute(context);
        LOG.info(new List().execute(context));
        list();
    }

    private void infoOnDatabases() {
        Databases databases = context.databases();
        StringList stringListOfDatabases = databases.listDBs();
        String currentDatabaseName = null;

        Iterator<String> databaseIterator = stringListOfDatabases.iterator();

        while (databaseIterator.hasNext()) {
            currentDatabaseName = databaseIterator.next();
            LOG.info(currentDatabaseName);
            //xQuery here..
        }
    }

    public void fetch() throws BaseXException, MalformedURLException {
        drop();
        create();
        infoOnDatabases();
        list();
        context.close();
    }

}

it's rather limited.

reference:

http://docs.basex.org/wiki/Java_Examples

https://github.com/BaseXdb/basex/blob/master/basex-examples/src/main/java/org/basex/examples/local/RunQueries.java

https://stackoverflow.com/a/44638635/262852

https://docs.oracle.com/database/121/ADXDK/adx_j_xqj.htm#ADXDK115

Thufir
  • 8,216
  • 28
  • 125
  • 273
  • 2
    If you want to use that API then I think https://github.com/BaseXdb/basex/blob/master/basex-examples/src/main/java/org/basex/examples/xqj/XQJQuery.java is the relevant example in the BaseX examples section. I am not sure however https://en.wikipedia.org/wiki/XQuery_API_for_Java got ever updated for XQuery 3 or 3.1 so using the native API of your XQuery database processor or processor in general these days might give you more flexibility and easy access to the richer type system (maps, arrays) of XQuery 3.1. – Martin Honnen Jan 03 '19 at 06:46

1 Answers1

0

Simplest possible query result:

thufir@dur:~/NetBeansProjects/helloWorldBaseX$ 
thufir@dur:~/NetBeansProjects/helloWorldBaseX$ gradle clean run

> Task :run
Jan 02, 2019 7:44:16 PM org.basex.examples.local.DatabaseQuery runQuery
INFO: name           Resources  Size  Input Path                              
----------------------------------------------------------------------
w3school_data  1          5178  https://www.w3schools.com/xml/note.xml  

1 Databases.

Jan 02, 2019 7:44:16 PM org.basex.examples.local.DatabaseQuery runQuery
INFO: Don't forget me this weekend!
Jan 02, 2019 7:44:16 PM org.basex.examples.local.DatabaseQuery runQuery
INFO: query was                 //note/body/text()

BUILD SUCCESSFUL in 1s
4 actionable tasks: 3 executed, 1 up-to-date
thufir@dur:~/NetBeansProjects/helloWorldBaseX$ 

Java:

package org.basex.examples.local;

import java.net.MalformedURLException;
..
import org.basex.core.cmd.XQuery;

public class DatabaseQuery {

    private static final Logger LOG = Logger.getLogger(App.class.getName());
    private Properties properties = new Properties();
    private URL url = null;
    private String databaseName = null;
    private Context context = null;
    private String parserType = null;

    private DatabaseQuery() {
    }

    public DatabaseQuery(Properties properties) {
        this.properties = properties;
        LOG.fine(properties.toString());
    }

    public void init() throws MalformedURLException {
        parserType = properties.getProperty("parserType");
        url = new URL(properties.getProperty(parserType + "URL"));
        databaseName = properties.getProperty("databaseName");
        context = new Context();
    }

    public void runQuery(String query) throws BaseXException {
        new Open(databaseName).execute(context);
        LOG.info(new List().execute(context));
        LOG.info(new XQuery(query).execute(context));
        LOG.info("query was\t\t\t" + query);
        context.close();
    }

}

(Same class, a configuration parameter fetches xml which was more readable for me to query against.)

The query method from:

https://github.com/BaseXdb/basex/blob/master/basex-examples/src/main/java/org/basex/examples/local/RunQueries.java

Thufir
  • 8,216
  • 28
  • 125
  • 273
  • 1
    The code segments are long enough that it's a bit tricky to parse out exactly what changed between the question and answer -- any chance of calling that out? (Similarly, if it's possible to cull some of the helpers and still have code complete enough to act as a reproducer, that would help improve focus, and thus ease-of-comprehension). – Charles Duffy Jan 03 '19 at 03:26
  • bit messy, I know. – Thufir Jan 03 '19 at 03:44