Make Glossary (mkgloss)#

Wir halten das Glossar in der Excel-Datei mkgloss.xls und/oder der Mindmap mkgloss.mm vor (beide Dateien lassen sich mischen).

Das vorliegende Notebook 0_mkgloss.ipynb generiert dann daraus die Datei mkgloss_glossar.txt, die wir in der Markdown-Datei Glossar dann importieren. Dazu muss dieses Notebook die Datei mkgloss_glossar.txt erzeugen, bevor diese Datei selbst compiliert wird, und also von Sphinx vor dieser Datei durchlaufen. Weil die Notebooks in alfabetischer Reihenfolge durchlaufen werden, startet der Namen dieses Notebooks mit einer 0_....

Installation#

  • das Notebook 0_mkgloss.ipynb von dieser Seite herunterladen, in den Ordner der anderen Notebooks legen, in die Datei _toc.yml einfügen

  • bei Bedarf die Variablen gloss_xls_path etc. anpassen

Dateien:

  • Excel-Datei mkgloss.xls anlegen. Ausgewertet werden nur die zwei Spalten dt (wie in html: definition term) und dd (definition definition), alle anderen werden ignoriert und können anders verwendet werden.

  • Freeplane Mindmap mkgloss.mm anlegen. Ausgewertet werden alle Nodes der Art:

Begriff
   DEF
      Definition 1
      noch eine Definition
verbose = 1
gloss_xls_path = "./mkgloss.xls"
gloss_mm_path = "./mkgloss.mm"
gloss_output_path = "./mkgloss_glossar.txt"
# gloss_dict = { "definition term" : [ "Definition eins", "Definition zwei", ...] }
gloss_dict = {}

Excel einlesen#

Quelle: Eine Excel-Tabelle mit den Spalten dt und dd.

import pandas as pd
import os
#!pip install xlrd

if os.path.exists(gloss_xls_path):

    # Wir lesen Excel als pandas dataframe ein
    gloss_df = pd.read_excel(gloss_xls_path)
    
    # und erzeugen daraus ein dict,
    # siehe https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_dict.html 
    gloss_dictdict = gloss_df.to_dict(orient='index')


    for row in gloss_dictdict.values():
        dt = row["dt"]
        dd = row["dd"]
        if dt not in gloss_dict:
            # intitialisiere key mit einer Liste von Defs, hier mit Def 1
            gloss_dict[dt] = [ dd ]
        else:
            # dt ist als key schon da: erweitere Liste von Defs
            gloss_dict[dt].append(dd)
    if verbose >= 1 :
        print(f"mkgloss: read {len(gloss_df['dd'])} dd from {gloss_mm_path}")
mkgloss: read 5 dd from ./mkgloss.mm
# gloss_dict

Mindmap einlesen#

Quelle: Eine freemind- oder freeplane-Mindmap, mit Teilästen der Struktur

...
    Term
        DEF
            Definition 1
            Definition 2
def get_text_from_mm_node(current):
    """returns a mindmap node's text"""
    # nachschauen: ist current ein rich content Knoten mit html text?
    rich_content = current.find('richcontent[@TYPE="NODE"]')
    if rich_content is not None:
        # html Knoteninhalt als Markdown zurückliefern
        return markdownify(etree.tostring(rich_content, encoding="utf8"), heading_style="ATX")
    else:
        # Knoten ist Plaintext im Attribut @TEXT
       return current.get("TEXT")
# das standard etree hat eine unvollständige xpath Implementierung,
# besser ist <https://lxml.de/>
from lxml import etree

# https://pypi.org/project/markdownify/
# pip install markdownify
from markdownify import markdownify
if os.path.exists(gloss_mm_path):
    tree = etree.parse(gloss_mm_path)
    dd_nodes = tree.xpath('//node[@TEXT="DEF"]/node')
    
    for node in dd_nodes:
        dt = get_text_from_mm_node(node.getparent().getparent())
        dd = get_text_from_mm_node(node)
        if dt not in gloss_dict:
            gloss_dict[dt] = [ dd ]
        else:
            gloss_dict[dt].append(dd)
    if verbose >= 1 :
        print(f"mkgloss: read {len(dd_nodes)} dd from {gloss_mm_path}")
mkgloss: read 5 dd from ./mkgloss.mm
# gloss_dict

Glossar erzeugen#

sorted_gloss_dict = dict(sorted(gloss_dict.items(), key = lambda x: x[0].lower()))
if verbose >=1 :
    print(sorted_gloss_dict)
{'abc': ['Die Katze lief im Schnee', 'Das ABC', 'Das Alphabet ist ein nettes Tier', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'], 'c': [''], 'Explanation': ['Ausführliche, didaktisierte Erklärung'], 'HowTo': ['kurze, zielorientierte Anleitung'], 'pi': ['3.1415'], 'Reference': ['Lexikon, auch API'], 'Tutorial': ['Anleitung, wie man etwas lernen kann']}
# erste Zeile unseres Glossary
gloss_md_list = [ "```{glossary}" ]

for k, v in sorted_gloss_dict.items():
    v_string = "\n\n   ".join(v)
    gloss_entry = "\n" + k + "\n   " + v_string
    gloss_md_list.append(gloss_entry)
    
# letzte Zeile unseres Glossary
gloss_md_list.append("\n```\n")
gloss =  "\n".join(gloss_md_list)
if verbose >=2 :
    print(gloss)
# sorted_gloss_dict
with open(gloss_output_path, "w") as gloss_output:
    gloss_output.write(gloss)
    if verbose >= 1:
        print(f"mkgloss: wrote {len(sorted_gloss_dict)} dt to {gloss_output_path}")
mkgloss: wrote 7 dt to ./mkgloss_glossar.txt