#!/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()