2 votes

Analyse syntaxique de XML : Équations mathématiques - Exemple SVG

Je voudrais repérer les positions et les tailles de police de chacun des symboles utilisés dans un SVG d'une équation mathématique.

Je joue avec la bibliothèque d'analyse XML de Python : xml.etree.ElementTree ( https://docs.python.org/3/library/xml.etree.elementtree.html ).

Voici l'exemple de SVG que j'utilise :

example_svg = '''<svg style="vertical-align:-10.2252022445128pt" xmlns="http://www.w3.org/2000/svg" width="193pt" height="31pt" viewBox="-1 -1 193 31">
<path d="M43.875 16.305h20.426" fill="none" stroke-width=".914" stroke="#000" stroke-miterlimit="10"></path>
<g font-family="MathFont" font-size="13.5">
<text y="11.168" x="45.874">3</text>
<text y="11.168" x="52.532"></text> 
<text y="28.382" x="50.758">4</text>
</g>
<g font-family="MathFont" font-size="9.45">
<text y="6.327" x="60.453">3</text></g>
</svg>'''    

En Latex, l'équation est $ \frac {3x^3}{4}$.

L'utilisation du code suivant me donne presque tout ce que je veux, mais je ne parviens pas à le relier aux attributs du texte du groupe. Idéalement, je voudrais que la sortie soit (symbole, coordonnée_y, coordonnée_x, famille de caractères, taille de caractères).

import xml.etree.ElementTree as ET

root = ET.fromstring(example_svg)

for tag in root.findall('.//{http://www.w3.org/2000/svg}text'):
  symbol = tag.text
  y_coord = tag.get('y')
  x_coord = tag.get('x')
  print(symbol, y_coord, x_coord)

1voto

Jongware Points 6943

Le nom et la taille de la famille de polices ne sont pas spécifiés dans le document <text> mais dans leurs éléments parents <g> groupes. Une certaine prudence est nécessaire, car de multiples <g> peuvent apparaître imbriqués les uns dans les autres.

Vous pouvez localiser tous les <g> éléments avec find_all et stocker temporairement les paramètres de la police, mais si vous essayez de le faire pour trouver d'abord <g> et ensuite son <text> vous remarquerez rapidement qu'il ne peut pas gérer correctement les groupes imbriqués. Chaque occurrence de <g> se déclenchera à la recherche de son contenu <text> et donc s'il existe un ensemble d'éléments imbriqués

<g _group parameters_> <g _text parameters_> <text>_your text_</text> </g> </g>

alors il signalera tous les <text> éléments deux fois : une fois pour chaque (imbriqué ou non) <g> .

Il est donc préférable d'itérer sur l'ensemble du fichier XML et de stocker les informations relatives à la police au fur et à mesure que vous les rencontrez.

root = ET.fromstring(example_svg)

font = None
font_size = None
for elem in root.iter():
    if elem.tag == '{http://www.w3.org/2000/svg}g':
        item = elem.get('font-family')
        if item is not None:
            font = item
        item = elem.get('font-size')
        if item is not None:
            font_size = item

    elif elem.tag == '{http://www.w3.org/2000/svg}text':
        symbol = elem.text
        y_coord = elem.get('y')
        x_coord = elem.get('x')
        print (symbol, y_coord, x_coord, font, font_size)

(Notez que iter() a besoin de l'espace de nom SVG complet préplié à chaque élément).

Résultat :

3 11.168 45.874 MathFont 13.5
 11.168 52.532 MathFont 13.5
4 28.382 50.758 MathFont 13.5
3 6.327 60.453 MathFont 9.45

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X