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