0
# Identifiers and Namespaces
1
2
System for creating and managing globally unique identifiers using qualified names and namespaces, following URI and W3C standards. This system enables unambiguous identification of PROV elements across different documents and systems.
3
4
## Capabilities
5
6
### Identifier
7
8
Base class for all identifiers, representing xsd:anyURI.
9
10
```python { .api }
11
class Identifier:
12
def __init__(self, uri: str):
13
"""
14
Create an identifier from a URI string.
15
16
Args:
17
uri (str): URI string for the identifier
18
"""
19
20
@property
21
def uri(self) -> str:
22
"""
23
The URI associated with this identifier.
24
25
Returns:
26
str: The URI representing the resource identifier
27
"""
28
29
def provn_representation(self) -> str:
30
"""
31
Get the PROV-N representation of this identifier.
32
33
Returns:
34
str: The PROV-N representation of the URI
35
"""
36
37
def __str__(self) -> str:
38
"""String representation returns the URI."""
39
40
def __eq__(self, other) -> bool:
41
"""Equality based on URI comparison."""
42
43
def __hash__(self) -> int:
44
"""Hash based on URI and class."""
45
```
46
47
### QualifiedName
48
49
Qualified names combining a namespace with a local part, providing compact representation of URIs.
50
51
```python { .api }
52
class QualifiedName(Identifier):
53
def __init__(self, namespace: Namespace, localpart: str):
54
"""
55
Create a qualified name from namespace and local part.
56
57
Args:
58
namespace (Namespace): The namespace object
59
localpart (str): The local part of the qualified name
60
"""
61
62
@property
63
def namespace(self) -> Namespace:
64
"""
65
The namespace object for this qualified name.
66
67
Returns:
68
Namespace: Associated namespace
69
"""
70
71
@property
72
def localpart(self) -> str:
73
"""
74
The local part of this qualified name.
75
76
Returns:
77
str: Local part string
78
"""
79
80
def provn_representation(self) -> str:
81
"""
82
Get the PROV-N representation of this qualified name.
83
84
Returns:
85
str: PROV-N representation (e.g., 'prefix:localpart')
86
"""
87
88
def __str__(self) -> str:
89
"""String representation in prefix:localpart format."""
90
```
91
92
### Namespace
93
94
Namespace management for creating qualified names and managing URI prefixes.
95
96
```python { .api }
97
class Namespace:
98
def __init__(self, prefix: str, uri: str):
99
"""
100
Create a namespace with prefix and URI.
101
102
Args:
103
prefix (str): Short prefix for the namespace
104
uri (str): Full URI for the namespace
105
"""
106
107
@property
108
def prefix(self) -> str:
109
"""
110
The prefix string for this namespace.
111
112
Returns:
113
str: Namespace prefix
114
"""
115
116
@property
117
def uri(self) -> str:
118
"""
119
The URI string for this namespace.
120
121
Returns:
122
str: Full namespace URI
123
"""
124
125
def contains(self, identifier: Identifier) -> bool:
126
"""
127
Check if an identifier belongs to this namespace.
128
129
Args:
130
identifier (Identifier): Identifier to check
131
132
Returns:
133
bool: True if identifier is in this namespace
134
"""
135
136
def qname(self, localpart: str) -> QualifiedName:
137
"""
138
Create a qualified name in this namespace.
139
140
Args:
141
localpart (str): Local part of the name
142
143
Returns:
144
QualifiedName: New qualified name
145
"""
146
147
def __getitem__(self, localpart: str) -> QualifiedName:
148
"""
149
Create qualified name using bracket notation: namespace['localpart'].
150
151
Args:
152
localpart (str): Local part of the name
153
154
Returns:
155
QualifiedName: New qualified name
156
"""
157
158
def __str__(self) -> str:
159
"""String representation showing prefix and URI."""
160
161
def __eq__(self, other) -> bool:
162
"""Equality based on URI comparison."""
163
164
def __hash__(self) -> int:
165
"""Hash based on URI."""
166
```
167
168
### Namespace Management
169
170
The `NamespaceManager` class handles namespace registration and qualified name resolution.
171
172
```python { .api }
173
class NamespaceManager(dict):
174
def __init__(self, namespaces=None, default=None, parent=None):
175
"""
176
Manage namespaces for a document or bundle.
177
178
Args:
179
namespaces (dict or iterable, optional): Initial namespaces
180
default (str, optional): Default namespace URI
181
parent (NamespaceManager, optional): Parent namespace manager
182
"""
183
184
def get_namespace(self, uri: str) -> Namespace | None:
185
"""
186
Get namespace by URI.
187
188
Args:
189
uri (str): Namespace URI to find
190
191
Returns:
192
Namespace: Found namespace or None
193
"""
194
195
def get_registered_namespaces(self) -> Iterable[Namespace]:
196
"""
197
Get all registered namespaces.
198
199
Returns:
200
Iterable[Namespace]: All registered namespaces
201
"""
202
203
def set_default_namespace(self, uri: str) -> None:
204
"""
205
Set the default namespace URI.
206
207
Args:
208
uri (str): Default namespace URI
209
"""
210
211
def get_default_namespace(self) -> Namespace | None:
212
"""
213
Get the default namespace.
214
215
Returns:
216
Namespace: Default namespace or None
217
"""
218
219
def add_namespace(self, namespace: Namespace) -> Namespace:
220
"""
221
Add a namespace to the manager.
222
223
Args:
224
namespace (Namespace): Namespace to add
225
226
Returns:
227
Namespace: The added namespace (may have modified prefix)
228
"""
229
230
def add_namespaces(self, namespaces):
231
"""
232
Add multiple namespaces.
233
234
Args:
235
namespaces (dict or iterable): Namespaces to add
236
"""
237
238
def valid_qualified_name(self, element: Identifier) -> QualifiedName | None:
239
"""
240
Convert identifier to valid qualified name if possible.
241
242
Args:
243
element (Identifier): Identifier to convert
244
245
Returns:
246
QualifiedName: Valid qualified name or None
247
"""
248
249
def get_anonymous_identifier(self, local_prefix: str = "id") -> Identifier:
250
"""
251
Generate an anonymous identifier.
252
253
Args:
254
local_prefix (str): Prefix for generated identifier
255
256
Returns:
257
Identifier: New anonymous identifier
258
"""
259
```
260
261
## Predefined Namespaces
262
263
Common namespaces are predefined as constants:
264
265
```python { .api }
266
# W3C PROV namespace
267
PROV: Namespace # prefix='prov', uri='http://www.w3.org/ns/prov#'
268
269
# XML Schema namespace
270
XSD: Namespace # prefix='xsd', uri='http://www.w3.org/2001/XMLSchema#'
271
272
# XML Schema Instance namespace
273
XSI: Namespace # prefix='xsi', uri='http://www.w3.org/2001/XMLSchema-instance'
274
```
275
276
## Usage Examples
277
278
### Creating and Using Namespaces
279
280
```python
281
from prov.identifier import Namespace, QualifiedName
282
from prov.model import ProvDocument
283
284
# Create custom namespaces
285
ex = Namespace('ex', 'http://example.org/')
286
foaf = Namespace('foaf', 'http://xmlns.com/foaf/0.1/')
287
288
# Create qualified names
289
person_id = ex['person1'] # Using bracket notation
290
name_attr = foaf.qname('name') # Using qname method
291
292
print(person_id) # ex:person1
293
print(person_id.uri) # http://example.org/person1
294
print(name_attr.uri) # http://xmlns.com/foaf/0.1/name
295
```
296
297
### Working with Documents and Namespaces
298
299
```python
300
# Create document and add namespaces
301
doc = ProvDocument()
302
doc.add_namespace('ex', 'http://example.org/')
303
doc.add_namespace(foaf)
304
305
# Set default namespace
306
doc.set_default_namespace('http://example.org/')
307
308
# Create elements using different identifier styles
309
entity1 = doc.entity('ex:entity1') # Qualified name string
310
entity2 = doc.entity(ex['entity2']) # QualifiedName object
311
entity3 = doc.entity('entity3') # Uses default namespace
312
entity4 = doc.entity('http://other.org/entity') # Full URI
313
```
314
315
### Namespace Resolution
316
317
```python
318
# Get registered namespaces
319
for ns in doc.get_registered_namespaces():
320
print(f"Prefix: {ns.prefix}, URI: {ns.uri}")
321
322
# Find namespace by URI
323
ex_ns = doc.get_namespace('http://example.org/')
324
if ex_ns:
325
print(f"Found namespace: {ex_ns.prefix}")
326
327
# Get default namespace
328
default_ns = doc.get_default_namespace()
329
if default_ns:
330
print(f"Default namespace: {default_ns.uri}")
331
```
332
333
### Creating Complex Identifiers
334
335
```python
336
from prov.constants import PROV
337
338
# Use predefined PROV namespace
339
entity_type = PROV['Entity'] # prov:Entity
340
person_type = PROV['Person'] # prov:Person
341
342
# Create entity with PROV types
343
person = doc.entity('ex:researcher', {
344
'prov:type': person_type,
345
'foaf:name': 'Dr. Jane Smith'
346
})
347
348
# Check namespace membership
349
if ex.contains(person.identifier):
350
print("Person is in example namespace")
351
```
352
353
### Working with URIs and Identifiers
354
355
```python
356
from prov.identifier import Identifier
357
358
# Create direct URI identifier
359
uri_id = Identifier('http://example.org/resource1')
360
361
# Convert to qualified name if possible
362
qname = doc.valid_qualified_name(uri_id)
363
if qname:
364
print(f"Converted to: {qname}")
365
else:
366
print("Could not convert to qualified name")
367
368
# Generate anonymous identifiers
369
anon_id = doc.get_anonymous_identifier('temp')
370
print(f"Anonymous ID: {anon_id}")
371
```
372
373
### PROV-N Representation
374
375
```python
376
# Get PROV-N representation of identifiers
377
print(person_id.provn_representation()) # ex:person1
378
print(uri_id.provn_representation()) # <http://example.org/resource1>
379
380
# Different representation styles
381
entity = doc.entity('ex:myEntity')
382
print(f"URI: {entity.identifier.uri}")
383
print(f"PROV-N: {entity.identifier.provn_representation()}")
384
print(f"String: {str(entity.identifier)}")
385
```
386
387
### Namespace Conflicts and Resolution
388
389
```python
390
# Handle namespace prefix conflicts
391
doc.add_namespace('ex', 'http://example.org/')
392
doc.add_namespace('ex', 'http://other.org/') # Will get different prefix
393
394
# Check actual prefixes assigned
395
for ns in doc.get_registered_namespaces():
396
if ns.uri == 'http://other.org/':
397
print(f"Other namespace got prefix: {ns.prefix}") # Might be 'ex1'
398
399
# Use specific namespace objects to avoid conflicts
400
other_ns = Namespace('other', 'http://other.org/')
401
doc.add_namespace(other_ns)
402
entity = doc.entity(other_ns['entity'])
403
```