Gracieusement récupérer de l'erreur Parse dans expat
-
28-10-2019 - |
Question
XML est censé être stricte, et donc il y a des caractères Unicode qui ne sont pas autorisés en XML. Cependant, je suis en train de travailler avec les flux RSS qui contiennent souvent ces personnages de toute façon, et je voudrais éviter soit erreurs d'analyse de caractères non valides ou les récupérer gracieusement et présenter le document de toute façon.
Voir un exemple ici (le 21 Mars de toute façon): http://feeds.feedburner.com/chrisblattman
Quelle est la méthode recommandée pour gérer l'unicode dans le flux XML? Détecter les caractères et les remplacer en octets nuls, modifier l'analyseur, ou une autre méthode?
La solution
On dirait que flux RSS contient un caractère onglet vertical \x0c
qui est illégal par XML 1.0 spec .
Mon conseil est de filtrer les caractères illégaux avant de transmettre les données à expat, plutôt que de tenter d'erreurs de capture et de récupérer. Voici une routine pour filtrer les caractères Unicode qui sont illégales. Je l'ai testé sur votre chrisblattman.xml
flux RSS:
import re
from xml.parsers import expat
# illegal XML 1.0 character ranges
# See http://www.w3.org/TR/REC-xml/#charsets
XML_ILLEGALS = u'|'.join(u'[%s-%s]' % (s, e) for s, e in [
(u'\u0000', u'\u0008'), # null and C0 controls
(u'\u000B', u'\u000C'), # vertical tab and form feed
(u'\u000E', u'\u001F'), # shift out / shift in
(u'\u007F', u'\u009F'), # C1 controls
(u'\uD800', u'\uDFFF'), # High and Low surrogate areas
(u'\uFDD0', u'\uFDDF'), # not permitted for interchange
(u'\uFFFE', u'\uFFFF'), # byte order marks
])
RE_SANITIZE_XML = re.compile(XML_ILLEGALS, re.M | re.U)
# decode, filter illegals out, then encode back to utf-8
data = open('chrisblattman.xml', 'rb').read().decode('utf-8')
data = RE_SANITIZE_XML.sub('', data).encode('utf-8')
pr = expat.ParserCreate('utf-8')
pr.Parse(data)
Mise à jour : Voici un Wikipédia sur la validité de caractères XML . Mon expression rationnelle ci-dessus filtres sur la plage de réglage de C1, mais vous pouvez autoriser ces caractères en fonction de votre application.