Replacing blank node IDs

Skip to first unread message


Mar 18, 2021, 8:54:32 PM3/18/21
I've Triples extracted from the web like:

<> .
_:na43d612388514fcfaaa74771e40a879cxb0 <>
_:na43d612388514fcfaaa74771e40a879cxb2 .
_:na43d612388514fcfaaa74771e40a879cxb0 <> "925872" .
_:na43d612388514fcfaaa74771e40a879cxb0 <>
"Executive Anvil" .

but would like to replace the blank node IDs with non-blank IDs that
reflect the URI where the data came from. I've loaded the data in a
RDF4J Model successfully but don't know if what I want to do is
possible or how to proceed from there.

Thanking you in advance for your help and suggestions, Simon.

Jeen Broekstra

Mar 18, 2021, 11:26:16 PM3/18/21
to RDF4J Users
Off the top of my head a simple way to do this for a Model is something like this:

Model model = ... // your model with blank nodes
Model converted = -> convert(st)).collect(ModelCollector.toModel());

Statement convert(Statement st) {
        var subject = st.getSubject();
        var object = st.getObject();
        if (!(subject.isBNode() || object.isBNode())) {            
            return st;

        IRI newSubject = subject.isBNode() ? Values.iri("", subject.stringValue()) : (IRI) subject;
        Value newObject = object.isBNode() ? Values.iri("", object.stringValue()) : object;

        return Values.statement(newSubject, st.getPredicate(), newObject, st.getContext());

Of course, what's also possible is to do the conversion while parsing (so before you even have created a Model object for it), something like this:
        RDFParser parser = Rio.createParser(RDFFormat.TURTLE);
        parser.getParserConfig().set(BasicParserSettings.SKOLEMIZE_ORIGIN, "");

        Model model = new TreeModel();
        parser.setRDFHandler(new StatementCollector(model));

        model.forEach(System.out::println); // will print out the model to show all bnodes converted to IRIs



simon t

Mar 19, 2021, 8:42:20 PM3/19/21
to RDF4J Users
I wanted more control of the IDs than SKOLEMIZE_ORIGIN provided so went something closer to the convert() approach, streaming and map-ing worked great.

Thanks for saving me some time figuring this out, Simon
Reply all
Reply to author
0 new messages