CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-rdflib

RDFLib is a Python library for working with RDF, a simple yet powerful language for representing information.

Pending
Overview
Eval results
Files

rdf-containers-collections.mddocs/

RDF Containers and Collections

Support for RDF containers (Bag, Seq, Alt) and collections (rdf:List) providing ordered and unordered groupings of RDF resources according to RDF specifications.

Capabilities

Container - Base RDF Container

Base class for RDF containers with common functionality for managing collections of resources.

class Container:
    def __init__(self, graph: Graph, uri: Node, seq: List[Node] = None, rtype: str = "Bag"):
        """
        Create an RDF container.
        
        Parameters:
        - graph: Graph to store container in
        - uri: Container URI (BNode or URIRef)
        - seq: Initial sequence of items
        - rtype: Container type ("Bag", "Seq", "Alt")
        """
    
    def append(self, item: Node) -> 'Container':
        """
        Add an item to the container.
        
        Parameters:
        - item: Item to add
        
        Returns:
        Container: Self for method chaining
        """
    
    def __getitem__(self, index: int) -> Node:
        """
        Get item by index (1-based).
        
        Parameters:
        - index: Item index (starting from 1)
        
        Returns:
        Node: Item at index
        """
    
    def __setitem__(self, index: int, item: Node):
        """
        Set item at index (1-based).
        
        Parameters:
        - index: Item index (starting from 1)
        - item: New item value
        """
    
    def __delitem__(self, index: int):
        """
        Delete item at index (1-based).
        
        Parameters:
        - index: Item index to delete
        """
    
    def __iter__(self) -> Iterator[Node]:
        """
        Iterate over container items.
        
        Returns:
        Iterator: Container items
        """
    
    def __len__(self) -> int:
        """
        Get number of items in container.
        
        Returns:
        int: Item count
        """
    
    def index(self, item: Node) -> int:
        """
        Find index of item (1-based).
        
        Parameters:
        - item: Item to find
        
        Returns:
        int: Item index or raises ValueError
        """
    
    def clear(self):
        """Remove all items from container."""
    
    @property
    def uri(self) -> Node:
        """
        Get container URI.
        
        Returns:
        Node: Container identifier
        """
    
    @property
    def graph(self) -> Graph:
        """
        Get container's graph.
        
        Returns:
        Graph: Graph containing container
        """

Bag - Unordered Container

RDF Bag container for unordered collections where duplicates are allowed.

class Bag(Container):
    def __init__(self, graph: Graph, uri: Node, seq: List[Node] = None):
        """
        Create an RDF Bag.
        
        Parameters:
        - graph: Graph to store bag in
        - uri: Bag URI (BNode or URIRef)
        - seq: Initial sequence of items
        """

Seq - Ordered Container

RDF Sequence container for ordered collections where duplicates are allowed.

class Seq(Container):
    def __init__(self, graph: Graph, uri: Node, seq: List[Node] = None):
        """
        Create an RDF Sequence.
        
        Parameters:
        - graph: Graph to store sequence in
        - uri: Sequence URI (BNode or URIRef)
        - seq: Initial sequence of items
        """

Alt - Alternative Container

RDF Alternative container representing a set of alternative values.

class Alt(Container):
    def __init__(self, graph: Graph, uri: Node, seq: List[Node] = None):
        """
        Create an RDF Alternative.
        
        Parameters:
        - graph: Graph to store alternative in
        - uri: Alternative URI (BNode or URIRef)
        - seq: Initial sequence of alternatives
        """

Collection - RDF List

Implementation of RDF collections (rdf:List) for ordered sequences.

class Collection:
    def __init__(self, graph: Graph, uri: Node, seq: List[Node] = None):
        """
        Create an RDF Collection (List).
        
        Parameters:
        - graph: Graph to store collection in
        - uri: Collection head URI (BNode or URIRef)
        - seq: Initial sequence of items
        """
    
    def append(self, item: Node) -> 'Collection':
        """
        Add an item to the end of the collection.
        
        Parameters:
        - item: Item to add
        
        Returns:
        Collection: Self for method chaining
        """
    
    def clear(self):
        """Remove all items, making this an empty list (rdf:nil)."""
    
    def __iter__(self) -> Iterator[Node]:
        """
        Iterate over collection items.
        
        Returns:
        Iterator: Collection items in order
        """
    
    def __len__(self) -> int:
        """
        Get number of items in collection.
        
        Returns:
        int: Item count
        """
    
    def __getitem__(self, index: int) -> Node:
        """
        Get item by index (0-based).
        
        Parameters:
        - index: Item index (starting from 0)
        
        Returns:
        Node: Item at index
        """
    
    def __contains__(self, item: Node) -> bool:
        """
        Check if collection contains item.
        
        Parameters:
        - item: Item to check
        
        Returns:
        bool: True if item is in collection
        """
    
    @property
    def uri(self) -> Node:
        """
        Get collection head URI.
        
        Returns:
        Node: Collection head identifier
        """
    
    @property
    def graph(self) -> Graph:
        """
        Get collection's graph.
        
        Returns:
        Graph: Graph containing collection
        """

Exception Classes

class NoElementException(Exception):
    """Raised when trying to access non-existent container element."""

Usage Examples

Working with RDF Bags

from rdflib import Graph, BNode, Literal, URIRef
from rdflib.container import Bag
from rdflib.namespace import RDF

g = Graph()

# Create a bag
bag_uri = BNode()
fruits = Bag(g, bag_uri, [Literal("Apple"), Literal("Orange"), Literal("Banana")])

# Add more items
fruits.append(Literal("Grape"))
fruits.append(Literal("Apple"))  # Duplicates allowed

# Access items
print(f"First fruit: {fruits[1]}")  # 1-based indexing
print(f"Bag has {len(fruits)} items")

# Iterate over items
for fruit in fruits:
    print(f"Fruit: {fruit}")

# Check the RDF representation
print(g.serialize(format="turtle"))

Working with RDF Sequences

from rdflib import Graph, BNode, Literal
from rdflib.container import Seq

g = Graph()

# Create a sequence (order matters)
seq_uri = BNode()
steps = Seq(g, seq_uri)

# Add steps in order
steps.append(Literal("Mix ingredients"))
steps.append(Literal("Heat oven to 350°F"))
steps.append(Literal("Bake for 30 minutes"))
steps.append(Literal("Cool before serving"))

# Access by index
print(f"Step 2: {steps[2]}")

# Modify a step
steps[2] = Literal("Preheat oven to 350°F")

# Insert is achieved by manipulating the sequence
print(f"Recipe has {len(steps)} steps")

# The sequence maintains order
for i, step in enumerate(steps, 1):
    print(f"Step {i}: {step}")

Working with RDF Alternatives

from rdflib import Graph, BNode, Literal
from rdflib.container import Alt

g = Graph()

# Create alternatives (representing choices)
alt_uri = BNode()
formats = Alt(g, alt_uri)

# Add format alternatives
formats.append(Literal("PDF"))
formats.append(Literal("HTML"))
formats.append(Literal("XML"))
formats.append(Literal("JSON"))

# Get preferred alternative (typically first)
preferred = formats[1]
print(f"Preferred format: {preferred}")

# List all alternatives
print("Available formats:")
for fmt in formats:
    print(f"  - {fmt}")

Working with RDF Collections (Lists)

from rdflib import Graph, BNode, Literal, URIRef
from rdflib.collection import Collection
from rdflib.namespace import RDF

g = Graph()

# Create a collection
list_uri = BNode()
authors = Collection(g, list_uri)

# Add authors in order
authors.append(Literal("Alice Smith"))
authors.append(Literal("Bob Jones"))
authors.append(Literal("Carol Brown"))

# Collections are ordered and can be accessed by index
print(f"First author: {authors[0]}")  # 0-based indexing
print(f"Last author: {authors[-1]}")

# Check membership
if Literal("Alice Smith") in authors:
    print("Alice Smith is an author")

# Iterate over authors
for author in authors:
    print(f"Author: {author}")

# Collections generate proper rdf:List structure
print(g.serialize(format="turtle"))

Container Integration with Graphs

from rdflib import Graph, URIRef, Literal
from rdflib.container import Bag, Seq
from rdflib.namespace import RDF, RDFS

g = Graph()

# Create a book with multiple authors (bag) and chapters (sequence)
book = URIRef("http://example.org/book/1")
g.add((book, RDF.type, URIRef("http://example.org/Book")))
g.add((book, RDFS.label, Literal("Python Programming")))

# Authors as a bag (unordered)
authors_bag = Bag(g, URIRef("http://example.org/book/1/authors"))
authors_bag.append(Literal("John Doe"))
authors_bag.append(Literal("Jane Smith"))
g.add((book, URIRef("http://example.org/hasAuthors"), authors_bag.uri))

# Chapters as a sequence (ordered)
chapters_seq = Seq(g, URIRef("http://example.org/book/1/chapters"))
chapters_seq.append(Literal("Introduction"))
chapters_seq.append(Literal("Basic Syntax"))
chapters_seq.append(Literal("Data Structures"))
chapters_seq.append(Literal("Functions"))
g.add((book, URIRef("http://example.org/hasChapters"), chapters_seq.uri))

# Query the containers
query = """
    PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    SELECT ?book ?author ?chapter WHERE {
        ?book <http://example.org/hasAuthors> ?authors .
        ?authors ?author_prop ?author .
        FILTER(STRSTARTS(STR(?author_prop), STR(rdf:_)))
        
        ?book <http://example.org/hasChapters> ?chapters .
        ?chapters ?chapter_prop ?chapter .
        FILTER(STRSTARTS(STR(?chapter_prop), STR(rdf:_)))
    }
"""

results = g.query(query)
for row in results:
    print(f"Book: {row.book}, Author: {row.author}, Chapter: {row.chapter}")

Advanced Container Operations

from rdflib import Graph, BNode, Literal
from rdflib.container import Seq

g = Graph()

# Create a mutable sequence
playlist = Seq(g, BNode())

# Build playlist
songs = [
    "Song A",
    "Song B", 
    "Song C",
    "Song D"
]

for song in songs:
    playlist.append(Literal(song))

# Rearrange playlist - remove and insert
song_b = playlist[2]  # Get "Song B"
del playlist[2]       # Remove "Song B"
playlist.append(song_b)  # Add to end

print("Rearranged playlist:")
for i, song in enumerate(playlist, 1):
    print(f"{i}. {song}")

# Find position of a song
try:
    pos = playlist.index(Literal("Song A"))
    print(f"Song A is at position {pos}")
except ValueError:
    print("Song A not found")

# Clear playlist
playlist.clear()
print(f"Playlist now has {len(playlist)} songs")

Working with Empty Containers

from rdflib import Graph, BNode
from rdflib.container import Bag
from rdflib.collection import Collection
from rdflib.namespace import RDF

g = Graph()

# Create empty containers
empty_bag = Bag(g, BNode())
empty_list = Collection(g, BNode())

print(f"Empty bag length: {len(empty_bag)}")
print(f"Empty list length: {len(empty_list)}")

# Empty containers still create RDF structure
print("Empty bag RDF:")
for triple in g.triples((empty_bag.uri, None, None)):
    print(f"  {triple}")

print("Empty list RDF:")
for triple in g.triples((empty_list.uri, None, None)):
    print(f"  {triple}")

Install with Tessl CLI

npx tessl i tessl/pypi-rdflib

docs

dataset-named-graphs.md

graph-operations.md

index.md

namespace-management.md

parsers-serializers.md

rdf-containers-collections.md

rdf-terms.md

sparql-queries-updates.md

utilities-helpers.md

tile.json