A JavaScript port of the XQuery ns module for managing RDF namespaces, SPARQL operations, and namespace translations in MarkLogic environments.
NamespaceManager.js- Main class implementationNamespaceManager.examples.js- Usage examplestest-sparql-params.js- Test file demonstrating parameter injectionREADME.md- This documentation file
- Namespace Management: Get/set namespace URIs and prefixes
- CURIE/IRI Conversion: Convert between compact URIs and full IRIs
- SPARQL Prolog Generation: Create namespace declarations for SPARQL queries
- SHACL Support: Generate SHACL prefix declarations
- Turtle Translation: Transform Turtle RDF between different namespace conventions
- Namespace Extraction: Parse namespace declarations from Turtle documents
- SPARQL Parameter Injection: Support for parameterized SPARQL queries with VALUES clauses
The sparql() and update() methods now support parameter injection using VALUES clauses. This allows for safe, parameterized SPARQL queries similar to prepared statements in SQL.
- Add a
#@paramsmarker in your SPARQL query where you want the VALUES clauses to be inserted - Pass a parameters object as the second argument to
sparql()orupdate() - The class automatically formats values based on their type and generates appropriate VALUES clauses
The class automatically detects and formats different value types:
| JavaScript Type | Example | SPARQL Format |
|---|---|---|
| CURIE | 'chemical:Substance' |
<http://data.syngenta.org/def/chemical-substances/Substance> |
| String (plain) | 'benzene' |
"benzene" |
| String (quoted) | '"Aspirin"@en' |
"Aspirin"@en |
| IRI | '<http://example.org>' |
<http://example.org> |
| Number (integer) | 100 |
"100"^^xsd:integer |
| Number (decimal) | 150.5 |
"150.5"^^xsd:decimal |
| Date string | '2024-01-15' |
"2024-01-15"^^xsd:date |
| DateTime string | '2024-01-15T10:30:00Z' |
"2024-01-15T10:30:00Z"^^xsd:dateTime |
| Boolean | true |
"true"^^xsd:boolean |
| Date object | new Date() |
"2024-01-15T..."^^xsd:dateTime |
| Array | ['val1', 'val2'] |
Multiple values in VALUES clause |
const NamespaceManager = require('./NamespaceManager');
const nsManager = new NamespaceManager();
// Initialize with MarkLogic modules (required for execution)
nsManager.initializeModules({
sem: require('/MarkLogic/semantics'),
xdmp: xdmp
});
// Parameterized SELECT query
const query = `
#@params
SELECT ?substance ?label ?weight
WHERE {
?substance rdf:type ?type ;
rdfs:label ?label ;
chemical:molecularWeight ?weight .
FILTER(?weight > ?minWeight && ?weight < ?maxWeight)
}
ORDER BY ?weight
`;
const results = nsManager.sparql(query, {
type: 'chemical:Pesticide', // CURIE - expanded to full IRI
minWeight: 200, // Integer
maxWeight: 500 // Integer
});
// Parameterized UPDATE query
const updateQuery = `
#@params
INSERT DATA {
GRAPH ?graph {
?substance rdf:type ?type ;
rdfs:label ?label ;
chemical:registeredDate ?date .
}
}
`;
nsManager.update(updateQuery, {
graph: '<http://data.syngenta.org/graphs/substances>',
substance: 'substances:new-compound',
type: 'chemical:ActiveIngredient',
label: '"New Compound"@en',
date: new Date('2024-01-15')
});For the above SELECT query, the following VALUES clauses would be generated:
VALUES ?type { <http://data.syngenta.org/def/chemical-substances/Pesticide> }
VALUES ?minWeight { "200"^^<http://www.w3.org/2001/XMLSchema#integer> }
VALUES ?maxWeight { "500"^^<http://www.w3.org/2001/XMLSchema#integer> }The generateSparql() and generateUpdate() methods allow you to generate complete SPARQL queries with all transformations applied, WITHOUT executing them. This is useful for:
- Debugging: See exactly what query will be executed
- Logging: Store queries for audit trails
- Testing: Verify query generation logic
- Documentation: Show examples of generated queries
- Dry-run operations: Preview before execution
// Define your query with parameters placeholder
const query = `
#@params
SELECT ?substance ?label
WHERE {
?substance rdf:type ?type ;
rdfs:label ?label .
}
`;
const params = {
type: 'chemical:Pesticide'
};
// Generate without executing
const generatedQuery = nsManager.generateSparql(query, params);
console.log(generatedQuery); // Shows complete SPARQL with prefixes and VALUES
// When ready, execute the same query
const results = nsManager.sparql(query, params);| Method | Returns | Executes | Use Case |
|---|---|---|---|
generateSparql() |
SPARQL string | No | Preview, debug, log |
generateUpdate() |
UPDATE string | No | Preview, debug, log |
sparql() |
Query results | Yes | Get data from triple store |
update() |
Update result | Yes | Modify data in triple store |
The generateSparql() and generateUpdate() methods internally perform all the same transformations as their execution counterparts:
- Add namespace PREFIX declarations
- Inject VALUES clauses for parameters
- Expand CURIEs to full IRIs
- Add proper type annotations to literals
They simply return the generated string instead of executing it against the triple store.
Most features work without MarkLogic modules:
const NamespaceManager = require('./NamespaceManager');
const nsManager = new NamespaceManager();
// Get namespace from prefix
const rdfNs = nsManager.get('rdf');
// Returns: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
// Convert IRI to CURIE
const curie = nsManager.curie('http://data.syngenta.org/chem/chemical-substances/aspirin');
// Returns: 'substances:aspirin'
// Convert CURIE to IRI
const iri = nsManager.ciri('chemical:benzene');
// Returns: 'http://data.syngenta.org/def/chemical-substances/benzene'
// Generate SPARQL prolog
const prolog = nsManager.prolog();
// Returns PREFIX declarations for all registered namespaces
// Translate Turtle between namespace conventions
const translatedTurtle = nsManager.translate(sourceTurtle);For SPARQL execution and phonetic search, initialize with MarkLogic modules:
nsManager.initializeModules({
sem: require('/MarkLogic/semantics'),
spell: require('/MarkLogic/spell'),
xdmp: xdmp
});The class includes default namespace mappings for Syngenta's data model:
chemical: Chemical substances definitionssubstances: Chemical substance instancesorganisms: Organism definitionsproducts: Product definitionsstudy: Study definitionsrdf,rdfs,owl: Standard W3C vocabulariessh: SHACL vocabulary- And many more...
ns()- Get current namespace mapget(prefix)- Get namespace URI from prefixprefix(namespace)- Get prefix from namespace URIcurie(iri, [ns])- Convert IRI to CURIEciri(curie, [ns])- Convert CURIE to IRIsplit(iri, [ns])- Split IRI into namespace and local name
prolog([ns])- Generate SPARQL PREFIX declarationsgenerateSparql(query, [params])- Generate complete SPARQL query string WITHOUT executiongenerateUpdate(query, [params])- Generate complete SPARQL UPDATE string WITHOUT executionsparql(query, [params], [properties])- Execute parameterized SPARQL queryupdate(query, [params], [properties])- Execute parameterized SPARQL updateshacl([ns])- Generate SHACL namespace declarations
addPrefix(prefix, namespace)- Add new namespace mappingdeletePrefix(prefix)- Remove namespace mappingisValidCurie(curie, [ns])- Check if CURIE has valid prefixreset()- Reset to default namespace mappingssave(ns)- Save namespace map to storage
translate(turtle, [ns])- Translate Turtle between namespace conventionsextractMap(turtle)- Extract namespace declarations from Turtledescribe(iri, [ns])- SPARQL DESCRIBE query (requires MarkLogic)soundsLike(prompt)- Phonetic search (requires MarkLogic)
toJson([ns])- Convert namespace map to JSONfromJson(json)- Parse JSON to namespace map
Based on original XQuery code by Kurt Cagle. JavaScript port maintains the same functionality for use in Node.js and browser environments.