使用 RDF4J 在加载和写入 TTL 文件时保留前缀

Keep prefixes in loading and writing TTL file with RDF4J

我需要加载一个 Turtle TTL 文件,添加一些三元组,然后再次保存。 原始 TTL 文件有一个很大的 header 包含一些命名空间的前缀。

@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/> .
...

加载文件并添加三元组后,保存的 TTL 将不包含前缀,除非我手动指定它们,一一指定。有没有办法让命名空间已经存在于加载的文件中?

这是我的 Java 代码:

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

问题是您用于写入文件的代码明确地只写入语句本身,而不是存储在您的 model 对象中的名称空间。

您可以通过添加如下内容来修复它:

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

但是,更一般地说,写入文件的代码比需要的更复杂。将 model 对象写入文件的一种更简单的方法是这样的:

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

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

或者如果您更喜欢使用 RDFWriter 对象(这样您就可以调整配置):

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

//... tweak writer config

Rio.write(model, writer);

这两个都是更短、更简单的代码,它们还为您处理命名空间。

同样,读取文件也可以更方便的完成:

// Load input TTL file
InputStream stream = new FileInputStream(ttlFile);
Model model = Rio.parse(stream, RDFFormat.TURTLE);