Подтвердить что ты не робот

ParseError: неверно сформированный (недопустимый токен) с использованием cElementTree

Я получаю строки xml из внешнего источника, который может содержать несаминированный пользовательский контент.

Следующая строка xml дала ParseError в cElementTree:

>>> print repr(s)
'<Comment>dddddddd\x08\x08\x08\x08\x08\x08_____</Comment>'
>>> import xml.etree.cElementTree as ET
>>> ET.XML(s)

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    ET.XML(s)
  File "<string>", line 106, in XML
ParseError: not well-formed (invalid token): line 1, column 17

Есть ли способ заставить cElementTree не жаловаться?

4b9b3361

Ответ 1

Кажется, вы жалуетесь на \x08, вам нужно будет избежать этого.

Изменить:

Или вы можете заставить анализатор игнорировать ошибки, используя recover

from lxml import etree
parser = etree.XMLParser(recover=True)
etree.fromstring(xmlstring, parser=parser)

Ответ 2

У меня была такая же ошибка (с ElementTree). В моем случае это было из-за кодировок, и я смог его решить, не используя внешнюю библиотеку. Надеюсь, это поможет другим людям найти этот вопрос на основе названия. (ссылка)

import xml.etree.ElementTree as ET
parser = ET.XMLParser(encoding="utf-8")
tree = ET.fromstring(xmlstring, parser=parser)

EDIT. На основе комментариев этот ответ может быть устаревшим. Но это сработало, когда было получено ответ...

Ответ 3

Смотрите этот ответ на другой вопрос и в соответствии с частью XML спецификации.

Backspace U+0008 является недопустимым символом в документах XML. Он должен быть представлен как скрытый объект &#8; и не может отображаться явно.

Если вам нужно обработать этот фрагмент XML, вы должны заменить \x08 на s перед его загрузкой в ​​XML-парсер.

Ответ 4

Я столкнулся с подобной проблемой. Наконец выяснилось, что было основной причиной в моем конкретном случае. Если вы прочитаете данные из нескольких файлов XML, которые находятся в одной папке, вы также проанализируете файл .DS_Store. Перед синтаксическим разбором добавьте это условие

for file in files:
    if file.endswith('.xml'):
       run_your_code...

Этот трюк также помог мне

Ответ 5

Решение для gottcha для меня, используя Python ElementTree... у этого есть недопустимая ошибка токена:

# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET

xml = u"""<?xml version='1.0' encoding='utf8'?>
<osm generator="pycrocosm server" version="0.6"><changeset created_at="2017-09-06T19:26:50.302136+00:00" id="273" max_lat="0.0" max_lon="0.0" min_lat="0.0" min_lon="0.0" open="true" uid="345" user="john"><tag k="test" v="Съешь же ещё этих мягких французских булок да выпей чаю" /><tag k="foo" v="bar" /><discussion><comment data="2015-01-01T18:56:48Z" uid="1841" user="metaodi"><text>Did you verify those street names?</text></comment></discussion></changeset></osm>"""

xmltest = ET.fromstring(xml.encode("utf-8"))

Однако он работает с добавлением дефиса в типе кодирования:

<?xml version='1.0' encoding='utf-8'?>

Самое странное. Кто-то нашел эту сноску в python docs:

Строка кодирования, включенная в выход XML, должна соответствовать соответствующие стандарты. Например, "UTF-8" действителен, но "UTF8" нет.

Ответ 6

Это скорее всего ошибка кодирования. Например, у меня был xml файл, закодированный в UTF-8-BOM (отмеченный в меню Notepad ++ Encoding) и получил подобное сообщение об ошибке.

Обходной путь (Python 3.6)

import io
from xml.etree import ElementTree as ET

with io.open(file, 'r', encoding='utf-8-sig') as f:
    contents = f.read()
    tree = ET.fromstring(contents)

Проверьте кодировку вашего XML файла. Если он использует различную кодировку, измените "utf-8-sig" соответственно.

Ответ 7

Ни одно из перечисленных исправлений не помогло мне. Единственное, что сработало, было использовать BeautifulSoup вместо ElementTree следующим образом:

from bs4 import BeautifulSoup

with open("data/myfile.xml") as fp:
    soup = BeautifulSoup(fp, 'xml')

Затем вы можете искать дерево следующим образом:

soup.find_all('mytag')

Ответ 8

Что помогло мне с этой ошибкой, ответил Хуан - fooobar.com/questions/441065/... Но было недостаточно - после борьбы я узнал, что XML файл должен быть сохранен с UTF-8 без кодировки спецификации.

Решение не работает для "нормального" UTF-8.

Ответ 9

Единственное, что сработало для меня, - мне пришлось добавить режим и кодировку при открытии файла, как показано ниже:

with open(filenames[0], mode='r',encoding='utf-8') as f:
     readFile()

В противном случае он каждый раз заканчивался ошибкой с неверным токеном, если я просто делал это:

 f = open(filenames[0], 'r')
 readFile()

Ответ 10

Я попробовал другие решения в ответах здесь, но безуспешно. Поскольку мне нужно было только извлечь значение из одного узла xml, я дал ему и написал свою функцию для этого:

def ParseXmlTagContents(source, tag, tagContentsRegex):
    openTagString = "<"+tag+">"
    closeTagString = "</"+tag+">"
    found = re.search(openTagString + tagContentsRegex + closeTagString, source)
    if found:   
        start = found.regs[0][0]
        end = found.regs[0][1]
        return source[start+len(openTagString):end-len(closeTagString)]
    return ""

Пример использования:

<?xml version="1.0" encoding="utf-16"?>
<parentNode>
    <childNode>123</childNode>
</parentNode>

ParseXmlTagContents(xmlString, "childNode", "[0-9]+")