È risaputo che certain character ranges non è consentito nei documenti XML. Sono a conoscenza di soluzioni per filtrare questi caratteri (come [1], [2]).Modo centrale per filtrare i caratteri Unicode non validi in lxml?
Andando con il principio Non Repeat Yourself, preferirei di implementare una di queste soluzioni in un unico punto centrale - in questo momento, devo disinfettare qualsiasi testo potenzialmente non sicuro prima di essere inviato al lxml
. C'è un modo per raggiungere questo obiettivo, ad es. sottoclassando una classe di filtro lxml
, rilevando alcune eccezioni o impostando uno switch di configurazione?
Modifica: Per spera di chiarire la questione un po ', ecco un esempio di codice:
from lxml import etree
root = etree.Element("root")
root.text = u'\uffff'
root.text += u'\ud800'
print(etree.tostring(root))
root.text += '\x02'.decode("utf-8")
L'esecuzione di questo dà il risultato
<root>�</root>
Traceback (most recent call last):
File "[…]", line 9, in <module>
root.text += u'\u0002'
File "lxml.etree.pyx", line 953, in lxml.etree._Element.text.__set__ (src/lxml/lxml.etree.c:44956)
File "apihelpers.pxi", line 677, in lxml.etree._setNodeText (src/lxml/lxml.etree.c:20273)
File "apihelpers.pxi", line 1395, in lxml.etree._utf8 (src/lxml/lxml.etree.c:26485)
ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters
Come si vede, viene generata un'eccezione per il 2 byte, ma lxml sfugge felicemente agli altri due caratteri fuori intervallo. Il vero guaio è che
s = "<root>�</root>"
root = etree.fromstring(s)
tiri anche un'eccezione. Questo comportamento è un po 'snervante a mio parere, soprattutto perché produce documenti XML non validi.
scopre che questo potrebbe essere un 2 vs 3 problema. Con python3.4, il codice precedente genera l'eccezione
Traceback (most recent call last):
File "[…]", line 5, in <module>
root.text += u'\ud800'
File "lxml.etree.pyx", line 953, in lxml.etree._Element.text.__set__ (src/lxml/lxml.etree.c:44971)
File "apihelpers.pxi", line 677, in lxml.etree._setNodeText (src/lxml/lxml.etree.c:20273)
File "apihelpers.pxi", line 1387, in lxml.etree._utf8 (src/lxml/lxml.etree.c:26380)
UnicodeEncodeError: 'utf-8' codec can't encode character '\ud800' in position 1: surrogates not allowed
L'unico problema e 'il carattere \uffff
, che lxml
ancora accetta felicemente.
Forse questo dovrebbe essere risolto in lxml stesso. Hai inviato un bug al progetto lxml? – oefe
@oefe non l'ho fatto. Ma sembra che questo sia un problema di 'libxml' (per il quale lxml è solo un wrapper) dato che PHP' DOMDocument' (un altro wrapper) sfugge anche caratteri fuori dall'intervallo e ha problemi a caricare tali documenti in seguito, quindi forse un bug la relazione dovrebbe essere meglio compilata lì. –
come soluzione temporanea si potrebbe usare 'soupparser' che è fornito da lxml ' da lxml.html.soupparser import fromstring' e mangerà " & # 65535; & # 55296; " senza problemi. si basa sul parser di libxml2 –
Urban48