Ver código fonte

initial commit

kora 4 meses atrás
commit
a3e4d38496

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+venv/
+__pycache__/

+ 326 - 0
data/man_draft.json

@@ -0,0 +1,326 @@
+{
+  "Entità": {
+    "Manoscritto": {
+      "Attributi": [
+        "Nome vulgato"
+      ]
+    },
+    "Unità codicologica": {
+      "Attributi": [
+        "Consistenza",
+        "Legatura",
+        "Fascicolazione"
+      ]
+    },
+    "Supporto": {
+      "Attributi": [
+        "Stato di conservazione",
+        "Materiale"
+      ]
+    },
+    "Fascicolo": {
+      "Sottoclasse di": "Unità codicologica"
+    },
+    "Bifoglio": {
+      "Attributi": [
+        "Numerazione bifoglio"
+      ]
+    },
+    "Foglio": {
+      "Attributi": [
+        "Numerazione foglio"
+      ]
+    },
+    "Carta": {
+      "Sottoclasse di": "Foglio"
+    },
+    "Pagina": {
+      "Attributi": [
+        "Numerazione pagina"
+      ]
+    },
+    "Illustrazione": {},
+    "Miniatura": {
+      "Sottoclasse di": "Illustrazione"
+    },
+    "Decorazione": {
+      "Sottoclasse di": "Illustrazione"
+    },
+    "Dimensioni": {
+      "Attributi": [
+        "Larghezza",
+        "Lunghezza",
+        "Unità di misura"
+      ]
+    },
+    "Mano": {
+      "Attributi": [
+        "Data mano",
+        "Collocazione nel manoscritto mano",
+        "Tipo di scrittura mano"
+      ]
+    },
+    "Organizzazione della pagina": {
+      "Attributi": [
+        "Descrizione pagina",
+        "Tipo di scrittura pagina"
+      ]
+    },
+    "Evento": {
+      "Attributi": [
+        "Descrizione evento"
+      ]
+    },
+    "Luogo": {
+      "Attributi": [
+        "Descrizione luogo",
+        "Coordinate",
+        "Estensione"
+      ]
+    },
+    "Periodo": {
+      "Attributi": [
+        "Inizio",
+        "Fine"
+      ]
+    },
+    "Origine": {
+      "Sottoclasse di": "Evento"
+    },
+    "Provenienza": {
+      "Sottoclasse di": "Evento"
+    },
+    "Persona": {
+      "Attributi": [
+        "Nome",
+        "Ruolo",
+        "Sesso",
+        "Nascita",
+        "Morte"
+      ]
+    },
+    "Attività": {
+      "Sottoclasse di": "Evento"
+    },
+    "Ente": {
+      "Attributi": [
+        "Descrizione",
+        "Vide"
+      ]
+    },
+    "Testo": {
+      "Attributi": [
+        "Titolo"
+      ]
+    },
+    "Aggiunta": {
+      "Attributi": [
+        "Descrizione aggiunta"
+      ]
+    },
+    "Marginalia": {
+      "Attributi": [
+        "Descrizione marginalia",
+        "Annotazione"
+      ]
+    },
+    "Fondo": {},
+    "Segnatura": {
+      "Attributi": [
+        "Segnatura numerica"
+      ]
+    }
+  },
+  "Relazioni": [
+    {
+      "Entità 1": "Manoscritto",
+      "Entità 2": "Unità codicologica",
+      "Etichetta": "is_composed_by",
+      "Inversa": "is_part_of"
+    },
+    {
+      "Entità 1": "Manoscritto",
+      "Entità 2": "Origine",
+      "Etichetta": "originated_in",
+      "Inversa": "is_origin_of"
+    },
+    {
+      "Entità 1": "Manoscritto",
+      "Entità 2": "Provenienza",
+      "Etichetta": "has_been_in",
+      "Inversa": "is_part_of_the_history_of"
+    },
+    {
+      "Entità 1": "Unità codicologica",
+      "Entità 2": "Bifoglio",
+      "Etichetta": "is_composed_by",
+      "Inversa": "is_part_of"
+    },
+    {
+      "Entità 1": "Unità codicologica",
+      "Entità 2": "Foglio",
+      "Etichetta": "is_composed_by",
+      "Inversa": "is_part_of"
+    },
+    {
+      "Entità 1": "Manoscritto",
+      "Entità 2": "Supporto",
+      "Etichetta": "consists_of",
+      "Inversa": "is_incorporated_in"
+    },
+    {
+      "Entità 1": "Bifoglio",
+      "Entità 2": "Foglio",
+      "Etichetta": "is_composed_by",
+      "Inversa": "is_part_of"
+    },
+    {
+      "Entità 1": "Foglio",
+      "Entità 2": "Pagina",
+      "Etichetta": "is_composed_by",
+      "Inversa": "is_part_of"
+    },
+    {
+      "Entità 1": "Pagina",
+      "Entità 2": "Illustrazione",
+      "Etichetta": "contains",
+      "Inversa": "is_contained_in"
+    },
+    {
+      "Entità 1": "Pagina",
+      "Entità 2": "Mano",
+      "Etichetta": "is_written_by",
+      "Inversa": "writes"
+    },
+    {
+      "Entità 1": "Pagina",
+      "Entità 2": "Organizzazione della pagina",
+      "Etichetta": "is_described_by",
+      "Inversa": "describes"
+    },
+    {
+      "Entità 1": "Illustrazione",
+      "Entità 2": "#any",
+      "Etichetta": "represents",
+      "Inversa": "is_represented_in"
+    },
+    {
+      "Entità 1": "Evento",
+      "Entità 2": "Periodo",
+      "Etichetta": "has_time_span",
+      "Inversa": "is_time_span_of"
+    },
+    {
+      "Entità 1": "Evento",
+      "Entità 2": "Luogo",
+      "Etichetta": "happens_in",
+      "Inversa": "is_theater_of"
+    },
+    {
+      "Entità 1": "Persona",
+      "Entità 2": "Periodo",
+      "Etichetta": "is_active_in",
+      "Inversa": "sees_activity_of"
+    },
+    {
+      "Entità 1": "Manoscritto",
+      "Entità 2": "Testo",
+      "Etichetta": "transmits",
+      "Inversa": "is_transmitted_by"
+    },
+    {
+      "Entità 1": "Persona",
+      "Entità 2": "Testo",
+      "Etichetta": "is_author_of",
+      "Inversa": "is_authored_by"
+    },
+    {
+      "Entità 1": "Pagina",
+      "Entità 2": "Aggiunta",
+      "Etichetta": "includes",
+      "Inversa": "is_included_in"
+    },
+    {
+      "Entità 1": "Pagina",
+      "Entità 2": "Marginalia",
+      "Etichetta": "includes",
+      "Inversa": "is_included_in"
+    },
+    {
+      "Entità 1": "Foglio",
+      "Entità 2": "Dimensioni",
+      "Etichetta": "is_described_by",
+      "Inversa": "describes"
+    },
+    {
+      "Entità 1": "Ente",
+      "Entità 2": "Luogo",
+      "Etichetta": "is_placed_in",
+      "Inversa": "has"
+    },
+    {
+      "Entità 1": "Ente",
+      "Entità 2": "Attività",
+      "Etichetta": "hosts",
+      "Inversa": "takes_place_at"
+    },
+    {
+      "Entità 1": "Persona",
+      "Entità 2": "Attività",
+      "Etichetta": "participates_in",
+      "Inversa": "sees_participation_of"
+    },
+    {
+      "Entità 1": "Manoscritto",
+      "Entità 2": "Segnatura",
+      "Etichetta": "is_identified_by",
+      "Inversa": "identifies"
+    },
+    {
+      "Entità 1": "Persona",
+      "Entità 2": "Evento",
+      "Etichetta": "is_witness_of",
+      "Inversa": "has_witness"
+    },
+    {
+      "Entità 1": "Segnatura",
+      "Entità 2": "Fondo",
+      "Etichetta": "has_prefix",
+      "Inversa": "has"
+    },
+    {
+      "Entità 1": "Fondo",
+      "Entità 2": "Ente",
+      "Etichetta": "is_part_of",
+      "Inversa": "has"
+    },
+    {
+      "Entità 1": "Manoscritto",
+      "Entità 2": "Ente",
+      "Etichetta": "is_kept_at",
+      "Inversa": "holds"
+    }
+  ],
+  "Same_as": {
+    "Manoscritto": [
+      "Codice"
+    ],
+    "Unità codicologica": [
+      "Sezione"
+    ],
+    "Dimensioni": [
+      "Formato"
+    ],
+    "Organizzazione della pagina": [
+      "Architettura della pagina",
+      "Disposizione della pagina",
+      "Utilizzazione della pagina",
+      "Impaginazione"
+    ],
+    "Aggiunta": [
+      "Inserzione",
+      "Integrazione",
+      "Addizione"
+    ]
+  }
+}

BIN
data/man_draft.xlsx


BIN
data/man_draft_2.xlsx


+ 63 - 0
data/man_draft_entities.csv

@@ -0,0 +1,63 @@
+ENTITÀ,ATTRIBUTO (LITERAL),SAME AS
+Manoscritto,,Codice
+,Nome vulgato,
+Unità codicologica,,Sezione
+,Consistenza,
+,Legatura,
+,Fascicolazione,
+Supporto,,
+,Stato di conservazione,
+,Materiale,
+Fascicolo,,
+Bifoglio,,
+,Numerazione bifoglio,
+Foglio,,
+,Numerazione foglio,
+Carta,,
+Pagina,,
+,Numerazione pagina,
+Illustrazione,,
+Miniatura,,
+Decorazione,,
+Dimensioni,,Formato
+,Larghezza,
+,Lunghezza,
+,Unità di misura,
+Mano,,
+,Data mano,
+,Collocazione nel manoscritto mano,
+,Tipo di scrittura mano,
+Organizzazione della pagina,,"Architettura della pagina, Disposizione della pagina, Utilizzazione della pagina, Impaginazione"
+,Descrizione pagina,
+,Tipo di scrittura pagina,
+Evento,,
+,Descrizione evento,
+Luogo,,
+,Descrizione luogo,
+,Coordinate,
+,Estensione,
+Periodo,,
+,Inizio,
+,Fine,
+Origine,,
+Provenienza,,
+Persona,,
+,Nome,
+,Ruolo,
+,Sesso,
+,Nascita,
+,Morte,
+Attività,,
+Ente,,
+,Descrizione,
+,Vide,
+Testo,,
+,Titolo,
+Aggiunta,,"Inserzione, Integrazione, Addizione"
+,Descrizione aggiunta,
+Marginalia,,
+,Descrizione marginalia,
+,Annotazione,
+Fondo,,
+Segnatura,,
+,Segnatura numerica,

+ 36 - 0
data/man_draft_relations.csv

@@ -0,0 +1,36 @@
+ENTITÀ 1,ENTITÀ 2,NOME RELAZIONE,NOME RELAZIONE INVERSA
+Manoscritto,Unità codicologica,is_composed_by,is_part_of
+Manoscritto,Origine,originated_in,is_origin_of
+Manoscritto,Provenienza,has_been_in,is_part_of_the_history_of
+Unità codicologica,Bifoglio,is_composed_by,is_part_of
+Unità codicologica,Foglio,is_composed_by,is_part_of
+Manoscritto,Supporto,consists_of,is_incorporated_in
+Bifoglio,Foglio,is_composed_by,is_part_of
+Foglio,Pagina,is_composed_by,is_part_of
+Pagina,Illustrazione,contains,is_contained_in
+Pagina,Mano,is_written_by,writes
+Pagina,Organizzazione della pagina,is_described_by,describes
+Illustrazione,#any,represents,is_represented_in
+Evento,Periodo,has_time_span,is_time_span_of
+Evento,Luogo,happens_in,is_theater_of
+Persona,Periodo,is_active_in,sees_activity_of
+Manoscritto,Testo,transmits,is_transmitted_by
+Persona,Testo,is_author_of,is_authored_by
+Pagina,Aggiunta,includes,is_included_in
+Pagina,Marginalia,includes,is_included_in
+Foglio,Dimensioni,is_described_by,describes
+Ente,Luogo,is_placed_in,has
+Ente,Attività,hosts,takes_place_at
+Persona,Attività,participates_in,sees_participation_of
+Manoscritto,Segnatura,is_identified_by,identifies
+Persona,Evento,is_witness_of,has_witness
+Segnatura,Fondo,has_prefix,has
+Fondo,Ente,is_part_of,has
+Manoscritto,Ente,is_kept_at,holds
+Fascicolo,Unità codicologica,is_subclass_of,is_superclass_of
+Carta,Foglio,is_subclass_of,is_superclass_of
+Miniatura,Illustrazione,is_subclass_of,is_superclass_of
+Decorazione,Illustrazione,is_subclass_of,is_superclass_of
+Origine,Evento,is_subclass_of,is_superclass_of
+Provenienza,Evento,is_subclass_of,is_superclass_of
+Attività,Evento,is_subclass_of,is_superclass_of

+ 138 - 0
parse_onto_xlsx.py

@@ -0,0 +1,138 @@
+# %%
+import csv
+import json
+
+# CONFIGURATION
+DATA_FOLDER = './data/'
+XLSX_FILENAME = 'man_draft.xlsx'
+ENTITIES_SHEETNAME = 'Entità'
+RELATIONS_SHEETNAME = 'Relazioni'
+#
+HEADER_ROW = True
+#
+ENTITIES_COLUMN_LABEL = 'ENTITÀ'
+ATTRIBUTES_COLUMN_LABEL = 'ATTRIBUTO (LITERAL)'
+SAMEAS_COLUMN_LABEL = 'SAME AS'
+#
+RELATION_FIRST_COLUMN_LABEL = 'ENTITÀ 1'
+RELATION_SECOND_COLUMN_LABEL = 'ENTITÀ 2'
+RELATION_NAME_COLUMN_LABEL = 'NOME RELAZIONE'
+INVERSE_RELATION_COLUMN_LABEL = 'NOME RELAZIONE INVERSA'
+
+# %%
+# Import xlsx through openpyxl
+import openpyxl as op
+
+input_data = op.load_workbook(DATA_FOLDER + XLSX_FILENAME)
+
+entities_sheet = input_data[ENTITIES_SHEETNAME]
+relations_sheet = input_data[RELATIONS_SHEETNAME]
+# %%
+# Conversion utility: from openpyxl object to csv-style list of dicts
+def sheet_to_dict_list(openpyxl_sheet, keys, header_row_local=True):
+
+    if header_row_local:
+        headers = next(openpyxl_sheet.values)
+        indices = {key: headers.index(key) for key in keys}
+    else:
+        indices = {key: int(key) for key in keys}
+
+    output = []
+    for sheet_row in openpyxl_sheet.values:
+
+        # Get row data as dict
+        out_row = {key: sheet_row[indices[key]]for key in keys if indices[key]>-1}
+        output.append(out_row)
+
+    if header_row_local:
+        output = output[1:]
+
+    return output
+# %%
+# Define csv-style list of dicts for entities and relations
+
+# Collect headers (column names) for the Entities Sheet
+ent_keys = [ENTITIES_COLUMN_LABEL, ATTRIBUTES_COLUMN_LABEL, SAMEAS_COLUMN_LABEL]
+# Convert
+entities = sheet_to_dict_list(entities_sheet, ent_keys, HEADER_ROW)
+# Export
+basename = XLSX_FILENAME[:XLSX_FILENAME.rfind('.')]
+ent_filename = basename + '_entities.csv'
+with open(DATA_FOLDER + ent_filename, 'w') as out_file:
+    writer = csv.DictWriter(out_file, ent_keys)
+    writer.writeheader()
+    writer.writerows(entities)
+
+# Collect headers (column names) for the Relations Sheet
+rel_keys = [RELATION_FIRST_COLUMN_LABEL, RELATION_SECOND_COLUMN_LABEL, RELATION_NAME_COLUMN_LABEL,INVERSE_RELATION_COLUMN_LABEL]
+# Convert
+relations = sheet_to_dict_list(relations_sheet, rel_keys, HEADER_ROW)
+# Export
+rel_filename = basename + '_relations.csv'
+with open(DATA_FOLDER + rel_filename, 'w') as out_file:
+    writer = csv.DictWriter(out_file, rel_keys)
+    writer.writeheader()
+    writer.writerows(relations)
+# %%
+# From here on, work with the 'entities' and 'relations' lists of dicts
+
+def dict_lists_to_json(entities_local, relations_local):
+
+    entity = {}
+    same_as = {}
+
+    current_entity = None
+    for row in entities_local:
+        entity_name = row.get(ENTITIES_COLUMN_LABEL)
+        attribute_name = row.get(ATTRIBUTES_COLUMN_LABEL)
+        same_as_row = row.get(SAMEAS_COLUMN_LABEL)
+        same_as_list = same_as_row.split(',') if same_as_row else []
+
+        if entity_name:
+            current_entity = entity_name
+            entity[current_entity] = {}
+
+        if current_entity and attribute_name:
+            if not entity[current_entity].get('Attributi'):
+                entity[current_entity]['Attributi'] = []
+            entity[current_entity]['Attributi'].append(attribute_name)
+
+        if current_entity and same_as_list:
+            same_as[current_entity] = [s.strip() for s in same_as_list]
+
+    # Add subclass information
+    for row in relations_local:
+        entity1 = row.get(RELATION_FIRST_COLUMN_LABEL)
+        entity2 = row.get(RELATION_SECOND_COLUMN_LABEL)
+        label = row.get(RELATION_NAME_COLUMN_LABEL)
+
+        if label == "is_subclass_of":
+            if entity1 in entity:
+                entity[entity1]["Sottoclasse di"] = entity2
+
+    # Construct relations
+    entity_relations = []
+    for row in relations_local:
+        if row['NOME RELAZIONE'] != "is_subclass_of":
+            relation = {
+                "Entità 1": row['ENTITÀ 1'],
+                "Entità 2": row['ENTITÀ 2'],
+                "Etichetta": row['NOME RELAZIONE'],
+                "Inversa": row['NOME RELAZIONE INVERSA']
+            }
+            entity_relations.append(relation)
+
+    # Create final JSON structure
+    data = {
+        "Entità": entity,
+        "Relazioni": entity_relations,
+        "Same_as": same_as
+    }
+
+    return data
+# %%
+json_data = dict_lists_to_json(entities, relations)
+
+with open(DATA_FOLDER + basename + '.json', 'w') as out_json:
+    json.dump(json_data, out_json, indent=2, ensure_ascii=False)
+# %%

+ 0 - 0
readme.md


+ 204 - 0
reparsing_2_TO_REVIEW.py

@@ -0,0 +1,204 @@
+# %%
+import json
+import csv
+
+# IMPORT MASTER FILE
+with open('.dat/man_draft.json', 'r') as in_file:
+    data = json.load(in_file)
+with open('entities_in.csv', 'r') as csv_in_1:
+    reader = csv.DictReader(csv_in_1)
+    ent_csv_in = [row for row in reader]
+with open('relations_in.csv', 'r') as csv_in_2:
+    reader = csv.DictReader(csv_in_2)
+    rel_csv_in = [row for row in reader]
+# %%
+# Consistency check
+
+entity_rels = {ent for rel in data['Relazioni'] for ent in [rel['Entità 1'], rel['Entità 2']]}
+
+entities = set(data['Entità'].keys())
+entities.add('#any') # For compatibility
+
+if not entity_rels.issubset(entities):
+    print(entity_rels.difference(entities))
+# %%
+# USE A DIRTY SHORTCUT: paste entity/relation info on a precompiled rdf template file.
+
+# Load template
+with open('template_2.rdf', 'r') as in_file:
+    raw_rdf = in_file.read()
+
+# Defined rdf snippets; info will replace placeholder tags (in uppercase between '#')
+entity_template = '''
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:Class rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <rdfs:subClassOf>#PARENT#</rdfs:subClassOf>
+        <rdfs:isDefinedBy rdf:resource="#URI#"/>
+    </owl:Class>
+'''
+subclass_string = "        <rdfs:subClassOf>#PARENT#</rdfs:subClassOf>\n"
+class_defined_string = '        <rdfs:isDefinedBy rdf:resource="#URI#"/>\n'
+
+object_property_template = '''
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:ObjectProperty rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <rdfs:range rdf:resource="&h2iosc;#RANGE#"/>
+        <rdfs:domain rdf:resource="&h2iosc;#DOMAIN#"/>
+        <rdfs:isDefinedBy rdf:resource="#URI#"/>
+    </owl:ObjectProperty>
+'''
+
+object_property_inverse_template = '''
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:ObjectProperty rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <owl:inverseOf rdf:resource="&h2iosc;#INV#"/>
+        <rdfs:range rdf:resource="&h2iosc;#RANGE#"/>
+        <rdfs:domain rdf:resource="&h2iosc;#DOMAIN#"/>
+        <rdfs:isDefinedBy rdf:resource="#URI#"/>
+    </owl:ObjectProperty>
+'''
+object_defined_string = '        <rdfs:isDefinedBy rdf:resource="#URI#"/>\n'
+
+datatype_property_template = '''
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:DatatypeProperty rdf:about="&h2iosc;#NAME#" rdf:isDefinedBy="#URI#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <rdfs:domain rdf:resource="&h2iosc;#DOMAIN#"/>
+        <rdfs:isDefinedBy rdf:resource="#URI#"/>
+    </owl:DatatypeProperty>
+'''
+datatype_defined_string = '        <rdfs:isDefinedBy rdf:resource="#URI#"/>\n'
+
+# Define a normalization function for rdf labels for easier portability
+def label_to_name(label):
+    return label.replace(' ', '_').replace('à', 'a').replace('è', 'e').replace('é', 'e').replace('ì', 'i').replace('ò', 'o').replace('ù', 'u')
+
+# Generic ('propietary') datatypes to std. xsd datatypes mapping
+datatype_xsd = {
+    "#string": 'string',
+    '#uri': '#uri',
+    '#number': 'decimal',
+    '#date': 'date',
+    '#coordinates': '#coordinates'
+}
+
+# %%
+# Map entity info to dedicated lists
+entities_rdf_list = []
+entities_csv = []
+datatype_properties_rdf_list = []
+same_as = list(data['Same_as'].keys())
+for label, ent in data['Entità'].items():
+    
+    entity_name = label_to_name(label)
+    entity_rdf = entity_template.replace('#LABEL#', label).replace('#NAME#', entity_name)
+
+    # Try to find entity in extra csv, see if there is CIDOC info and if so, map it
+    entity_in_csv = next((ent for ent in ent_csv_in if ent['ENTITÀ']==label), None)
+    cidoc_class = None
+    if entity_in_csv is not None:
+        cidoc_class = entity_in_csv.get('CIDOC-LINK')
+    if cidoc_class is not None and cidoc_class!='':
+        entity_rdf = entity_rdf.replace('#URI#', cidoc_class)
+    else:
+        entity_rdf = entity_rdf.replace(class_defined_string, '')
+
+    # Subclasses
+    if 'Sottoclasse di' in ent.keys():
+        parent = ent['Sottoclasse di']
+        data['Relazioni'].append({"Entità 1": label,
+            "Entità 2": parent,
+            "Etichetta": "is_subclass_of", "Inversa": "is_superclass_of"})
+        entity_rdf = entity_rdf.replace('#PARENT#', label_to_name(parent))
+    else:
+        entity_rdf = entity_rdf.replace(subclass_string, '')
+
+    entities_rdf_list.append(entity_rdf)
+    #
+    if label in same_as:
+        entities_csv.append( [label, "", ', '.join(data['Same_as'][label])] )
+    else:
+        entities_csv.append([label, "", ""])
+    for datatype_label, datatype_val in ent.items():
+        if not isinstance(datatype_val, str) or not datatype_val.startswith('#'):
+            continue
+        entities_csv.append(["", datatype_label, ""])
+        datatype_name = label_to_name(datatype_label)
+        datatype_rdf = datatype_property_template.replace('#LABEL#', datatype_label).replace('#NAME#', datatype_name).replace('#DOMAIN#', entity_name)
+        # Try to find entity in extra csv, see if there is CIDOC info and if so, map it
+        datatype_in_csv = next((ent for ent in ent_csv_in if ent['ATTRIBUTO (LITERAL)']==datatype_label), None)
+        cidoc_class = None
+        if datatype_in_csv is not None:
+            cidoc_class = datatype_in_csv.get('CIDOC-LINK')
+        if cidoc_class is not None and cidoc_class!='':
+            datatype_rdf = datatype_rdf.replace('#URI#', cidoc_class)
+        else:
+            datatype_rdf = datatype_rdf.replace(datatype_defined_string, '')
+
+        datatype_properties_rdf_list.append(datatype_rdf)
+
+
+# Map relation info to dedicated lists
+relations_rdf_list = []
+relations_csv = []
+for rel in data['Relazioni']:
+    label = rel['Etichetta']
+    inverse_label = rel['Inversa']
+    domain = label_to_name(rel['Entità 1'])
+    range1 = label_to_name(rel['Entità 2'])
+    relations_csv.append([rel['Entità 1'], rel['Entità 2'], rel['Etichetta'], rel['Inversa']])
+    name = domain + '_' + label_to_name(label) + '_' + range1
+    inverse_name = range1 + '_' + label_to_name(inverse_label) + '_' + domain
+
+    # Try to find entity in extra csv, see if there is CIDOC info and if so, map it
+    relation_in_csv = next((rel_csv for rel_csv in rel_csv_in if (rel_csv['ENTITÀ 1']==rel['Entità 1'] and rel_csv['ENTITÀ 2']==rel['Entità 2']) ), None)
+    cidoc_class = None
+    #
+    relation_rdf = object_property_template.replace('#NAME#', name).replace('#LABEL#', label).replace('#DOMAIN#', domain).replace('#RANGE#', range1)
+    #
+    if relation_in_csv is not None:
+        cidoc_class = relation_in_csv.get('CIDOC-LINK')
+    if cidoc_class is not None and cidoc_class!='':
+        relation_rdf = relation_rdf.replace('#URI#', cidoc_class)
+    else:
+        relation_rdf = relation_rdf.replace(object_defined_string, '')
+    #
+    relation_inverse_rdf = object_property_inverse_template.replace('#NAME#', inverse_name).replace('#LABEL#', inverse_label).replace('#DOMAIN#', range1).replace('#RANGE#', domain).replace('#INV#', name)
+    #
+    if cidoc_class is not None and cidoc_class!='':
+        relation_inverse_rdf = relation_inverse_rdf.replace('#URI#', cidoc_class)
+    else:
+        relation_inverse_rdf = relation_inverse_rdf.replace('<rdfs:isDefinedBy rdf:resource="#URI#"/>', '')
+    #
+    relation_full_rdf = relation_rdf + '\n\n\n' + relation_inverse_rdf
+    relations_rdf_list.append(relation_full_rdf)
+
+
+# Write info to template and export it to output file
+with open('draft.rdf', 'w') as out_file:
+    to_out = raw_rdf.replace(entity_template, '\n\n\n'.join(entities_rdf_list)).replace(datatype_property_template, '\n\n\n'.join(datatype_properties_rdf_list)).replace(object_property_inverse_template, '\n\n\n'.join(relations_rdf_list))
+    out_file.write(to_out)
+# %%
+# Write info to two csv files (one for Entities, one for Relations) for extra human readability
+with open('entities.csv', 'w') as out_csv:
+    writer = csv.writer(out_csv)
+    writer.writerow(['ENTITÀ', 'ATTRIBUTO (LITERAL)', 'SAME AS'])
+    writer.writerows(entities_csv)
+with open('relations.csv', 'w') as out_csv:
+    writer = csv.writer(out_csv)
+    writer.writerow(['ENTITÀ 1', 'ENTITÀ 2', 'NOME RELAZIONE', 'NOME RELAZIONE INVERSA'])
+    writer.writerows(relations_csv)
+# %%
+print(raw_rdf)
+# %%
+entity_template in raw_rdf
+# %%
+entity_template
+# %%

+ 142 - 0
reparsing_TO_REVIEW.py

@@ -0,0 +1,142 @@
+# %%
+import json
+import csv
+
+with open('./etc/man_draft.json', 'r') as in_file:
+    data = json.load(in_file)
+# %%
+entity_rels = {ent for rel in data['Relazioni'] for ent in [rel['Entità 1'], rel['Entità 2']]}
+# %%
+entities = set(data['Entità'].keys())
+entities.add('#any') # For compatibility
+# %%
+# Consistency check
+if not entity_rels.issubset(entities):
+    print(entity_rels.difference(entities))
+# %%
+with open('./dat/template.rdf', 'r') as in_file:
+    raw_rdf = in_file.read()
+
+entity_template = '''
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:Class rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <rdfs:subClassOf>#PARENT#</rdfs:subClassOf>
+    </owl:Class>
+'''
+subclass_string = "        <rdfs:subClassOf>#PARENT#</rdfs:subClassOf>\n"
+
+object_property_template = '''
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:ObjectProperty rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <rdfs:range rdf:resource="&h2iosc;#RANGE#"/>
+        <rdfs:domain rdf:resource="&h2iosc;#DOMAIN#"/>
+    </owl:ObjectProperty>
+'''
+
+object_property_inverse_template = '''
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:ObjectProperty rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <owl:inverseOf rdf:resource="&h2iosc;#INV#"/>
+        <rdfs:range rdf:resource="&h2iosc;#RANGE#"/>
+        <rdfs:domain rdf:resource="&h2iosc;#DOMAIN#"/>
+    </owl:ObjectProperty>
+'''
+
+datatype_property_template = '''
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:DatatypeProperty rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <rdfs:domain rdf:resource="&h2iosc;#DOMAIN#"/>
+    </owl:DatatypeProperty>
+'''
+
+
+def label_to_name(label):
+    return label.replace(' ', '_').replace('à', 'a').replace('è', 'e').replace('é', 'e').replace('ì', 'i').replace('ò', 'o').replace('ù', 'u')
+
+
+datatype_xsd = {
+    "#string": 'string',
+    '#uri': '#uri',
+    '#number': 'decimal',
+    '#date': 'date',
+    '#coordinates': '#coordinates'
+}
+
+entities_rdf_list = []
+entities_csv = []
+datatype_properties_rdf_list = []
+same_as = list(data['Same_as'].keys())
+for label, ent in data['Entità'].items():
+    
+    entity_name = label_to_name(label)
+    entity_rdf = entity_template.replace('#LABEL#', label).replace('#NAME#', entity_name)
+
+    # Subclasses
+    if 'Sottoclasse di' in ent.keys():
+        parent = ent['Sottoclasse di']
+        data['Relazioni'].append({"Entità 1": label,
+            "Entità 2": parent,
+            "Etichetta": "is_subclass_of", "Inversa": "is_superclass_of"})
+        entity_rdf = entity_rdf.replace('#PARENT#', label_to_name(parent))
+    else:
+        entity_rdf = entity_rdf.replace(subclass_string, '')
+
+    entities_rdf_list.append(entity_rdf)
+    #
+    if label in same_as:
+        entities_csv.append( [label, "", ', '.join(data['Same_as'][label])] )
+    else:
+        entities_csv.append([label, "", ""])
+    for datatype_label, datatype_val in ent.items():
+        if not isinstance(datatype_val, str) or not datatype_val.startswith('#'):
+            continue
+        entities_csv.append(["", datatype_label, ""])
+        datatype_name = label_to_name(datatype_label)
+        datatype_properties_rdf_list.append(
+            datatype_property_template.replace('#LABEL#', datatype_label).replace(
+                '#NAME#', datatype_name
+            ).replace('#DOMAIN#', entity_name)
+        )
+
+relations_rdf_list = []
+relations_csv = []
+for rel in data['Relazioni']:
+    label = rel['Etichetta']
+    inverse_label = rel['Inversa']
+    domain = label_to_name(rel['Entità 1'])
+    range1 = label_to_name(rel['Entità 2'])
+    relations_csv.append([rel['Entità 1'], rel['Entità 2'], rel['Etichetta'], rel['Inversa']])
+    name = domain + '_' + label_to_name(label) + '_' + range1
+    inverse_name = range1 + '_' + label_to_name(inverse_label) + '_' + domain
+    #
+    relation_rdf = object_property_template.replace('#NAME#', name).replace('#LABEL#', label).replace('#DOMAIN#', domain).replace('#RANGE#', range1)
+    #
+    relation_inverse_rdf = object_property_inverse_template.replace('#NAME#', inverse_name).replace('#LABEL#', inverse_label).replace('#DOMAIN#', range1).replace('#RANGE#', domain).replace('#INV#', name)
+    #
+    relation_full_rdf = relation_rdf + '\n\n\n' + relation_inverse_rdf
+    relations_rdf_list.append(relation_full_rdf)
+
+
+with open('./etc/draft.rdf', 'w') as out_file:
+    to_out = raw_rdf.replace(entity_template, '\n\n\n'.join(entities_rdf_list)).replace(
+        datatype_property_template, '\n\n\n'.join(datatype_properties_rdf_list)
+    ).replace(object_property_inverse_template, '\n\n\n'.join(relations_rdf_list))
+    out_file.write(to_out)
+# %%
+with open('./etc/entities.csv', 'w') as out_csv:
+    writer = csv.writer(out_csv)
+    writer.writerow(['ENTITÀ', 'ATTRIBUTO (LITERAL)', 'SAME AS'])
+    writer.writerows(entities_csv)
+with open('./etc/relations.csv', 'w') as out_csv:
+    writer = csv.writer(out_csv)
+    writer.writerow(['ENTITÀ 1', 'ENTITÀ 2', 'NOME RELAZIONE', 'NOME RELAZIONE INVERSA'])
+    writer.writerows(relations_csv)
+# %%

+ 74 - 0
template.rdf

@@ -0,0 +1,74 @@
+<?xml version="1.0"?>
+
+
+<!DOCTYPE rdf:RDF [
+    <!-- Link da rivedere -->
+    <!ENTITY h2iosc "http://www.h2iosc.it/onto#" >
+    <!ENTITY owl "https://www.w3.org/TR/owl-ref#" >
+    <!ENTITY rdfs "https://www.w3.org/TR/rdf11-schema#" >
+    <!ENTITY rdf "https://www.w3.org/TR/rdf11-concepts#" >
+]>
+
+
+<rdf:RDF xmlns="http://www.h2iosc.it/onto#"
+     xml:base="http://www.h2iosc.it/onto"
+     xmlns:h2iosc="http://www.h2iosc.it/onto#"
+     xmlns:owl="http://www.w3.org/2002/07/owl#"
+     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
+    <owl:Ontology rdf:about="http://www.h2iosc.it/onto#"/>
+    
+
+
+    <!-- 
+    ///////////////////////////////////////////////////////////////////////////////////////
+    //
+    // Object Properties
+    //
+    ///////////////////////////////////////////////////////////////////////////////////////
+     -->
+
+
+
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:ObjectProperty rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <owl:inverseOf rdf:resource="&h2iosc;#INV#"/>
+        <rdfs:range rdf:resource="&h2iosc;#RANGE#"/>
+        <rdfs:domain rdf:resource="&h2iosc;#DOMAIN#"/>
+    </owl:ObjectProperty>
+    
+
+    <!-- 
+    ///////////////////////////////////////////////////////////////////////////////////////
+    //
+    // Data properties
+    //
+    ///////////////////////////////////////////////////////////////////////////////////////
+     -->
+    
+
+    <owl:DatatypeProperty rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <rdfs:domain rdf:resource="&h2iosc;#DOMAIN#"/>
+    </owl:DatatypeProperty>
+
+    <!-- 
+    ///////////////////////////////////////////////////////////////////////////////////////
+    //
+    // Classes
+    //
+    ///////////////////////////////////////////////////////////////////////////////////////
+     -->
+
+
+    <!-- http://www.h2iosc.it/onto##NAME# -->
+
+    <owl:Class rdf:about="&h2iosc;#NAME#">
+        <rdfs:label>#LABEL#</rdfs:label>
+        <rdfs:subClassOf>#PARENT#</rdfs:subClassOf>
+    </owl:Class>
+    
+</rdf:RDF>
+