<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:my="xmlittre"
+ extension-element-prefixes="my">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
- indent="yes" standalone="no" omit-xml-declaration="yes"/>
+ indent="no" standalone="no" omit-xml-declaration="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
</xsl:copy>
</xsl:template>
- <xsl:template match="entree">
+ <xsl:template match="entree"><div>
<xsl:for-each select="entete/nature | entete/indent | entete/cit | entete/a | entete/semantique">
<xsl:apply-templates select="."/>
</xsl:for-each>
<xsl:if test="entete/prononciation">
<p><b>PRONONCIATION</b></p>
- <div>
- <xsl:apply-templates select="entete/prononciation/node()" />
- </div>
+ <p><xsl:apply-templates select="entete/prononciation/node()" /></p>
</xsl:if>
- </xsl:template>
+ </div></xsl:template>
<xsl:template match="nature">
<i><xsl:value-of select="text()"/></i>
</xsl:template>
+
<xsl:template match="indent">
- <div style="padding-left: 1em"><xsl:apply-templates select="node()"/></div>
+ <div style="padding-left: 2em"><xsl:apply-templates select="node()"/></div>
</xsl:template>
<xsl:template match="corps|résumé" mode="plusieurs_variantes">
</xsl:template>
<xsl:template match="corps|résumé" mode="unique_variante">
- <div><xsl:apply-templates select="node()"/></div>
+ <div><xsl:apply-templates select="variante/node()"/></div>
</xsl:template>
<xsl:template match="cit">
<xsl:apply-templates select="node()"/>
</xsl:template>
+ <xsl:template match="a"><my:massagelink/></xsl:template>
+
</xsl:stylesheet>
from glob import glob
from lxml import etree
+import re
+from copy import deepcopy
-xslt_entree = etree.XSLT(etree.parse("XMLittre-entree.xslt"))
+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):
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", "")
- if terme not in self.entrees:
- self.entrees[terme] = []
- self.entrees[terme].append(entree_text)
+ # entree_text = entree_text.replace("\n", "")
+ entree_text = re.sub(r"\s+|\n", " ", entree_text)
+ assert entree_text.startswith("<div>") and entree_text.endswith("</div>")
+ 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 terme in self.entrees:
- f.write(terme)
+ for termes in self.entrees:
+ f.write(", ".join(termes))
f.write("\t")
- if len(self.entrees[terme]) > 1:
- f.write("<ol>")
- for entree in self.entrees[terme]:
- f.write("<li>")
+ if len(self.entrees[termes]) > 1:
+ for i, (sous_titre, entree) in enumerate(self.entrees[termes]):
+ if sous_titre:
+ f.write(f"<h2>{i+1}. {sous_titre}</h2>")
+ else:
+ f.write(f"<h2>{i+1}. {','.join(termes)}</h2>")
f.write(entree)
- f.write("</li>")
- f.write("</ol>")
else:
- f.write(self.entrees[terme][0])
+ sous_titre, entree = self.entrees[termes][0]
+ if sous_titre:
+ f.write(f"<h2>{sous_titre}</h2>")
+ 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 glob("../xmlittre-data/?.xml"):
+ for fname in sorted(glob("../xmlittre-data/?.xml")):
+ print(f"Running on {fname}")
p.parse_file(fname)
p.writeout("XMLittre.tab_separated")