Skip to main content

XQuery

@dortdb/lang-xquery adds XQuery to DortDB. It is the language for tree-shaped and XML-like data, such as DOM documents, parsed XML, and similar hierarchical structures, and it brings XPath path navigation together with FLWOR transformations.

XQuery works on sequences of values. Sequences never nest (a sequence of sequences is flattened), a single value is a sequence of length one, and an empty sequence stands in for "no value".

import { DortDB } from '@dortdb/core';
import { defaultRules } from '@dortdb/core/optimizer';
import { XQuery, DomDataAdapter } from '@dortdb/lang-xquery';

const db = new DortDB({
// in a browser, XQuery() picks up the global document automatically
mainLang: XQuery({ adapter: new DomDataAdapter(document) }),
optimizer: { rules: defaultRules },
});

const people = new DOMParser().parseFromString(
`<people>
<person age="30">Alice</person>
<person age="20">Bob</person>
</people>`,
'text/xml',
);
db.registerSource(['people'], people);

db.query('for $p in $people/people/person return string($p/@age)');
// data: ['30', '20']

db.query('for $p in $people/people/person[@age > 25] return string($p)');
// data: ['Alice']

FLWOR and sequences

FLWOR expressions (For, Let, Where, Order by, Return) stream data as named tuples between clauses, but a FLWOR expression as a whole produces a flattened sequence of items:

db.query('for $x in (1 to 3) let $y := $x * 10 return $y');
// data: [10, 20, 30]

Aggregation is done by passing a sequence to a function:

db.query('sum(1 to 10)'); // data: [55]

Path predicates can read the current context item (.), position (fn:position()), and size (fn:last()):

db.query('(5 to 10)[. mod 2 eq 1]'); // data: [5, 7, 9]

The DOM adapter

By default XQuery reads data through DomDataAdapter, which expects DOM globals (document, Node, and friends).

  • In the browser these are available, so XQuery() works directly.
  • In Node.js there is no DOM by default. Supply a document from a DOM implementation (e.g. jsdom), as in XQuery({ adapter: new DomDataAdapter(doc) }), and make the DOM globals available, or provide a custom adapter that targets your own data shape. See Data Sources & Adapters.

Learn more