#!/usr/bin/python3 from glob import glob from lxml import etree import re from copy import deepcopy class MassageLink(etree.XSLTExtension): def execute(self, context, self_node, input_node, output_parent): link = etree.Element("a") ref = input_node.attrib["ref"] term = re.match("^[^#. ]+", ref).group(0) if input_node.text == "ce mot": link.text = term.lower() else: link.text = input_node.text.lower() link.attrib["style"] = "font-variant: small-caps" link.attrib["href"] = f"q://d?&{term.upper()}" output_parent.append(link) xslt_entree = etree.XSLT(etree.parse("XMLittre-entree.xslt"), extensions={("xmlittre", "massagelink"): MassageLink()}) class Parser: def __init__(self): self.entrees = {} def parse_file(self, fname): fxml = etree.parse(fname) root = fxml.getroot() for entree in root.getchildren(): assert entree.tag == "entree" terme = entree.attrib["terme"] termes, sous_titre = massage_terme(terme) entree_html = xslt_entree(entree) entree_text = str(entree_html) # entree_text = entree_text.replace("\n", "") entree_text = re.sub(r"\s+|\n", " ", entree_text) assert entree_text.startswith("
") and entree_text.endswith("
") entree_text = entree_text[5:] entree_text = entree_text[:-6] if termes not in self.entrees: self.entrees[termes] = [] self.entrees[termes].append((sous_titre, entree_text)) def writeout(self, fname): with open(fname, "w") as f: for termes in self.entrees: f.write(", ".join(termes)) f.write("\t") if len(self.entrees[termes]) > 1: for i, (sous_titre, entree) in enumerate(self.entrees[termes]): if sous_titre: f.write(f"

{i+1}. {sous_titre}

") else: f.write(f"

{i+1}. {','.join(termes)}

") f.write(entree) else: sous_titre, entree = self.entrees[termes][0] if sous_titre: f.write(f"

{sous_titre}

") f.write(entree) f.write("\n") def massage_terme(terme): vedettes = re.split(r"[ ,](?:[A-Z]?[a-zéêèàç-]+[ ,']*)+", terme) vedettes = list(filter(None, vedettes)) sous_terme = None if len(vedettes) > 1: sous_terme = terme retval = [] for v in vedettes: m = re.match(r"^(.*) \((.*)\)$", v) if m: if m.group(2)[-1] == "'": space = "" else: space = " " v = f"{m.group(2)}{space}{m.group(1)}" if sous_terme: sous_terme = sous_terme.replace(m.group(0), v) formes = v.split(",") if len(formes) > 1: v = formes[0] sous_terme = terme retval.append(v) return (tuple(retval), sous_terme) def test_massage_terme(): assert massage_terme("ÉTANCHE") == (("ÉTANCHE",), None) assert massage_terme("ÉREINTÉ, ÉE") == (("ÉREINTÉ",), "ÉREINTÉ, ÉE") assert massage_terme("CLÉ ou CLEF") == (("CLÉ", "CLEF"), "CLÉ ou CLEF") assert massage_terme("HÉMORRAGIE, suivant le dictionnaire de l'Académie, mais mieux HÉMORRHAGIE") == \ (("HÉMORRAGIE", "HÉMORRHAGIE"), "HÉMORRAGIE, suivant le dictionnaire de l'Académie, mais mieux HÉMORRHAGIE") assert massage_terme("QUINDÉCEMVIRS ou mieux QUINDÉCIMVIRS puisque le latin est quindecimviri") \ == (("QUINDÉCEMVIRS", "QUINDÉCIMVIRS"), "QUINDÉCEMVIRS ou mieux QUINDÉCIMVIRS puisque le latin est quindecimviri") assert massage_terme("DÉVOUEMENT, ou comme quelques-uns écrivent, dit l'Académie, DÉVOÛMENT") == (("DÉVOUEMENT", "DÉVOÛMENT"), "DÉVOUEMENT, ou comme quelques-uns écrivent, dit l'Académie, DÉVOÛMENT") assert massage_terme("HÉMA- ou HÉMO- ou HÉMATO-") == (("HÉMA-", "HÉMO-", "HÉMATO-"), "HÉMA- ou HÉMO- ou HÉMATO-") assert massage_terme("DIVINIS (A)") == (("A DIVINIS",), None) assert massage_terme("BORDEAUX (VIN DE) ou vulgairement et en termes de commerce BORDEAUX") == \ (("VIN DE BORDEAUX", "BORDEAUX"), "VIN DE BORDEAUX ou vulgairement et en termes de commerce BORDEAUX") def main(): p = Parser() for fname in sorted(glob("../xmlittre-data/?.xml")): print(f"Running on {fname}") p.parse_file(fname) p.writeout("XMLittre.tab_separated") if __name__ == "__main__": main()