diff --git a/rdflib/plugins/serializers/longturtle.py b/rdflib/plugins/serializers/longturtle.py index 2aaed36e6d..1e68e68495 100644 --- a/rdflib/plugins/serializers/longturtle.py +++ b/rdflib/plugins/serializers/longturtle.py @@ -22,7 +22,7 @@ from rdflib.compare import to_canonical_graph from rdflib.exceptions import Error -from rdflib.graph import Graph +from rdflib.graph import Graph, _TripleType from rdflib.namespace import RDF from rdflib.term import BNode, Literal, URIRef @@ -149,11 +149,20 @@ def serialize( self.base = None - def preprocessTriple(self, triple): + def preprocessTriple(self, triple: _TripleType) -> None: super(LongTurtleSerializer, self).preprocessTriple(triple) for i, node in enumerate(triple): - if node in self.keywords: - continue + if i == VERB: + if node in self.keywords: + # predicate is a keyword + continue + if ( + self.base is not None + and isinstance(node, URIRef) + and node.startswith(self.base) + ): + # predicate corresponds to base namespace + continue # Don't use generated prefixes for subjects and objects self.getQName(node, gen_prefix=(i == VERB)) if isinstance(node, Literal) and node.datatype: @@ -180,6 +189,8 @@ def getQName(self, uri, gen_prefix=True): prefix, namespace, local = parts + local = local.replace(r"(", r"\(").replace(r")", r"\)") + # QName cannot end with . if local.endswith("."): return None diff --git a/rdflib/plugins/serializers/turtle.py b/rdflib/plugins/serializers/turtle.py index d1dfcf4a67..abee2e43b4 100644 --- a/rdflib/plugins/serializers/turtle.py +++ b/rdflib/plugins/serializers/turtle.py @@ -263,9 +263,17 @@ def serialize( def preprocessTriple(self, triple: _TripleType) -> None: super(TurtleSerializer, self).preprocessTriple(triple) for i, node in enumerate(triple): - if i == VERB and node in self.keywords: - # predicate is a keyword - continue + if i == VERB: + if node in self.keywords: + # predicate is a keyword + continue + if ( + self.base is not None + and isinstance(node, URIRef) + and node.startswith(self.base) + ): + # predicate corresponds to base namespace + continue # Don't use generated prefixes for subjects and objects self.getQName(node, gen_prefix=(i == VERB)) if isinstance(node, Literal) and node.datatype: diff --git a/test/test_serializers/test_serializer_turtle_base_namespace.py b/test/test_serializers/test_serializer_turtle_base_namespace.py new file mode 100644 index 0000000000..f0971611d8 --- /dev/null +++ b/test/test_serializers/test_serializer_turtle_base_namespace.py @@ -0,0 +1,34 @@ +from rdflib import Graph, Namespace, URIRef + +# https://github.com/RDFLib/rdflib/issues/3237 +# Test that the ns1 prefix is not generated when the base is set. +mns = Namespace("http://my-namespace.net/") + + +def test_turtle(): + g = Graph(base="http://my-base.net/") + g.add((mns.foo, URIRef("http://my-base.net/my-predicate"), mns.bar)) + result = g.serialize(format="text/turtle") + assert ( + result + == """@base . + + . + +""" + ) + + +def test_longturtle(): + g = Graph(base="http://my-base.net/") + g.add((mns.foo, URIRef("http://my-base.net/my-predicate"), mns.bar)) + result = g.serialize(format="longturtle", canon=True) + assert ( + result + == """BASE + + + ; +. +""" + ), print(result)