Skip to content

NamespaceManager.bind(prefix, namespace, replace=True) leaves existing prefix in place  #543

@Jeroen537

Description

@Jeroen537

I want to change an existing and bound namespace prefix. From the documentation of NamespaceManager I understand that "bind" with parameter "replace=True" should achieve this. However, while this does associate the namespace with the new prefix, the old prefix remains bound to the same namespace.
This can make it impossible to obtain a serialization with the new prefix. Is this intended behaviour?

Code example:

from rdflib import Graph, Namespace

g = Graph()

g.parse(data="""<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
   xmlns:ns1="http://somewhere/else#"
   xmlns:ns2="http://nowhere/else#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
  <rdf:Description rdf:about="http://somewhere/else#y">
    <ns2:Q rdf:resource="http://somewhere/else#z"/>
  </rdf:Description>
  <rdf:Description rdf:about="http://somewhere/else#root">
    <ns1:P rdf:resource="http://somewhere/else#y"/>
    <ns1:P rdf:resource="http://somewhere/else#x"/>
  </rdf:Description>
</rdf:RDF>
""")

for ns in g.namespaces():
    print('%s (%s)' % (ns))

# prints:
#
# xml (http://www.w3.org/XML/1998/namespace)
# ns2 (http://nowhere/else#)
# ns1 (http://somewhere/else#)
# rdfs (http://www.w3.org/2000/01/rdf-schema#)
# xsd (http://www.w3.org/2001/XMLSchema#)
# rdf (http://www.w3.org/1999/02/22-rdf-syntax-ns#)
#
# (as expected)

print(g.serialize().decode())

# prints:
#
# <?xml version="1.0" encoding="UTF-8"?>
# <rdf:RDF
#    xmlns:ns1="http://somewhere/else#"
#    xmlns:ns2="http://nowhere/else#"
#    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
# >
#   <rdf:Description rdf:about="http://somewhere/else#y">
#     <ns2:Q rdf:resource="http://somewhere/else#z"/>
#   </rdf:Description>
#   <rdf:Description rdf:about="http://somewhere/else#root">
#     <ns1:P rdf:resource="http://somewhere/else#y"/>
#     <ns1:P rdf:resource="http://somewhere/else#x"/>
#   </rdf:Description>
# </rdf:RDF>
#
# (as expected)

elseNS = Namespace('http://somewhere/else#') # same namespace as ns1 above

g.namespace_manager.bind('there', elseNS, replace=True) # attempt to rebind to other prefix

for ns in g.namespaces():
    print('%s (%s)' % (ns))    

# prints:
#
# xsd (http://www.w3.org/2001/XMLSchema#)
# there (http://somewhere/else#)
# rdfs (http://www.w3.org/2000/01/rdf-schema#)
# rdf (http://www.w3.org/1999/02/22-rdf-syntax-ns#)
# xml (http://www.w3.org/XML/1998/namespace)
# ns2 (http://nowhere/else#)
# ns1 (http://somewhere/else#)
#
# ("there" and "ns1" are bound to the same namespace)

print(g.serialize().decode())

# prints:
#
# <?xml version="1.0" encoding="UTF-8"?>
# <rdf:RDF
#    xmlns:ns1="http://somewhere/else#"
#    xmlns:ns2="http://nowhere/else#"
#    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
# >
#   <rdf:Description rdf:about="http://somewhere/else#root">
#     <ns1:P rdf:resource="http://somewhere/else#x"/>
#     <ns1:P rdf:resource="http://somewhere/else#y"/>
#   </rdf:Description>
#   <rdf:Description rdf:about="http://somewhere/else#y">
#     <ns2:Q rdf:resource="http://somewhere/else#z"/>
#   </rdf:Description>
# </rdf:RDF>
#
# (in the serialization "ns1" is used, not "there" as was intended)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions