Usage¶
Creating a METS document with METS builder consists of the following steps:
Create a METS object instance
Create digital objects and add metadata to them
Create/generate a structural map organizing the digital objects to a wanted structure
Create/generate file references
Transform the METS object instance to an XML file
The example code here can be found in full at the Example code section.
Create a METS object instance¶
Initialize a METS object:
from mets_builder import METS, MetsProfile, AgentRole, AgentType
mets = METS(
mets_profile=MetsProfile.CULTURAL_HERITAGE,
contract_id="urn:uuid:abcd1234-abcd-1234-5678-abcd1234abcd",
creator_name="CSC – IT Center for Science Ltd.",
creator_type=AgentType.ORGANIZATION,
)
The obligatory creator agent is already created in the object initialization, but additional agents can be added with the add_agent()
method:
mets.add_agent(
name="Melissa Mets",
agent_role=AgentRole.ARCHIVIST,
agent_type=AgentType.INDIVIDUAL
)
Create digital objects and add metadata to them¶
A DigitalObject
instance should be created for each digital object that should be included in the METS document. Technical metadata that applies to the digital object can be added using metadata objects:
from pathlib import Path
from mets_builder import DigitalObject, DigitalObjectStream
from mets_builder.metadata import (
ImportedMetadata, TechnicalBitstreamObjectMetadata,
TechnicalImageMetadata, TechnicalFileObjectMetadata
)
picture = DigitalObject(
path="data/pictures/cat_picture.jpg"
)
object_md = TechnicalFileObjectMetadata(
file_format="image/jpeg",
file_format_version="1.01",
checksum_algorithm="MD5",
checksum="4b05bb123f3a00187d3b1b130d67af1c",
file_created_date="2000-12-24T22:00:00"
)
image_md = TechnicalImageMetadata(
compression="jpeg",
colorspace="rgb",
width="100",
height="200",
bps_value="8",
bps_unit="integer",
samples_per_pixel="3",
mimetype="image/jpeg",
byte_order="little endian"
)
picture.add_metadata([object_md, image_md])
Metadata that has been prepared earlier can be imported using the ImportedMetadata
class:
audio_md = ImportedMetadata(
data_path=Path("/home/mets-enthusiast/metadata/audiomd.xml"),
metadata_type="technical",
metadata_format="OTHER",
other_format="AudioMD",
format_version="2.0"
)
video_md = ImportedMetadata(
data_path=Path("/home/mets-enthusiast/metadata/videomd.xml"),
metadata_type="technical",
metadata_format="OTHER",
other_format="VideoMD",
format_version="2.0"
)
If a digital object has streams (for example video files often consist of video and audio streams in a container), the streams can be added to the digital object using DigitalObjectStream
class, and have metadata of their own added to them:
container_md = TechnicalFileObjectMetadata(
file_format="video/x-matroska",
file_format_version="4",
checksum_algorithm="MD5",
checksum="686b680720c61512f5fb438f7879aa76",
file_created_date="2000-12-24T22:00:00"
)
movie = DigitalObject(
path="data/movies/cat_video.mkv",
metadata=[container_md]
)
audio_bitstream_md = TechnicalBitstreamObjectMetadata(
file_format="audio/flac",
file_format_version="1.2.1"
)
video_bitstream_md = TechnicalBitstreamObjectMetadata(
file_format="video/x-ffv",
file_format_version="3"
)
audio_stream = DigitalObjectStream(metadata=[audio_bitstream_md, audio_md])
video_stream = DigitalObjectStream(metadata=[video_bitstream_md, video_md])
movie.add_streams([audio_stream, video_stream])
Create/generate a structural map organizing the digital objects to a wanted structure¶
The digital objects should be given a structure with structural maps, using the StructuralMap
class. Digital objects are grouped into divisions with StructuralMapDiv
objects. Finally the structural maps are given to the METS
object.
A structural map can be generated according to the directory structure inferred from the path
attributes of the given DigitalObject
instances, turning each directory found in the filepaths to a division in the structural map, finally placing the digital objects in the correct division:
from mets_builder import StructuralMap, StructuralMapDiv
structural_map = StructuralMap.from_directory_structure([picture, movie])
mets.add_structural_maps([structural_map])
However, it is possible to build the structural map manually if different structure for the files is needed:
root_div = StructuralMapDiv(div_type="directory")
pictures_div = StructuralMapDiv(div_type="image_files", digital_objects=[picture])
movies_div = StructuralMapDiv(div_type="movie_files", digital_objects=[movie])
root_div.add_divs([pictures_div, movies_div])
structural_map = StructuralMap(root_div=root_div)
mets.add_structural_maps([structural_map])
Metadata that applies to all digital objects in a division can be added to the division. For example digital provenance event information could describe all digital files, so that could be written to the root div of the structural map:
event_md = DigitalProvenanceEventMetadata(
event_type="message digest calculation",
datetime="2000-01-01T12:00:00",
detail="Checksum calculation for digital objects",
outcome="success",
outcome_detail=(
"Checksum(s) successfully calculated for digital object(s)."
)
)
agent_md = DigitalProvenanceAgentMetadata(
name="checksum-calculator",
agent_type="software",
version="1.2.4"
)
event_md.link_agent_metadata(
agent_metadata=agent_md,
agent_role="executing program"
)
root_div.add_metadata([event_md])
Create/generate file references¶
If there are no special needs for the file references, they can be generated from the digital objects added to the structural maps, placing all digital objects found in the structural maps into a single file group in file references:
mets.generate_file_references()
If the file references section needs a special structure, the file references can also be formed manually:
from mets_builder import FileReferences, FileGroup
file_references = FileReferences()
production_group = FileGroup(use="production", digital_objects=[movie])
master_group = FileGroup(use="master", digital_objects=[picture])
file_references.add_file_groups([production_group, master_group])
mets.add_file_references(file_references)
Transform the METS object instance to an XML file¶
When the METS is fully formed, the write
method of the METS object can be called to write an XML representation of the METS object to the given file path:
mets.write("/home/mets-enthusiast/mets.xml")