|
@@ -0,0 +1,783 @@
|
|
|
+{
|
|
|
+ "cells": [
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Inizio radunando tutti gli **IMPORT** necessari per girare il notebook, per chiarezza."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 2,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "# IMPORT ESSENZIALI\n",
|
|
|
+ "\n",
|
|
|
+ "# Per il parsing dell'XML -- questo pacchetto è incluso anche nel più generale lxml\n",
|
|
|
+ "import xml.etree.ElementTree as ET\n",
|
|
|
+ "# Utilities per leggere/scrivere files csv\n",
|
|
|
+ "import csv\n",
|
|
|
+ "# Utilities per gestire i character encodings\n",
|
|
|
+ "import unicodedata\n",
|
|
|
+ "# Dizionari ordinati\n",
|
|
|
+ "from collections import OrderedDict\n",
|
|
|
+ "\n",
|
|
|
+ "\n",
|
|
|
+ "# IMPORT OPZIONALI\n",
|
|
|
+ "\n",
|
|
|
+ "# Per fare un stima della velocità delle varie istruzioni\n",
|
|
|
+ "from datetime import datetime\n",
|
|
|
+ "# Generatore di numeri casuali -- può sempre servire in fase di testing\n",
|
|
|
+ "from random import *\n",
|
|
|
+ "# Può servire per alcuni test\n",
|
|
|
+ "import sys\n",
|
|
|
+ "# Per le regex\n",
|
|
|
+ "import re"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# FUNZIONI\n",
|
|
|
+ "\n",
|
|
|
+ "**ElementTree** ha una funzione built-in, **iter**, che scorre (molto velocemente) su tutti i 'nodi' dell'albero di dati che rappresenta l'XML. La funzione *iter* purtroppo però non traccia i nodi 'parents'.\n",
|
|
|
+ "\n",
|
|
|
+ "Ho esteso quindi la libreria scrivendo una mia versione di *iter*, **'traceElems'**, che dovrebbe riuscire a fornirci tutto quello di cui abbiamo bisogno.\n",
|
|
|
+ "\n",
|
|
|
+ "*traceElems* traccia tutti i nodi nell'albero tenendo conto dei 'parents', e restituisce tutti quelli per cui la funzione-argomento 'condition' ritorna True. **NON** indaga i nodi **figli** di quelli che sono restituiti."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 3,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "# La funzione BASE: traceElems\n",
|
|
|
+ "def traceElems(node: ET.Element, condition, parents: list = [], coords: list = []):\n",
|
|
|
+ " res = []\n",
|
|
|
+ " jj = 0\n",
|
|
|
+ " for child in node:\n",
|
|
|
+ " if condition(child):\n",
|
|
|
+ " res.append({'a_par': parents+[node],\n",
|
|
|
+ " 'coords': coords+[jj], 'child': child})\n",
|
|
|
+ " else:\n",
|
|
|
+ " res = res + traceElems(child, condition, parents+[node], coords+[jj])\n",
|
|
|
+ " jj = jj+1 \n",
|
|
|
+ " return res\n",
|
|
|
+ "\n",
|
|
|
+ "# Funzione-base per stoppare traceElems\n",
|
|
|
+ "def isLeafOrC(aa: ET.Element):\n",
|
|
|
+ " if(aa.tag=='c' or len(aa)==0):\n",
|
|
|
+ " return True\n",
|
|
|
+ " else:\n",
|
|
|
+ " return False"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 4,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "# Funzioni-utilità che servono solo a visualizzare meglio i dati sul notebook.\n",
|
|
|
+ "def shownode(node: ET.Element):\n",
|
|
|
+ " return (node.tag, node.attrib, node.text.replace('\\t','').replace('n','').strip() \\\n",
|
|
|
+ " if type(node.text) is str else '')\n",
|
|
|
+ "\n",
|
|
|
+ "def shownodelist(el: ET.Element):\n",
|
|
|
+ " return list(map(shownode, el))\n",
|
|
|
+ "\n",
|
|
|
+ "\n",
|
|
|
+ "# Utility copiata da INTERNEZZ -- versione 'multipla' del metodo str.index:\n",
|
|
|
+ "def indices(lst, element):\n",
|
|
|
+ " result = []\n",
|
|
|
+ " offset = -1\n",
|
|
|
+ " while True:\n",
|
|
|
+ " try:\n",
|
|
|
+ " offset = lst.index(element, offset+1)\n",
|
|
|
+ " except ValueError:\n",
|
|
|
+ " return result\n",
|
|
|
+ " result.append(offset)"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# AL LAVORO"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "**DA CAMBIARE A SECONDA DEL COMPUTER**: directory di input e output"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 5,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "import_dir = '/home/kora/Desktop/OVI_Data_Local/ASPO/XML/'\n",
|
|
|
+ "export_dir = '/home/kora/Desktop/OVI_Data_Local/ASPO/CSV/Gettatelli/'\n",
|
|
|
+ "\n",
|
|
|
+ "#import_dir = '/Users/federicaspinelli/Google Drive/OVI:CNR/LAVORO 2020/SELEZIONE CONTENUTI/01_ASPO/XDAMS/'\n",
|
|
|
+ "#export_dir = '/Users/federicaspinelli/Google Drive/OVI:CNR/CSV/ASPO/gettatelli/'"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Importo il file XML del Datini, tracciando il tempo necessario"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 6,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "0.04100799560546875\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "ts1 = datetime.timestamp(datetime.now())\n",
|
|
|
+ "\n",
|
|
|
+ "treeDatini = ET.parse(import_dir + 'export_aspoGT001--gettatelli.xml')\n",
|
|
|
+ "rootDatini = treeDatini.getroot()\n",
|
|
|
+ "\n",
|
|
|
+ "ts2 = datetime.timestamp(datetime.now())\n",
|
|
|
+ "print(ts2 - ts1)"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Uso *iter* per trovare tutti i nodi con label **'c'** nel file Datini, e mi faccio restituire il\n",
|
|
|
+ "valore dell'attributo **'level'**; salvo tutti i *levels* nella variabile **cLevs**"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 7,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "{'item', 'fonds'}\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "cLevs = set(map(lambda a : a.attrib['level'], rootDatini.iter('c')))\n",
|
|
|
+ "print(cLevs)"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "A questo punto metto al lavoro la funzione **traceElems**: registro TUTTI i nodi **'c'** dividendoli in base all'attributo **'level'**; mi faccio stampare il numero di elementi per ogni livello ed il tempo trascorso.\n",
|
|
|
+ "\n",
|
|
|
+ "**OCCHIO:** per come è costruita, questa routine non va ad investigare dentro i livelli restituiti -- quindi si perde eventuali sotto-livelli con la stessa label di quelli che trova durante il primo scan. La presenza di sotto-livelli di questo tipo va controllata separatamente."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 8,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "# di tag \"c\", livello item, primo passaggio: 685\n",
|
|
|
+ "# di tag \"c\", livello fonds, primo passaggio: 1\n",
|
|
|
+ "\n",
|
|
|
+ "Tempo trascorso: 0.0016021728515625\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "ts1 = datetime.timestamp(datetime.now())\n",
|
|
|
+ "\n",
|
|
|
+ "allCs = {}\n",
|
|
|
+ "\n",
|
|
|
+ "for label in cLevs:\n",
|
|
|
+ " def tempFilt(aa: ET.Element):\n",
|
|
|
+ " if(aa.tag=='c' and aa.attrib['level']==label):\n",
|
|
|
+ " return True\n",
|
|
|
+ " else:\n",
|
|
|
+ " return False\n",
|
|
|
+ " \n",
|
|
|
+ " allCs[label] = traceElems(rootDatini, tempFilt);\n",
|
|
|
+ " print('# di tag \"c\", livello ' + label + ', primo passaggio:', len(allCs[label]))\n",
|
|
|
+ "\n",
|
|
|
+ "print()\n",
|
|
|
+ "print('Tempo trascorso:', datetime.timestamp(datetime.now()) - ts1)"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Notare che l'elaborazione è piuttosto veloce (sul mio laptop) malgrado la dimensione del file.\n",
|
|
|
+ "\n",
|
|
|
+ "Rimane il problema dei livelli dentro a livelli omonimi. Vediamo di affrontarlo."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 9,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "# di tag \"c\", livello item, primo passaggio: 685\n",
|
|
|
+ "# di tag \"c\", livello item, totali: 685\n",
|
|
|
+ "# di tag \"c\", livello fonds, primo passaggio: 1\n",
|
|
|
+ "# di tag \"c\", livello fonds, totali: 1\n",
|
|
|
+ "\n",
|
|
|
+ "Tempo trascorso: 0.024380922317504883\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "ts1 = datetime.timestamp(datetime.now())\n",
|
|
|
+ "\n",
|
|
|
+ "allCs2 = {}\n",
|
|
|
+ "\n",
|
|
|
+ "for label in cLevs:\n",
|
|
|
+ " partial = allCs[label]\n",
|
|
|
+ " print('# di tag \"c\", livello ' + label + ', primo passaggio:', len(partial))\n",
|
|
|
+ " allCs2[label] = partial\n",
|
|
|
+ " partialUpdate = []\n",
|
|
|
+ " while True:\n",
|
|
|
+ " def tempFilt(aa: ET.Element):\n",
|
|
|
+ " if(aa.tag=='c' and aa.attrib['level']==label):\n",
|
|
|
+ " return True\n",
|
|
|
+ " else:\n",
|
|
|
+ " return False\n",
|
|
|
+ " for node in partial:\n",
|
|
|
+ " partialUpdate = partialUpdate + traceElems(node['child'], tempFilt)\n",
|
|
|
+ " #print(len(partialUpdate))\n",
|
|
|
+ " partial = partialUpdate\n",
|
|
|
+ " if(len(partialUpdate)==0):\n",
|
|
|
+ " break\n",
|
|
|
+ " allCs2[label] = allCs2[label] + partial\n",
|
|
|
+ " partialUpdate = []\n",
|
|
|
+ "\n",
|
|
|
+ " print('# di tag \"c\", livello ' + label + ', totali:', len(allCs2[label]))\n",
|
|
|
+ "\n",
|
|
|
+ "print()\n",
|
|
|
+ "print('Tempo trascorso:', datetime.timestamp(datetime.now()) - ts1)"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "A questo punto diventa facile visualizzare tutti i dettagli dei vari elementi **'c'**, di qualunque livello; un esempio è fornito nella prossima cella. Si può cambiare l'elemento da visualizzare cambiando il valore delle variabili *ii* e *level*"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 10,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "item: 25\n",
|
|
|
+ "['c', 'did', 'materialspec']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'label': 'tipologia'}]\n",
|
|
|
+ "['', '', 'scheda anagrafica']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'did', 'repository']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {}]\n",
|
|
|
+ "['', '', 'Archivio di Stato di Prato']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'did', 'unitid', 'extref']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'countrycode': 'IT', 'encodinganalog': 'ISAD 1 - 1 reference code', 'repositorycode': 'ASPO'}, {'role': 'id_galileo'}]\n",
|
|
|
+ "['', '', '', 'A46C062A-DC08-4F95-B54E-69E48DDE7AEB']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'did', 'unitid', 'emph']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'countrycode': 'IT', 'encodinganalog': 'ISAD 1 - 1 reference code', 'repositorycode': 'ASPO'}, {'altrender': 'numero provvisorio'}]\n",
|
|
|
+ "['', '', '', '10']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'did', 'container']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'type': 'registro'}]\n",
|
|
|
+ "['', '', 'VV']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'did', 'unittitle', 'persname', 'emph']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'encodinganalog': 'ISAD 1 - 2 title'}, {'role': 'bambino'}, {'altrender': 'nome'}]\n",
|
|
|
+ "['', '', '', '', 'Perla Maria']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'did', 'unittitle', 'num']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'encodinganalog': 'ISAD 1 - 2 title'}, {'type': 'matricola'}]\n",
|
|
|
+ "['', '', '', '287']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'did', 'unittitle', 'date']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'encodinganalog': 'ISAD 1 - 2 title'}, {'normal': '17820401-17820401', 'type': 'ritrovamento'}]\n",
|
|
|
+ "['', '', '', '01/04/1782']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'did', 'unittitle', 'unitdate', 'emph']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'encodinganalog': 'ISAD 1 - 2 title'}, {'normal': '17820401-17820401'}, {}]\n",
|
|
|
+ "['', '', '', '', 'ritrovamento: 01/04/1782']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'did', 'physdesc', 'physfacet']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'encodinganalog': 'ISAD 1 - 5 extent and medium of the unit of description'}, {'type': 'descrizione contrassegno'}]\n",
|
|
|
+ "['', '', '', 'Nastro in seta gialla con mezzo\\t\\t\\t\\t\\t\\t\\tsoldo in rame.']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'note', 'p']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {'encodinganalog': 'ISAD 6 - 1 note'}, {}]\n",
|
|
|
+ "['', '', 'Nota dell\\'ospedale: \"Si battezzi la bambina di nascita [venuta] per la nostra ferrata alle ore sei incirca della scorsa sera per mano di Rosa vedova di Francesco Galantini di questa citt� quale asser� essere di genitori incerti e del distretto Pistoiese; detta bambina aveva pendente dal collo con un nastro giallo di seta un mezzo soldo di nostra moneta; fu [ricevuta] e mandata al sacro fonte col nome Perla Maria\".\\tSul medesimo biglietto, in calce: \"Ad� 23 aprile 1782. La suddetta bambina consegnata alla Maria Anna di Francesco Toccafondi di S. Lionardo a Vernio\".']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'daogrp', 'daoloc']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'href': '/GETTATELLI/010_a.jpg', 'title': '010_a.JPG'}]\n",
|
|
|
+ "['', '', 'None']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'daogrp', 'daoloc']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'href': '/GETTATELLI/010_a.JPG_1', 'title': '010_a.JPG_1'}]\n",
|
|
|
+ "['', '', 'None']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'daogrp', 'daoloc']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'href': '/GETTATELLI/010_b.jpg', 'title': '010_b.JPG'}]\n",
|
|
|
+ "['', '', 'None']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'daogrp', 'daoloc']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'href': '/GETTATELLI/010_c.JPG_1', 'title': '010_c.JPG_1'}]\n",
|
|
|
+ "['', '', 'None']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'daogrp', 'daoloc']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {'href': '/GETTATELLI/010_c.jpg', 'title': '010_c.JPG'}]\n",
|
|
|
+ "['', '', 'None']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'processinfo', 'list', 'item', 'date']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {}, {}, {}]\n",
|
|
|
+ "['', '', '', '', '04-2014']\n",
|
|
|
+ "\n",
|
|
|
+ "['c', 'processinfo', 'list', 'item', 'persname']\n",
|
|
|
+ "[{'audience': 'external', 'id': 'IT-ASPO-GT001-0000026', 'level': 'item'}, {}, {}, {}, {}]\n",
|
|
|
+ "['', '', '', '', 'regesta.exe']\n",
|
|
|
+ "\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "level = 'item'\n",
|
|
|
+ "ii = 25\n",
|
|
|
+ "test = allCs2[level][ii]\n",
|
|
|
+ "\n",
|
|
|
+ "print(level+':',ii)\n",
|
|
|
+ "\n",
|
|
|
+ "toProc = traceElems(test['child'], isLeafOrC)\n",
|
|
|
+ "for node in toProc:\n",
|
|
|
+ " tags = list(map(lambda a: a.tag, node['a_par'])) + [node['child'].tag]\n",
|
|
|
+ " attributes = list(map(lambda a: a.attrib, node['a_par'])) + [node['child'].attrib]\n",
|
|
|
+ " contents = list(map(lambda a: a.text.replace('\\n','').replace('\\n','').strip(), node['a_par'])) + [str(node['child'].text).replace('\\n','').replace('\\n','').strip()]\n",
|
|
|
+ "\n",
|
|
|
+ " print(tags)\n",
|
|
|
+ " print(attributes) \n",
|
|
|
+ " print(contents)\n",
|
|
|
+ " print()"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "A questo punto, quello che devo fare è scrivere un **traduttore** -- una funzione che scorra l'output degli elementi esaminati e trasformi le info in modo da poterle esportare in formato csv (o in qualunque altro formato vogliamo).\n",
|
|
|
+ "\n",
|
|
|
+ "La mia attuale versione di **traduttore per gli item** è data nella prossima cella; accetta come argomento un nodo (che è supposto essere di tipo item) e restituisce un dict."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 11,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "def traduttoreItem(elem):\n",
|
|
|
+ " # Variabile che contiene l'output della traduzione:\n",
|
|
|
+ " csvProt = {}\n",
|
|
|
+ "\n",
|
|
|
+ " # Processo i nodi-parent di 'elem'\n",
|
|
|
+ " par_tags = list(map(lambda a: a.tag, elem['a_par']))\n",
|
|
|
+ " par_attributes = list(map(lambda a: a.attrib, elem['a_par']))\n",
|
|
|
+ " # e0: Le varie id dei nodi parent\n",
|
|
|
+ " for ii in indices(par_tags, 'c'):\n",
|
|
|
+ " key = 'id_' + par_attributes[ii]['level']\n",
|
|
|
+ " csvProt[key] = par_attributes[ii]['id']\n",
|
|
|
+ "\n",
|
|
|
+ " # Processo i nodi-child di 'elem'\n",
|
|
|
+ " toProc = traceElems(elem['child'], isLeafOrC)\n",
|
|
|
+ " first = True\n",
|
|
|
+ " for node in toProc:\n",
|
|
|
+ " tags = list(map(lambda a: a.tag, node['a_par'])) + [node['child'].tag]\n",
|
|
|
+ " attributes = list(map(lambda a: a.attrib, node['a_par'])) + [node['child'].attrib]\n",
|
|
|
+ " content = node['child'].text\n",
|
|
|
+ "\n",
|
|
|
+ " # Da controllare solo per il primo nodo\n",
|
|
|
+ " # (informazioni a livello del nodo, uguali per tutti i figli)\n",
|
|
|
+ " if(first):\n",
|
|
|
+ " # e1 ID della item\n",
|
|
|
+ " csvProt['id'] = attributes[tags.index('c')]['id']\n",
|
|
|
+ " # e2 Audience: external o internal\n",
|
|
|
+ " try:\n",
|
|
|
+ " csvProt['audience'] = attributes[tags.index('c')]['audience']\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ " # e19 Otherlevel\n",
|
|
|
+ " try:\n",
|
|
|
+ " csvProt['altro_livello'] = attributes[tags.index('c')]['otherlevel']\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ " first = False\n",
|
|
|
+ "\n",
|
|
|
+ " # La 'ciccia': si processa il contenuto vero e proprio\n",
|
|
|
+ " # e11: Il titolo da unittitle\n",
|
|
|
+ " try:\n",
|
|
|
+ " aa = csvProt['titolo_aspo']\n",
|
|
|
+ " except:\n",
|
|
|
+ " try:\n",
|
|
|
+ " ii = tags.index('unittitle')\n",
|
|
|
+ " try:\n",
|
|
|
+ " csvProt['titolo_aspo'] = str(node['a_par'][ii].text).replace('\\t','').replace('\\n','').strip()\n",
|
|
|
+ " except:\n",
|
|
|
+ " csvProt['titolo_aspo'] = str(content).replace('\\t','').replace('\\n','').strip()\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ " # e10 Repository (qui dovrebbe essere sempre l'Archivio di Prato)\n",
|
|
|
+ " if('repository' in tags):\n",
|
|
|
+ " csvProt['repository'] = content\n",
|
|
|
+ "\n",
|
|
|
+ " # e4 Tipologia\n",
|
|
|
+ " try:\n",
|
|
|
+ " ii = tags.index('materialspec')\n",
|
|
|
+ " if(attributes[ii]['label']=='tipologia'): \n",
|
|
|
+ " csvProt['tipologia'] = content\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ "\n",
|
|
|
+ " # e1 Persona + ruolo\n",
|
|
|
+ " try:\n",
|
|
|
+ " ii = tags.index('emph')\n",
|
|
|
+ " type1 = attributes[ii]['altrender']\n",
|
|
|
+ " if(type1=='cognome'):\n",
|
|
|
+ " csvProt['cognome_bambino'] = content\n",
|
|
|
+ " if(type1=='nome'):\n",
|
|
|
+ " csvProt['nome_bambino'] = content\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ "\n",
|
|
|
+ " # e2 Matricola\n",
|
|
|
+ " try:\n",
|
|
|
+ " ii = tags.index('num')\n",
|
|
|
+ " type1 = attributes[ii]['type']\n",
|
|
|
+ " if(type1=='matricola'):\n",
|
|
|
+ " csvProt['matricola'] = content\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ " \n",
|
|
|
+ " # e6 Registri Gettatelli\n",
|
|
|
+ " try:\n",
|
|
|
+ " ii = tags.index('container')\n",
|
|
|
+ " type1 = attributes[ii]['type']\n",
|
|
|
+ " if(type1=='registro'):\n",
|
|
|
+ " csvProt['riferimento_registro'] = content\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ "\n",
|
|
|
+ " #e7 Id oggetto nella scatola\n",
|
|
|
+ " try:\n",
|
|
|
+ " aa = csvProt['id_oggetto']\n",
|
|
|
+ " except:\n",
|
|
|
+ " try:\n",
|
|
|
+ " ii = tags.index('unitid')\n",
|
|
|
+ " try:\n",
|
|
|
+ " tails = \"\"\n",
|
|
|
+ " for chi in node['a_par'][ii]:\n",
|
|
|
+ " tails = \"\" + chi.tail\n",
|
|
|
+ " csvProt['id_oggetto'] = (node['a_par'][ii].text + tails).replace('\\t','').replace('\\n','').strip()\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ " \n",
|
|
|
+ " # e2 Date varie: tutte quelle con 'type' definito\n",
|
|
|
+ " try:\n",
|
|
|
+ " ii = tags.index('date')\n",
|
|
|
+ " key = 'data_' + attributes[ii]['type']\n",
|
|
|
+ " csvProt[key] = content\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ " \n",
|
|
|
+ " # e3 Data 1: periodo\n",
|
|
|
+ " if('unitdate' in tags):\n",
|
|
|
+ " csvProt['data_periodo'] = content\n",
|
|
|
+ "\n",
|
|
|
+ " # e1 Scope-content head & body\n",
|
|
|
+ " if('scopecontent' in tags):\n",
|
|
|
+ " if('head' in tags):\n",
|
|
|
+ " csvProt['scope-content_head'] = content\n",
|
|
|
+ " else:\n",
|
|
|
+ " if('p' in tags):\n",
|
|
|
+ " csvProt['scope-content_body'] = content\n",
|
|
|
+ "\n",
|
|
|
+ " # e8 Supporto fisico\n",
|
|
|
+ " try:\n",
|
|
|
+ " ii = tags.index('physfacet')\n",
|
|
|
+ " if(attributes[ii]['type']=='descrizione contrassegno'):\n",
|
|
|
+ " csvProt['descrizione_contrassegno'] = content\n",
|
|
|
+ " if(attributes[ii]['type']=='conservazione'):\n",
|
|
|
+ " csvProt['conservazione'] = content\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass\n",
|
|
|
+ "\n",
|
|
|
+ " # e11 Note\n",
|
|
|
+ " if('note' in tags):\n",
|
|
|
+ " csvProt['nota'] = content\n",
|
|
|
+ " \n",
|
|
|
+ " # e13 Oggetto digitale allegato (nome)\n",
|
|
|
+ " # Questo è un campo multiplo; per il momento, salviamo tutto\n",
|
|
|
+ " # su una cella concatenando e separando i campi con una pipe\n",
|
|
|
+ " # '| '\n",
|
|
|
+ " try:\n",
|
|
|
+ " ii = tags.index('daoloc')\n",
|
|
|
+ " out = attributes[ii]['title']\n",
|
|
|
+ " try:\n",
|
|
|
+ " csvProt['oggetto_digitale'] = csvProt['oggetto_digitale'] + ' | ' + out\n",
|
|
|
+ " except:\n",
|
|
|
+ " csvProt['oggetto_digitale'] = out\n",
|
|
|
+ " except:\n",
|
|
|
+ " pass \n",
|
|
|
+ " \n",
|
|
|
+ " return csvProt\n",
|
|
|
+ "\n",
|
|
|
+ "\n",
|
|
|
+ "# Di pari passo alla funzione, definisco un dict contenente tutti gli header;\n",
|
|
|
+ "# servirà per il CSV.\n",
|
|
|
+ "itemHeader = OrderedDict()\n",
|
|
|
+ "\n",
|
|
|
+ "# e1 ID dell'entità\n",
|
|
|
+ "itemHeader.update({'id': '<c level=\"X\" id=#>'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e2 Audience: external o internal\n",
|
|
|
+ "itemHeader.update({'audience': '<c level=\"item\" audience=#>'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e15 Repository (qui dovrebbe essere sempre l'Archivio di Prato)\n",
|
|
|
+ "itemHeader.update({'repository': '<repository>#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e10 Tipologia\n",
|
|
|
+ "itemHeader.update({'tipologia': '<materialspec label=\"tipologia\">#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e11 Persona + ruolo\n",
|
|
|
+ "itemHeader.update(\n",
|
|
|
+ "{'cognome_bambino': '<emph altrender=\"cognome\">#', 'nome_bambino': '<emph altrender=\"nome\">#',})\n",
|
|
|
+ "\n",
|
|
|
+ "# e17 Segnatura codice\n",
|
|
|
+ "itemHeader.update({'matricola': '<num type=\"matricola\">#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e12 Registri Gettatelli\n",
|
|
|
+ "itemHeader.update(\n",
|
|
|
+ "{'riferimento_registro':'<container type=\"registro\">#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e7 ID oggetto\n",
|
|
|
+ "itemHeader.update({'id_oggetto': '<unitid>#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e8 Date varie: tutte quelle con 'type' definito\n",
|
|
|
+ "itemHeader.update(\n",
|
|
|
+ "{'data_ritrovamento': '<date type=\"ritrovamento\">#',\n",
|
|
|
+ " 'data_nascita': '<date type=\"nascita\">#',\n",
|
|
|
+ " 'data_morte': '<date type=\"morte\">#',\n",
|
|
|
+ " 'data_ricongiungimento': '<date type=\"ricongiungimento\">#',\n",
|
|
|
+ " 'data_adozione': '<date type=\"adozione\">#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e4 Titolo ASPO\n",
|
|
|
+ "itemHeader.update({'titolo_aspo': '<unittitle>#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e7 Data 1: periodo\n",
|
|
|
+ "itemHeader.update({'data_periodo': '<unitdate>#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e14 Supporto fisico\n",
|
|
|
+ "itemHeader.update({'descrizione_contrassegno': '<physfacet type=\"descrizione contrassegno\">#', 'conservazione': '<physfacet type=\"conservazione\">#' })\n",
|
|
|
+ "\n",
|
|
|
+ "# e3 Scope content, head & body\n",
|
|
|
+ "itemHeader.update(\n",
|
|
|
+ "{'scope-content_head': '<scopecontent><head>#',\n",
|
|
|
+ " 'scope-content_body': '<scopecontent><p>#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# Note\n",
|
|
|
+ "itemHeader.update({'nota': '<note>#'})\n",
|
|
|
+ "\n",
|
|
|
+ "# e18 Oggetto digitale allegato (nome)\n",
|
|
|
+ "itemHeader.update({'oggetto_digitale': '<daoloc title=#>'})\n",
|
|
|
+ "\n",
|
|
|
+ "#0: Le varie id dei nodi parent\n",
|
|
|
+ "itemHeader.update(\n",
|
|
|
+ "{'id_subfonds': '<c level=\"subfonds\" id=#>',\n",
|
|
|
+ " 'id_fonds': '<c level=\"fonds\" id=#>',\n",
|
|
|
+ " 'id_series': '<c level=\"series\" id=#>',\n",
|
|
|
+ " 'id_subseries': '<c level=\"subseries\" id=#>',\n",
|
|
|
+ " 'id_file': '<c level=\"file\" id=#>',\n",
|
|
|
+ " 'id_otherlevel': '<c level=\"otherlevel\" id=#>',\n",
|
|
|
+ " 'id_collection': '<c level=\"collection\" id=#>'})"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Test della funzione traduttore\n",
|
|
|
+ "\n",
|
|
|
+ "**NB:** l'ho definita basandomi sugli item, ma sembra funzionare decentemente anche sugli altri livelli!"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Export\n",
|
|
|
+ "\n",
|
|
|
+ "Produciamo il CSV per gli item tracciando, al solito, il tempo impiegato."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 12,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Tempo trascorso: 0.10759091377258301\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "# Do it! Export del CSV - items.\n",
|
|
|
+ "\n",
|
|
|
+ "ts1 = datetime.timestamp(datetime.now())\n",
|
|
|
+ "\n",
|
|
|
+ "# Apro il file per l'export\n",
|
|
|
+ "with open(export_dir + \"data_item.csv\", \"w\", newline=\"\") as csv_file:\n",
|
|
|
+ " # Definisco la classe-motore per l'export\n",
|
|
|
+ " writer = csv.DictWriter(csv_file, fieldnames=list(itemHeader.keys()))\n",
|
|
|
+ " # Scrivo l'intestazione\n",
|
|
|
+ " writer.writeheader()\n",
|
|
|
+ " # Scrivo la seconda riga, esplicativa\n",
|
|
|
+ " writer.writerow(itemHeader)\n",
|
|
|
+ " # Scrivo gli item tradotti, uno a uno\n",
|
|
|
+ " for ii in range(len(allCs2['item'])):\n",
|
|
|
+ " test = allCs2['item'][ii]\n",
|
|
|
+ " writer.writerow(traduttoreItem(test))\n",
|
|
|
+ "\n",
|
|
|
+ "print('Tempo trascorso:', datetime.timestamp(datetime.now()) - ts1)"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Altri livelli"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Definisco un dizionario ridotto per l'header delle *subseries*, poi esporto -- per il momento con lo stesso traduttore usato per gli *item*"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "*Rinse & Repeat* con i livelli *series*, *subfonds* e *fonds*"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 13,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Tempo trascorso: 0.01978278160095215\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "ts1 = datetime.timestamp(datetime.now())\n",
|
|
|
+ "\n",
|
|
|
+ "fondsKeys = set()\n",
|
|
|
+ "for ii in range(len(allCs2['fonds'])):\n",
|
|
|
+ " test = allCs2['fonds'][ii]\n",
|
|
|
+ " fondsKeys = fondsKeys.union( traduttoreItem(test).keys() )\n",
|
|
|
+ "\n",
|
|
|
+ "fondsHeader = OrderedDict()\n",
|
|
|
+ "for key in itemHeader:\n",
|
|
|
+ " if(key in fondsKeys):\n",
|
|
|
+ " fondsHeader[key] = itemHeader[key]\n",
|
|
|
+ "\n",
|
|
|
+ "\n",
|
|
|
+ "with open(export_dir + \"data_fonds.csv\", \"w\", newline=\"\") as csv_file:\n",
|
|
|
+ " writer = csv.DictWriter(csv_file, fieldnames=list(fondsHeader.keys()))\n",
|
|
|
+ " writer.writeheader()\n",
|
|
|
+ " writer.writerow(fondsHeader)\n",
|
|
|
+ " for ii in range(len(allCs2['fonds'])):\n",
|
|
|
+ " test = allCs2['fonds'][ii]\n",
|
|
|
+ " writer.writerow(traduttoreItem(test))\n",
|
|
|
+ "\n",
|
|
|
+ "print('Tempo trascorso:', datetime.timestamp(datetime.now()) - ts1)"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "metadata": {
|
|
|
+ "kernelspec": {
|
|
|
+ "display_name": "Python 3",
|
|
|
+ "language": "python",
|
|
|
+ "name": "python3"
|
|
|
+ },
|
|
|
+ "language_info": {
|
|
|
+ "codemirror_mode": {
|
|
|
+ "name": "ipython",
|
|
|
+ "version": 3
|
|
|
+ },
|
|
|
+ "file_extension": ".py",
|
|
|
+ "mimetype": "text/x-python",
|
|
|
+ "name": "python",
|
|
|
+ "nbconvert_exporter": "python",
|
|
|
+ "pygments_lexer": "ipython3",
|
|
|
+ "version": "3.6.9"
|
|
|
+ },
|
|
|
+ "metadata": {
|
|
|
+ "interpreter": {
|
|
|
+ "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "nbformat": 4,
|
|
|
+ "nbformat_minor": 2
|
|
|
+}
|