Показаны сообщения с ярлыком XML. Показать все сообщения
Показаны сообщения с ярлыком XML. Показать все сообщения

4 февр. 2009 г.

Нетекстовые символы в XML и HTML

Большнство разработчиков знают, что некоторые специальные символы в XML и HTML необходимо записывать в виде entity или character reference. Но мало кто подозревает, что XML (а также SGML, на котором базируется HTML) документы могут содержать только "текстовые" символы. Привычные питоновские библиотеки также обходят это требование стороной. Средства конструирования XML, которые, казалось бы, должны полностью защищать нас от создания "битых" документов, справляются со своей задачей лишь частично. В результате вполне возможна ситуация, когда библиотека ругается на созданный с её же помощью документ. Вот пример с использованием ElementTree:
>>> from xml.etree import ElementTree
>>> element = ElementTree.Element('element')
>>> element.text = u'\0'
>>> xml = ElementTree.tostring(element, encoding='utf-8')
>>> ElementTree.fromstring(xml)
[...]
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 9
И то же самое с minidom:
>>> from xml.dom import minidom
>>> doc = minidom.getDOMImplementation().createDocument(None, None, None)
>>> element = doc.createElement('element')
>>> element.appendChild(doc.createTextNode(u'\0'))
<DOM Text node "">
>>> doc.appendChild(element)
<DOM Element: element at 0xb7ca688c>
>>> xml = doc.toxml(encoding='utf-8')
>>> minidom.parseString(xml)
[...]
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 47
На мой взгляд, в описанной ситуации библиотека должна давать исключение ещё на стадии конструирования. Но даже если так и будет в будущих версиях, в реальной жизни это не решит проблему конкретного приложения, а лишь облегчит диагностику. Для web-приложений основной источник получения потенциально плохих данных — через форму. И было бы правильно проверять или очищать данные на стадии получения их от пользователя. Однако и здесь всё плохо: из всех известных мне библиотек для обработки и валидации форм только одна (весьма древняя и малоизвестная) решает проблему нетекстовых символов, хотя большинство вполне корректно работают с "битыми" кодировками.

28 янв. 2009 г.

Задачка для собеседования

Была у меня в своё время любимая задачка для собеседования. Есть веб-страничка принимающая данные от посетителей сайта:
import cgi

form = cgi.FieldStorage()
message = form.getfirst('message', '')
attr = form.getfirst('attr', '')

result = '''<?xml version='1.0'?>
<message attr='%s'>%s</message>''' % (attr, message)
Далее данные отправляются, например, стороннему сервису. Так вот периодически этот сервис нам возвращает ошибку "not well-formed". И предлагаю найти и исправить ошибки. При этом я сразу оговариваю, что задача не столько на знание XML, сколько на умение решать проблемы, возникающие в ходе разработки. Кроме того, я делаю акцент на том, что пользователь может ввести произвольные данные.
Большинство соискателей сходу называют одну ошибку (представление спец-символов) и относительно быстро находят вторую (связанная с кодировкой). А вот третья проблема всегда остаётся незамеченной и "обходит" все предложенные тесты. Кроме того, большинство современных средств построения XML (например, ElementTree) молча пропускают такие ошибки. Как вариант, я предлагаю выбрать первый пришедший в голову blog-движок (как правило, это byteflow на django) с трансляцией RSS или Atom и написать тест, показывающий, что любой комментатор может "сломать" (весьма условно, учитывая что большиство современных читалок умеют переваривать и битый XML) feed комментариев. В короткий срок и без большого количества наводящих подсказок с этой задачей смог справиться только Олег Бройтман. Типичное время решения с подсказками — более суток.