Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 25/05/2017, à 17:34

albenic

[Résolu] Python problème avec le symbole & et lxml

Bonjour,

je tourne en rond en cherchant la solution à mon problème. Je me décide à vous le soumettre.

Voici mon code :

# -*- coding: utf-8 -*-

from lxml import etree

test = open("test.xfdf", "w")
fields = etree.Element("fields")
field = etree.SubElement(fields, "field")
field.set("name", "Nom")
value = etree.SubElement(field, "value")
value.text = "Toto"
field = etree.SubElement(fields, "field")
field.set("name", "établissement")
value = etree.SubElement(field, "value")
value.text = "lycée"
field = etree.SubElement(fields, "field")
field.set("name", "série")
value = etree.SubElement(field, "value")
value.text = "ES"
test.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
test.write("<xfdf xml:space=\"preserve\">\n")
test.write(str(object=etree.tostring(fields, pretty_print=True,encoding='unicode')))
test.write("</xfdf>")
test.close()

Le rendu est presque parfait sauf pour le symbole & de "&#233;tablissement" et "s&#233;rie". J'aimerais obtenir exactement le texte entre guillemets mais malheureusement comme vous pourrez le constatez, j'obtiens respectivement "&amp;#233;tablissement" et "s&amp;#233;rie".

Si l'un d'entre vous peut me dépanner sur ce problème de débutant, je lui en serai gré.

Par avance merci, Benoît.

PS : comme je débute sous python, mon code est certainement perfectible, ne pas hésiter à me le signaler.

Dernière modification par albenic (Le 29/05/2017, à 09:16)

Hors ligne

#2 Le 25/05/2017, à 20:02

αjet

Re : [Résolu] Python problème avec le symbole & et lxml

Petite suggestion (pas testée). Essaie de mettre la chaîne de caractères directement en unicode:

field.set("name", u'établissement')

Un conseil, je te recommande de lire la section sérialisation de cet article: http://lxml.de/tutorial.html#the-element-class

Dernière modification par αjet (Le 25/05/2017, à 20:03)


αjet: ça se prononce alfajet, bordel ! | GMT+1 | Viens poueter avec moi, bordel ! | Mes photos | Shaarli | Fluidbuntu-fr

Hors ligne

#3 Le 26/05/2017, à 13:22

albenic

Re : [Résolu] Python problème avec le symbole & et lxml

Bonjour,

merci pour votre aide. J'avais croiser cette astuce sur les nombreux sites que j'ai consulté malheureusement cela ne fonctionne pas.

En fait, je commence à percevoir la nature du problème. En effet, ouvert avec gedit mon fichier n'est pas correct : "s&amp;#233;rie" en lieu et place de "s&#233;rie". En revanche, ouvert avec un navigateur, il n'y a aucun souci, le fichier est correctement interprété et à l'affichage j'ai le rendu souhaité.

La solution serait donc de pouvoir indiquer à lxml de traiter la chaîne de caractères "s&#233;rie" sans l'interpréter et la transformer ie ne pas transformer & en &amp;

Cela doit bien être possible mais je n'ai pas encore trouvé le moyen de le faire.

Merci pour votre aide, Benoît.

Hors ligne

#4 Le 26/05/2017, à 19:08

grigouille

Re : [Résolu] Python problème avec le symbole & et lxml

Et tout simplement :

field.set("name", "établissement")
field.set("name", "série")

Dernière modification par grigouille (Le 26/05/2017, à 19:09)


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#5 Le 27/05/2017, à 09:39

albenic

Re : [Résolu] Python problème avec le symbole & et lxml

Bonjour,

merci de vous intéresser à mon problème. J'ai eu un moment de doute horrible car je n'avais même pas songé à faire ce test.

Ouf, l'honneur est sauf, cela ne fonctionne pas !

J'ai contourné la difficulté pour des problèmes de temps avec la fonction :

replace("&amp;", "&")

Décemment, je ne peux pas mettre le sujet en résolu car cette solution fonctionne dans mon cas particulier mais dans une autre situation elle pourrait s'avérer inefficace.

Benoît.

Hors ligne

#6 Le 27/05/2017, à 09:48

grigouille

Re : [Résolu] Python problème avec le symbole & et lxml

Cela fonctionne parfaitement :

$ cat toto.py
# -*- coding: utf-8 -*-

from lxml import etree

test = open("test.xfdf", "w")
fields = etree.Element("fields")
field = etree.SubElement(fields, "field")
field.set("name", "Nom")
value = etree.SubElement(field, "value")
value.text = "Toto"
field = etree.SubElement(fields, "field")
field.set("name", "établissement")
value = etree.SubElement(field, "value")
value.text = "lycée"
field = etree.SubElement(fields, "field")
field.set("name", "série")
value = etree.SubElement(field, "value")
value.text = "ES"
test.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
test.write("<xfdf xml:space=\"preserve\">\n")
test.write(str(object=etree.tostring(fields, pretty_print=True,encoding='unicode')))
test.write("</xfdf>")
test.close()
$ python3 toto.py
$ cat test.xfdf 
<?xml version="1.0" encoding="UTF-8"?>
<xfdf xml:space="preserve">
<fields>
  <field name="Nom">
    <value>Toto</value>
  </field>
  <field name="établissement">
    <value>lycée</value>
  </field>
  <field name="série">
    <value>ES</value>
  </field>
</fields>
$ 

Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#7 Le 27/05/2017, à 16:55

albenic

Re : [Résolu] Python problème avec le symbole & et lxml

Je crains qu'il n'y ait une incompréhension.

Je ne veux pas obtenir "établissement" mais "&#233;tablissement".

Or avec "établissement" j'obtiens "établissement" ce qui est normal et rassurant mais ce n'est pas ce que je souhaite.

Avec "&#233;tablissement", j'obtiens  "&amp;#233;tablissement". Le problème est là.

Quoi qu'il en soit merci du temps consacré à mon problème.

Hors ligne

#8 Le 27/05/2017, à 18:41

αjet

Re : [Résolu] Python problème avec le symbole & et lxml

Je ne comprends pas très bien ton problème albenic.

Si tu géneres un XML en Unicode, le caractère économique est tout à fait valide.
Je me trompe peut-être mais j'ai l'impression que lxml prenne en charge les contraintes d'encodage en fonction de celui que tu specifies pour la serialisation. Ainsi si tu lui passe la chaîne &#233; il ne le prendra pas comme une entité html mais comme une suite de caractères à parser afin de générer un code XML valide.


αjet: ça se prononce alfajet, bordel ! | GMT+1 | Viens poueter avec moi, bordel ! | Mes photos | Shaarli | Fluidbuntu-fr

Hors ligne

#9 Le 27/05/2017, à 18:47

αjet

Re : [Résolu] Python problème avec le symbole & et lxml

Tu devrais essayer cette option
resolve_entities=False

Source http://lxml.de/FAQ.html


αjet: ça se prononce alfajet, bordel ! | GMT+1 | Viens poueter avec moi, bordel ! | Mes photos | Shaarli | Fluidbuntu-fr

Hors ligne

#10 Le 27/05/2017, à 19:34

albenic

Re : [Résolu] Python problème avec le symbole & et lxml

Je partage votre avis.

Il se trouve que j'ai un pdf avec un formulaire et une base de données sous la forme d'un fichier csv avec 300 lignes. L'idée de faire une saisie manuelle ne m'enchantait guère.

D'où mon idée de consulter les champs du fichier pdf, d'utiliser un fichier xfdf pour remplir le formulaire pdf en utilisant pdftk et d'automatiser l'ensemble avec python comme indiqué à cette adresse :

https://doc.ubuntu-fr.org/pdftk#gestion_des_formulaires

Il se trouve que le fichier fourni n'est pas d'une qualité exemplaire (certainement fait sous windows, sans vouloir critiquer) et que les champs ont des noms singuliers certainement la conséquence d'un problème d'encodage sous windows. Mais il faut bien que je fasse avec ce fichu formulaire pdf. Ce qui explique mes acrobaties pour obtenir le libellé exact des champs du formulaire pdf.

Je comprends parfaitement le comportement de lxml qui est tout à fait conforme à ce qu'il devrait faire saut que dans mon cas il me faut obtenir un champ avec le libellé  "&#233;tablissement" et pas "établissement" ni même  "&amp;#233;tablissement".

Mon idée d'utiliser lxml était uniquement de me simplifier l'écriture du fichier xfdf qui est à la base un fichier xml.

Cette fois-ci vous savez tout.

Une nouvelle fois merci pour votre aide.

Hors ligne

#11 Le 27/05/2017, à 19:58

αjet

Re : [Résolu] Python problème avec le symbole & et lxml

Avez-vous essayé l'option que j'ai posté précédemment (post #9)?
J'aimerais tester par moi même mais je n'ai que mon téléphone sous la main en ce moment.

Sinon si ça ne marche pas. Il reste l'option de remplacer globalement l'entité &amp en trop.


αjet: ça se prononce alfajet, bordel ! | GMT+1 | Viens poueter avec moi, bordel ! | Mes photos | Shaarli | Fluidbuntu-fr

Hors ligne

#12 Le 27/05/2017, à 20:30

eiger

Re : [Résolu] Python problème avec le symbole & et lxml

A priori, avec la variante suivante, on obtient ce que tu veux (chaînes unicode passées à lxml, et appel à etree.tostring modifié) :

test = open("test.xfdf", "w")
fields = etree.Element("fields")
field = etree.SubElement(fields, "field")
field.set("name", "Nom")
value = etree.SubElement(field, "value")
value.text = "Toto"
field = etree.SubElement(fields, "field")
field.set("name", u"établissement")
value = etree.SubElement(field, "value")
value.text = u"lycée"
field = etree.SubElement(fields, "field")
field.set("name", u"série")
value = etree.SubElement(field, "value")
value.text = "ES"
test.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
test.write("<xfdf xml:space=\"preserve\">\n")
test.write(etree.tostring(fields, pretty_print=True,encoding='ascii').decode('ascii'))
test.write("</xfdf>")
test.close()

Note: en Python 3, les chaînes sont par défaut en unicode, donc on peut se contenter de "lycée" au lieu de u"lycée".

Ce n'est pas très propre, étant donné que l'en-tête annonce un encodage UTF-8, mais qu'on évite tous les caractères non-ASCII.

Le comportement de lxml est plutôt normal : il cherche à eviter de produire un document XML non valide. Le caractère '&' a une signification particulière en XML (il marque le début d'une entité) et doit obligatoirement être "échappé" s'il apparait dans les données. Donc lxml procède au remplacement systématique de '&' dans les données utilisateur par l'entité XML correspondante '&amp;'.

En fait, tu cherches à produire un document encodé en ASCII, pas en UTF-8, donc il faut passer les options correspondantes à etree.tostring.

Dernière modification par eiger (Le 27/05/2017, à 20:31)

Hors ligne

#13 Le 27/05/2017, à 21:21

albenic

Re : [Résolu] Python problème avec le symbole & et lxml

Vous m'aviez convaincu et fondamentalement, je pense que vous avez raison malheureusement, le code proposé n'a pas fonctionné.

Hors ligne

#14 Le 27/05/2017, à 21:32

eiger

Re : [Résolu] Python problème avec le symbole & et lxml

albenic a écrit :

Vous m'aviez convaincu et fondamentalement, je pense que vous avez raison malheureusement, le code proposé n'a pas fonctionné.

Concrètement, qu'est-ce que tu obtiens ? Des erreurs à l'exécution ? Un fichier qui ne correspond pas à ce que tu veux ?

Hors ligne

#15 Le 28/05/2017, à 07:56

albenic

Re : [Résolu] Python problème avec le symbole & et lxml

Je vous remercie du temps consacré à solutionner mon problème. Comme indiqué lors d'un précédent message, j'ai trouvé une solution non satisfaisante pour un puriste mais qui m'a permis de réaliser ce que je devais faire via l'utilisation de la fonction

replace("&amp;","&")

Pour répondre à votre question, voici ce que j'obtiens :

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xml:space="preserve">
<fields>
  <field name="Nom">
    <value>Toto</value>
  </field>
  <field name="&amp;#233;tablissement">
    <value>lyc&#233;e</value>
  </field>
  <field name="s&amp;#233;rie">
    <value>ES</value>
  </field>
</fields>
</xfdf>

Hors ligne

#16 Le 28/05/2017, à 10:07

αjet

Re : [Résolu] Python problème avec le symbole & et lxml

L'essentiel c'est que ça fonctionne. wink
J'aurais été curieux de voir si l'option proposée en #9 permettait de bypasser l'interprétation des chaînes de caractères par lxml.

Sinon ce que j'ai toujours du mal à comprendre est que dans la mesure où vous spécifiez bien l'encodage utf-8 votre fichier XML reste valide avec des caractères accentués. Est-ce pdftk qui n'interprete pas correctement le fichier dans ce cas ?


αjet: ça se prononce alfajet, bordel ! | GMT+1 | Viens poueter avec moi, bordel ! | Mes photos | Shaarli | Fluidbuntu-fr

Hors ligne

#17 Le 28/05/2017, à 11:45

albenic

Re : [Résolu] Python problème avec le symbole & et lxml

Je peux répondre à la dernière question : pdftk ignore les champs non reconnus et le pdf obtenu est "à trous".

J'ai également essayé l'option suggérée au #9 mais l'esperluette a toujours été interprétée en &amp;

Hors ligne

#18 Le 28/05/2017, à 17:26

eiger

Re : [Résolu] Python problème avec le symbole & et lxml

Es-tu certain d'avoir recopié tel quel la portion de code que j'ai suggéré en #12 ? Si tu obtiens

<field name="s&amp;#233;rie"> 

c'est que tu as injecté le caractère '&' dans tes données, probablement avec

field.set("name", "s&#233;rie")

Voici ce que j'obtiens :

test> cat xml.py
# -*- coding: utf-8 -*-

from lxml import etree

test = open("test.xfdf", "w")
fields = etree.Element("fields")
field = etree.SubElement(fields, "field")
field.set("name", "Nom")
value = etree.SubElement(field, "value")
value.text = "Toto"
field = etree.SubElement(fields, "field")
field.set("name", u"établissement")
value = etree.SubElement(field, "value")
value.text = u"lycée"
field = etree.SubElement(fields, "field")
field.set("name", u"série")
value = etree.SubElement(field, "value")
value.text = "ES"
test.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
test.write("<xfdf xml:space=\"preserve\">\n")
test.write(etree.tostring(fields, pretty_print=True,encoding='ascii').decode('ascii'))
test.write("</xfdf>")
test.close()

 test> python xml.py
 test> cat test.xfdf 
<?xml version="1.0" encoding="UTF-8"?>
<xfdf xml:space="preserve">
<fields>
  <field name="Nom">
    <value>Toto</value>
  </field>
  <field name="&#233;tablissement">
    <value>lyc&#233;e</value>
  </field>
  <field name="s&#233;rie">
    <value>ES</value>
  </field>
</fields>
</xfdf>

Hors ligne

#19 Le 29/05/2017, à 09:10

albenic

Re : [Résolu] Python problème avec le symbole & et lxml

Effectivement, tu m'as démasqué. J'ai parcouru en diagonale ta solution. Avec un copier-coller intégral de ton code, cela fonctionne parfaitement.

Sincères félicitations et un grand merci. Je n'aurais jamais pensé à cela.

Cela me servira pour une prochaine occasion mais il me reste encore à me pencher sérieusement sur ces problèmes d'encodage des caractères et à bien comprendre la solution que tu as trouvée.

Bonne journée, Benoît.

Hors ligne