Skip to content

This is a library I use for working with namespaces, principally within MarkLogic, but it can be adapted for different systems.

License

Notifications You must be signed in to change notification settings

kurtcagle/namespaceManager

Repository files navigation

NamespaceManager JavaScript Class

A JavaScript port of the XQuery ns module for managing RDF namespaces, SPARQL operations, and namespace translations in MarkLogic environments.

Files

  • NamespaceManager.js - Main class implementation
  • NamespaceManager.examples.js - Usage examples
  • test-sparql-params.js - Test file demonstrating parameter injection
  • README.md - This documentation file

Key Features

Core Functionality

  • 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

NEW: Parameterized SPARQL Queries

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.

How It Works

  1. Add a #@params marker in your SPARQL query where you want the VALUES clauses to be inserted
  2. Pass a parameters object as the second argument to sparql() or update()
  3. The class automatically formats values based on their type and generates appropriate VALUES clauses

Parameter Type Handling

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

Example Usage

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')
});

Generated VALUES Clauses

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> }

Query Generation Without Execution

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

Usage Example

// 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);

Comparison: generate vs execute

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.

Basic Usage (Non-MarkLogic Features)

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);

MarkLogic Integration

For SPARQL execution and phonetic search, initialize with MarkLogic modules:

nsManager.initializeModules({
    sem: require('/MarkLogic/semantics'),
    spell: require('/MarkLogic/spell'),
    xdmp: xdmp
});

Default Namespaces

The class includes default namespace mappings for Syngenta's data model:

  • chemical: Chemical substances definitions
  • substances: Chemical substance instances
  • organisms: Organism definitions
  • products: Product definitions
  • study: Study definitions
  • rdf, rdfs, owl: Standard W3C vocabularies
  • sh: SHACL vocabulary
  • And many more...

API Reference

Core Methods

  • ns() - Get current namespace map
  • get(prefix) - Get namespace URI from prefix
  • prefix(namespace) - Get prefix from namespace URI
  • curie(iri, [ns]) - Convert IRI to CURIE
  • ciri(curie, [ns]) - Convert CURIE to IRI
  • split(iri, [ns]) - Split IRI into namespace and local name

SPARQL Methods

  • prolog([ns]) - Generate SPARQL PREFIX declarations
  • generateSparql(query, [params]) - Generate complete SPARQL query string WITHOUT execution
  • generateUpdate(query, [params]) - Generate complete SPARQL UPDATE string WITHOUT execution
  • sparql(query, [params], [properties]) - Execute parameterized SPARQL query
  • update(query, [params], [properties]) - Execute parameterized SPARQL update
  • shacl([ns]) - Generate SHACL namespace declarations

Management Methods

  • addPrefix(prefix, namespace) - Add new namespace mapping
  • deletePrefix(prefix) - Remove namespace mapping
  • isValidCurie(curie, [ns]) - Check if CURIE has valid prefix
  • reset() - Reset to default namespace mappings
  • save(ns) - Save namespace map to storage

Translation Methods

  • translate(turtle, [ns]) - Translate Turtle between namespace conventions
  • extractMap(turtle) - Extract namespace declarations from Turtle
  • describe(iri, [ns]) - SPARQL DESCRIBE query (requires MarkLogic)
  • soundsLike(prompt) - Phonetic search (requires MarkLogic)

Utility Methods

  • toJson([ns]) - Convert namespace map to JSON
  • fromJson(json) - Parse JSON to namespace map

License

Based on original XQuery code by Kurt Cagle. JavaScript port maintains the same functionality for use in Node.js and browser environments.

About

This is a library I use for working with namespaces, principally within MarkLogic, but it can be adapted for different systems.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published