Files
musenalm/import/data/rtansfer.py
2025-02-28 16:54:49 +01:00

224 lines
10 KiB
Python

import xml.etree.ElementTree as ET
from xml.dom import minidom
import re
import sys
def create_zotero_rdf():
rdf = ET.Element('rdf:RDF')
rdf.set('xmlns:rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#')
rdf.set('xmlns:z', 'http://www.zotero.org/namespaces/export#')
rdf.set('xmlns:dc', 'http://purl.org/dc/elements/1.1/')
rdf.set('xmlns:vcard', 'http://nwalsh.com/rdf/vCard#')
rdf.set('xmlns:foaf', 'http://xmlns.com/foaf/0.1/')
rdf.set('xmlns:bib', 'http://purl.org/net/biblio#')
rdf.set('xmlns:dcterms', 'http://purl.org/dc/terms/')
return rdf
def create_actor_element(akteur):
if akteur.find('ORGANISATION') is not None and akteur.find('ORGANISATION').text == '1':
actor = ET.Element('foaf:Organization')
name = ET.SubElement(actor, 'foaf:name')
name.text = akteur.find('NAME').text if akteur.find('NAME') is not None else "Unknown Organization"
else:
actor = ET.Element('foaf:Person')
surname = ET.SubElement(actor, 'foaf:surname')
full_name = akteur.find('NAME').text if akteur.find('NAME') is not None else "Unknown Person"
surname.text = full_name.split(', ')[0] if ', ' in full_name else full_name
if ', ' in full_name:
given_name = ET.SubElement(actor, 'foaf:givenName')
given_name.text = full_name.split(', ')[1]
return actor
def create_memo(book_id, content, index):
memo = ET.Element('bib:Memo')
memo.set('rdf:about', f'#item_{book_id}_memo_{index}')
value = ET.SubElement(memo, 'rdf:value')
value.text = f'<div data-schema-version="9"><p>{content}</p></div>'
return memo
def create_book_entry(band, akteure, relationships, orte, vocabular, relationships_reihen, reihen, vocabular_reihe, zotero_rdf):
if band.find('TITEL') is None or not band.find('TITEL').text:
return None
book_id = band.find('ID').text if band.find('ID') is not None else "unknown"
book = ET.Element('bib:Book')
book.set('rdf:about', f'#item_{book_id}')
# Add item type
item_type = ET.SubElement(book, 'z:itemType')
item_type.text = 'book'
# Add title
title = ET.SubElement(book, 'dc:title')
title.text = band.find('TITEL').text if band.find('TITEL') is not None else "Unknown Title"
# Add year
year = ET.SubElement(book, 'dc:date')
year.text = band.find('JAHR').text if band.find('JAHR') is not None else ""
# Add editors
editors = ET.SubElement(book, 'bib:editors')
editors_seq = ET.SubElement(editors, 'rdf:Seq')
# Process relationships
for relation in relationships:
if relation.find('BAND') is not None and relation.find('BAND').text == book_id:
akteur_id = relation.find('AKTEUR').text if relation.find('AKTEUR') is not None else None
beziehung_id = relation.find('BEZIEHUNG').text if relation.find('BEZIEHUNG') is not None else None
akteur = next((a for a in akteure if a.find('ID') is not None and a.find('ID').text == akteur_id), None)
beziehung = next((v for v in vocabular if v.find('ID') is not None and v.find('ID').text == beziehung_id), None)
if akteur is not None and beziehung is not None and beziehung.find('Beziehung') is not None:
actor_element = create_actor_element(akteur)
if beziehung.find('Beziehung').text == 'wurde herausgegeben von':
editor_li = ET.SubElement(editors_seq, 'rdf:li')
editor_li.append(actor_element)
elif beziehung.find('Beziehung').text == 'wurde verlegt von':
publisher = ET.SubElement(book, 'dc:publisher')
publisher.append(actor_element)
# Add place of publication
ort_id = band.find('ORTE/Value').text if band.find('ORTE/Value') is not None else None
if ort_id:
ort = next((o for o in orte if o.find('ID') is not None and o.find('ID').text == ort_id), None)
if ort is not None and ort.find('NAME') is not None:
publisher = book.find('dc:publisher')
if publisher is None:
publisher = ET.SubElement(book, 'dc:publisher')
org = ET.SubElement(publisher, 'foaf:Organization')
else:
org = publisher.find('foaf:Organization')
if org is None:
org = ET.SubElement(publisher, 'foaf:Organization')
adr = ET.SubElement(org, 'vcard:adr')
address = ET.SubElement(adr, 'vcard:Address')
locality = ET.SubElement(address, 'vcard:locality')
locality.text = ort.find('NAME').text
# Add series information
for relation in relationships_reihen:
if relation.find('BAND') is not None and relation.find('BAND').text == book_id:
reihe_id = relation.find('REIHE').text if relation.find('REIHE') is not None else None
beziehung_id = relation.find('BEZIEHUNG').text if relation.find('BEZIEHUNG') is not None else None
reihe = next((r for r in reihen if r.find('ID') is not None and r.find('ID').text == reihe_id), None)
beziehung = next((v for v in vocabular_reihe if v.find('ID') is not None and v.find('ID').text == beziehung_id), None)
if reihe is not None and beziehung is not None and reihe.find('NAME') is not None:
series = ET.SubElement(book, 'dcterms:isPartOf')
series_element = ET.SubElement(series, 'bib:Series')
series_title = ET.SubElement(series_element, 'dc:title')
series_title.text = reihe.find('NAME').text
# Add STRUKTUR to z:numPages
if band.find('STRUKTUR') is not None and band.find('STRUKTUR').text:
num_pages = ET.SubElement(book, 'z:numPages')
num_pages.text = band.find('STRUKTUR').text
# Add description
description = ET.SubElement(book, 'dcterms:abstract')
desc_parts = []
# Handle STATUS
status = band.find('STATUS/Value')
if status is not None and status.text:
desc_parts.append(f"Status: {status.text}")
# Handle NACHWEIS
nachweis = band.find('NACHWEIS')
if nachweis is not None and nachweis.text:
desc_parts.append(f"Nachweis: {nachweis.text}")
# Handle BIBLIO-ID
biblio_id = band.find('BIBLIO-ID')
if biblio_id is not None and biblio_id.text:
desc_parts.append(f"BIBLIO-ID: {biblio_id.text}")
description.text = "\n".join(desc_parts)
# Add language
language = ET.SubElement(book, 'z:language')
language.text = 'Deutsch' # Assuming the language is German
# Add Anmerkungen as Memos
if band.find('ANMERKUNGEN') is not None and band.find('ANMERKUNGEN').text:
anmerkungen = band.find('ANMERKUNGEN').text
# Split Anmerkungen by \) or )\
memo_contents = re.split(r'\\\)|\)\\\s*', anmerkungen)
for i, content in enumerate(memo_contents):
if content.strip(): # Only create memo if content is not empty
memo = create_memo(book_id, content.strip(), i)
zotero_rdf.append(memo)
# Add reference to the memo in the book entry
is_referenced_by = ET.SubElement(book, 'dcterms:isReferencedBy')
is_referenced_by.set('rdf:resource', f'#item_{book_id}_memo_{i}')
return book
def transform_xml(baende_file, akteure_file, relations_file, orte_file, vocabular_file, reihen_file, relations_reihen_file, vocabular_reihe_file, output_file):
xml_string = ""
try:
# Parse all XML files
baende_tree = ET.parse(baende_file)
akteure_tree = ET.parse(akteure_file)
relations_tree = ET.parse(relations_file)
orte_tree = ET.parse(orte_file)
vocabular_tree = ET.parse(vocabular_file)
reihen_tree = ET.parse(reihen_file)
relations_reihen_tree = ET.parse(relations_reihen_file)
vocabular_reihe_tree = ET.parse(vocabular_reihe_file)
baende = baende_tree.getroot().findall('Baende')
akteure = akteure_tree.getroot().findall('Akteure')
relationships = relations_tree.getroot().findall('_x002A_RELATION_BaendeAkteure')
orte = orte_tree.getroot().findall('Orte')
vocabular = vocabular_tree.getroot().findall('_x002A_VOKABULAR_WerkeAkteure')
reihen = reihen_tree.getroot().findall('Reihen')
relationships_reihen = relations_reihen_tree.getroot().findall('_x002A_RELATION_BaendeReihen')
vocabular_reihe = vocabular_reihe_tree.getroot().findall('_x002A_VOKABULAR_Reihe')
# Create the Zotero RDF
zotero_rdf = create_zotero_rdf()
# Process each Band
for band in baende:
book_entry = create_book_entry(band, akteure, relationships, orte, vocabular, relationships_reihen, reihen, vocabular_reihe, zotero_rdf)
if book_entry is not None:
zotero_rdf.append(book_entry)
# Create a pretty-printed XML string
xml_string = ET.tostring(zotero_rdf, encoding='unicode')
# For debugging, print the first 1000 characters of the XML string
print("First 1000 characters of XML string:")
print(xml_string[:1000])
pretty_xml = minidom.parseString(xml_string).toprettyxml(indent=" ")
# Write to output file
with open(output_file, 'w', encoding='utf-8') as f:
f.write(pretty_xml)
print(f"Successfully wrote output to {output_file}")
except Exception as e:
print(f"An error occurred: {str(e)}", file=sys.stderr)
if xml_string:
print("XML string at the point of failure:", file=sys.stderr)
print(xml_string[:1000], file=sys.stderr) # Print the first 1000 characters
else:
print("Error occurred before XML string was created.", file=sys.stderr)
raise
# Usage
try:
transform_xml('Baende.xml', 'Akteure.xml', '_RELATION_BaendeAkteure.xml', 'Orte.xml', '_VOKABULAR_WerkeAkteure.xml', 'Reihen.xml', '_RELATION_BaendeReihen.xml', '_VOKABULAR_Reihe.xml', 'zotero_output.rdf')
except Exception as e:
print(f"Script execution failed: {str(e)}", file=sys.stderr)
sys.exit(1)