RDF Core
Parse, serialize, and query RDF graphs and datasets.
W3C RDF 1.1 compliant core library for Dart.
Getting Started
Install the package
dart pub add locorda_rdf_core import 'package:locorda_rdf_core/core.dart';
void main() {
final turtleData = '''
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
<http://example.org/alice> foaf:name "Alice"@en .
''';
final graph = turtle.decode(turtleData);
print('Triples: ${graph.triples.length}'); // Triples: 1
} import 'package:locorda_rdf_core/core.dart';
void main() {
// Create individual triples
final alice = const IriTerm('http://example.org/alice');
final foafName = const IriTerm('http://xmlns.com/foaf/0.1/name');
final foafAge = const IriTerm('http://xmlns.com/foaf/0.1/age');
final triple = Triple(alice, foafName, LiteralTerm.string('Alice'));
// Create graph from triples
final graph = RdfGraph(triples: [triple]);
print('Created graph with ${graph.triples.length} triple(s)');
// Add more triples (immutable - returns new graph)
final updatedGraph = graph.withTriple(
Triple(alice, foafAge, LiteralTerm.integer(30)),
);
print('Updated graph has ${updatedGraph.triples.length} triples');
// Note: For parsing, use turtle.decode(data) instead
print('\nTurtle output:');
print(turtle.encode(updatedGraph));
} import 'package:locorda_rdf_core/core.dart';
void main() {
// Create quads with graph context
final alice = const IriTerm('http://example.org/alice');
final bob = const IriTerm('http://example.org/bob');
final foafName = const IriTerm('http://xmlns.com/foaf/0.1/name');
final foafKnows = const IriTerm('http://xmlns.com/foaf/0.1/knows');
final peopleGraph = const IriTerm('http://example.org/graphs/people');
final quads = [
Quad(alice, foafName, LiteralTerm.string('Alice')), // default graph
Quad(alice, foafKnows, bob, peopleGraph), // named graph
Quad(bob, foafName, LiteralTerm.string('Bob'), peopleGraph), // named graph
];
// Create dataset from quads
final dataset = RdfDataset.fromQuads(quads);
// Encode to N-Quads
final nquadsData = nquads.encode(dataset);
print('N-Quads output:');
print(nquadsData);
// Decode N-Quads back to dataset
final decodedDataset = nquads.decode(nquadsData);
// Access default and named graphs
print(
'Default graph has ${decodedDataset.defaultGraph.triples.length} triples');
print('Dataset has ${decodedDataset.namedGraphs.length} named graphs');
for (final namedGraph in decodedDataset.namedGraphs) {
print(
'Named graph ${namedGraph.name} has ${namedGraph.graph.triples.length} triples');
}
} import 'package:locorda_rdf_core/core.dart';
void main() {
// Start with a graph
final alice = const IriTerm('http://example.org/alice');
final bob = const IriTerm('http://example.org/bob');
final charlie = const IriTerm('http://example.org/charlie');
final foafKnows = const IriTerm('http://xmlns.com/foaf/0.1/knows');
final graph = RdfGraph(triples: [
Triple(alice, foafKnows, bob),
Triple(bob, foafKnows, charlie),
]);
// Query: Find all "knows" relationships
final knowsTriples = graph.findTriples(predicate: foafKnows);
print('People who know someone:');
for (final triple in knowsTriples) {
print(' ${triple.subject} knows ${triple.object}');
}
// Update: Add new triple (returns new immutable graph)
final updatedGraph = graph.withTriple(Triple(alice, foafKnows, charlie));
print('\nTotal triples: ${updatedGraph.triples.length}');
// Check existence
if (updatedGraph.hasTriples(subject: alice, object: charlie)) {
print('Alice knows Charlie!');
}
} import 'package:locorda_rdf_core/core.dart';
void main() {
// Example: Decode a JSON-LD document
final jsonLdData = '''
{
"@context": {
"name": "http://xmlns.com/foaf/0.1/name",
"knows": {
"@id": "http://xmlns.com/foaf/0.1/knows",
"@type": "@id"
},
"Person": "http://xmlns.com/foaf/0.1/Person"
},
"@id": "http://example.org/alice",
"@type": "Person",
"name": "Alice",
"knows": [
{
"@id": "http://example.org/bob",
"@type": "Person",
"name": "Bob"
}
]
}
''';
// Using the convenience global variable
final graph = jsonldGraph.decode(jsonLdData);
// Print decoded triples
print('Decoded ${graph.triples.length} triples:');
for (final triple in graph.triples) {
print('${triple.subject} ${triple.predicate} ${triple.object}');
}
// Encode the graph back to JSON-LD
final serialized = jsonldGraph.encode(graph);
print('\nEncoded JSON-LD:');
print(serialized);
} import 'package:locorda_rdf_core/core.dart';
void main() {
final turtleData = '''
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
<http://example.org/alice> foaf:name "Alice" ;
foaf:age 30 .
''';
// Parse Turtle
final graph = rdf.decode(turtleData, contentType: 'text/turtle');
print('Parsed ${graph.triples.length} triples');
// Convert to JSON-LD
final jsonld = rdf.encode(graph, contentType: 'application/ld+json');
print('\nJSON-LD:\n$jsonld');
// Convert to N-Triples
final ntriples = rdf.encode(graph, contentType: 'application/n-triples');
print('\nN-Triples:\n$ntriples');
} // ignore_for_file: unused_local_variable
import 'package:locorda_rdf_core/core.dart';
// import 'package:locorda_rdf_xml/xml.dart';
void main() {
// Example 1: Customize Turtle parsing for SPARQL-style syntax
print('1. Custom Turtle codec for SPARQL-style files:');
final sparqlStyleTurtle = TurtleCodec(
decoderOptions: TurtleDecoderOptions(
parsingFlags: {
TurtleParsingFlag.allowMissingDotAfterPrefix,
TurtleParsingFlag.allowPrefixWithoutAtSign,
},
),
);
final customRdf = RdfCore.withCodecs(codecs: [
sparqlStyleTurtle,
NTriplesCodec(),
]);
// Parse SPARQL-style Turtle (no @ before PREFIX, no . after prefix)
final sparqlData = '''
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
<http://example.org/alice> foaf:name "Alice" .
''';
final graph = customRdf.decode(sparqlData, contentType: 'text/turtle');
print(' Parsed ${graph.triples.length} triples from SPARQL-style syntax\n');
// Example 2: Add RDF/XML support via extension package
print('2. Extending with RDF/XML support:');
final xmlRdf = RdfCore.withCodecs(codecs: [
TurtleCodec(),
NTriplesCodec(),
// RdfXmlCodec(), // from locorda_rdf_xml package
]);
final xmlData = '''
<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:foaf="http://xmlns.com/foaf/0.1/">
<rdf:Description rdf:about="http://example.org/alice">
<foaf:name>Alice</foaf:name>
</rdf:Description>
</rdf:RDF>
''';
// final xmlGraph = xmlRdf.decode(xmlData, contentType: 'application/rdf+xml');
// print(' Parsed ${xmlGraph.triples.length} triples from RDF/XML');
print(' Add locorda_rdf_xml to pubspec.yaml for RDF/XML support');
print(' Extensible architecture: any codec can be added!');
} What Can You Build?
ποΈ Knowledge Graphs
Build semantic knowledge bases with typed relationships. Perfect for domain modeling, ontologies, and linked data applications.
π Data Integration
Merge data from multiple sources into a unified graph. Transform between formats (Turtle β JSON-LD β N-Triples) seamlessly.
οΏ½ In-Memory Graph Queries
Graph queries with O(1) subject lookups. Automatic indexing makes complex queries efficient for datasets that fit in RAM.
Key Features
Automatic Performance Optimization
Lazy indexing provides O(1) subject-based queries with zero memory cost until first use. Queries benefit from transparent performance improvements.
Developer-Friendly API
Global convenience variables (turtle, jsonld, ntriples) make parsing trivial. Fluent APIs for graph composition and chaining.
Multiple Formats
Parse and serialize Turtle, N-Triples, N-Quads, and JSON-LD. W3C RDF 1.1 compliant.
Full Dataset Support
Work with named graphs and datasets. Complete quad support for N-Quads with RDF 1.1 Dataset compliance.
Type-Safe
Strongly-typed Dart APIs with full IDE support and autocompletion. Catch errors at compile time.
Zero Dependencies
No external dependencies except logging. Clean, maintainable codebase.
Yeah fine, but:
π "I want to work with Person and Book, not Triples"
β Use mapper (annotations + generator)
Define your domain model with annotations. The generator creates bidirectional mappings between your classes and RDF.
π "Do you support XML?"
β Yes, via xml
Full RDF/XML encoder and decoder for legacy format support and interoperability with older systems.
π© "Typing IRIs is hell"
β Use terms and vocabularies
Type-safe constants for Schema.org, FOAF, Dublin Core, and more. Never typo a property URI again.
π "Can you canonicalize?"
β Yes, canonicalization
RDF-CANON (RDFC-1.0) support for canonical serialization, reliable graph comparison, and cryptographic signing.
Ready to Start?
Read the documentation or explore other RDF packages.