Python ElementTree генерирует неверно сформированный XML файл со специальным символом '\ x0b' - PullRequest
4 голосов
/ 30 мая 2020

Я использовал ElementTree для генерации xml со специальным символом '\ x0b', а затем использовал minidom для его анализа. Выдает ошибку not well-formed.

import xml.etree.ElementTree as ET
from xml.dom import minidom
root = ET.Element('root')
root.text='\x0b'
xml = ET.tostring(root, 'UTF-8')
print(xml)
pretty_tree = minidom.parseString(xml)

Создано XML: <root>\x0b</root>

Ошибка :

Traceback (most recent call last):
  File "testXml.py", line 7, in <module>
    pretty_tree = minidom.parseString(xml)
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/xml/dom/minidom.py", line 1968, in parseString
    return expatbuilder.parseString(string)
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/xml/dom/expatbuilder.py", line 925, in parseString
    return builder.parseString(string)
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/xml/dom/expatbuilder.py", line 223, in parseString
    parser.Parse(string, True)
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 6

Ответы [ 3 ]

5 голосов
/ 30 мая 2020

Это поведение в прошлом называлось ошибкой и решалось как «не исправить».

Автор модуля ElementTree прокомментировал

Для ET [такое поведение] сделано намеренно. Проверка данных, предоставляемых каждым отдельным приложением, снизит производительность для всех из них, даже если лишь небольшое меньшинство когда-либо попытается сериализовать данные, которые не могут быть представлены в XML.

Закрытие комментарий (от сопровождающего l xml, который также является разработчиком ядра Python) включает следующие наблюдения:

Это непростое решение. l xml, например, проверяет вводимые пользователем данные, но это потому, что он все равно должен его обрабатывать и делает это по ходу непосредственно при вводе (и очень эффективно в коде C). ET, с другой стороны, довольно снисходительно относится к тому, что он позволяет пользователям делать, и не применяет много обработки к пользовательскому вводу. Он даже допускает недопустимые деревья во время обработки и ожидает, что дерево будет сериализовано только при запросе на сериализацию.

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

...

В конце концов, пользователи, которые действительно заботятся о правильном выводе, должны выполнить какую-то проверку схемы над ним после сериализации, поскольку это обнаружит не только проблемы с данными, но также структурные и логические проблемы ( например, отсутствующий или пустой атрибут), особенно для их целевого формата данных. В некоторых случаях он может даже обнаружить случайное повреждение данных из-за старой не-E CC RAM на сервере. :)

...

Таким образом, ET.tostring будет генерировать xml, который не является правильно сформированным, и это сделано намеренно. При необходимости вывод можно проанализировать, чтобы проверить правильность его формата, используя ET.fromstring или другой синтаксический анализатор. В качестве альтернативы вместо ElementTree можно использовать l xml.

1 голос
/ 30 мая 2020

В качестве обходного пути для себя я написал вспомогательный метод для очистки ограниченных символов перед сохранением в модель XML:

def clean(str):
  return re.sub(r'[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u10000-\u10FFF]+', '', str)
1 голос
/ 30 мая 2020

\x0b - это запрещенный символ XML. В ответах на этот вопрос .

есть хорошее описание допустимых и запрещенных символов.
...