Skip to content
Advertisement

Keep prefixes in loading and writing TTL file with RDF4J

I need to load a Turtle TTL file, add some triples, then save it again. The original TTL file has a big header containing the prefixes for some namespaces.

@prefix biro: <http://purl.org/spar/biro/> .
@prefix c4o: <http://purl.org/spar/c4o/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix deo: <http://purl.org/spar/deo/> .
@prefix doco: <http://purl.org/spar/doco/> .
...

After I load the file and add the triples, the saved TTL won’t contain the prefixes, unless I specify them manually, one by one. Is there a way to keep the namespaces already present in the loaded file?

This is my Java code:

// Load input TTL file
InputStream stream = new FileInputStream(ttlFile);
RDFParser rdfParser = Rio.createParser(RDFFormat.TURTLE);
Model model = new LinkedHashModel();
rdfParser.setRDFHandler(new StatementCollector(model));
rdfParser.parse(stream);
stream.close();

// Code to add triples here
model.add(...);

// Save the new TTL file
FileOutputStream out = new FileOutputStream(ttlOutputFile);
RDFWriter writer = Rio.createWriter(RDFFormat.TURTLE, out);
writer.startRDF();

// Here I can add the prefixes manually
// writer.handleNamespace("dcterms", DCTERMS.NAMESPACE);

for (Statement st : model) {
    writer.handleStatement(st);
}
writer.endRDF();

Advertisement

Answer

The problem is that your code for writing to file explicitly only writes the statements themselves, not the namespaces stored in your model object.

You could fix it by adding something like this:

model.getNamespaces().forEach(ns -> writer.handleNamespace(ns.getPrefix(), ns.getName()));

However, more generally, your code to write to file is more complex than it needs to be. A far simpler approach to writing your model object to file would be something like this:

// Save the new TTL file
FileOutputStream out = new FileOutputStream(ttlOutputFile);

Rio.write(model, out, RDFFormat.TURTLE);

or if you prefer to use a RDFWriter object (so you can tweak the config):

RDFWriter writer = Rio.createWriter(out, RDFFormat.TURTLE);

//... tweak writer config

Rio.write(model, writer);

Both of these are shorter, easier code, and they take care of namespace handling for you as well.

Similarly, reading the file can also be done more conveniently:

// Load input TTL file
InputStream stream = new FileInputStream(ttlFile);
Model model = Rio.parse(stream, RDFFormat.TURTLE);
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement