@jahed/sparql-engine
Version:
SPARQL query engine for servers and web browsers.
104 lines • 3.68 kB
JavaScript
// SPDX-License-Identifier: MIT
import { isBoolean, isNull, isUndefined, map } from "lodash-es";
import { Pipeline } from "../engine/pipeline/pipeline.js";
import { Bindings } from "../rdf/bindings.js";
import { termIsBNode, termIsIRI, termIsLiteral } from "../utils/rdf.js";
function _writeBoolean(input, root) {
root.push({ boolean: input });
}
function _writeBindings(input, results) {
// convert sets of bindings into objects of RDF Terms
let bindings = input
.filter((value) => !isNull(value[1]) && !isUndefined(value[1]))
.reduce((obj, variable, value) => {
obj[variable] = value;
return obj;
}, {});
// Write the result tag for this set of bindings
results.push({
result: map(bindings, (value, variable) => {
let xmlTag;
if (termIsIRI(value)) {
xmlTag = { uri: value.value };
}
else if (termIsBNode(value)) {
xmlTag = { bnode: value.value };
}
else if (termIsLiteral(value)) {
if (value.language === "") {
xmlTag = {
literal: [{ _attr: { "xml:lang": value.language } }, value.value],
};
}
else {
xmlTag = {
literal: [
{ _attr: { datatype: value.datatype.value } },
value.value,
],
};
}
}
else {
throw new Error(`Unsupported RDF Term type: ${value}`);
}
return {
binding: [{ _attr: { name: variable.substring(1) } }, xmlTag],
};
}),
});
}
/**
* Formats query solutions (bindings or booleans) from a PipelineStage in W3C SPARQL XML format
* @see https://www.w3.org/TR/2013/REC-rdf-sparql-XMLres-20130321/
* @param source - Input pipeline
* @return A pipeline s-that yields results in W3C SPARQL XML format
*/
export default function xmlFormat(source) {
return Pipeline.getInstance().fromAsync(async (input) => {
const { default: xml } = await import("xml");
const results = xml.element({});
const root = xml.element({
_attr: { xmlns: "http://www.w3.org/2005/sparql-results#" },
results: results,
});
const stream = xml({ sparql: root }, { stream: true, indent: "\t", declaration: true });
try {
let warmup = true;
for await (const b of source) {
if (warmup && !isBoolean(b)) {
const variables = Array.from(b.variables());
root.push({
head: variables
.filter((name) => name !== "*")
.map((name) => {
return { variable: { _attr: { name } } };
}),
});
warmup = false;
}
if (isBoolean(b)) {
_writeBoolean(b, root);
}
else {
_writeBindings(b, results);
}
}
results.close();
root.close();
}
catch (error) {
console.error(error);
}
try {
for await (const data of stream) {
input.next(data.toString("utf-8"));
}
input.complete();
}
catch (error) {
input.error(error);
}
});
}
//# sourceMappingURL=xml-formatter.js.map