Структура формата синдикации фида Atom

Рассмотрим блог (weblog) или любой сайт с часто обновляемым контентом, например CNN.com. Сайт содержит заголовок («CNN.com»), подзаголовок («Breaking News, U.S., World, Weather, Entertainment & Video News»), дату последнего изменения («обновлено 12:43 p.m. EDT, Sat May 16, 2009») и список статей опубликованных в разное время. Каждая статья в свою очередь также имеет заголовок, дату первой публикации (и, возможно, дату последнего обновления, в случае если статья была корректирована) и уникальный URL.

Формат синдикации Atom разработан с целью хранить информацию подобного рода стандартным образом. Мой блог и CNN.com абсолютно разные по дизайну, содержанию и посетителям сайты, но оба имеют сходную структуру. Оба сайта имеют заголовки и публикуют статьи.

На верхнем уровне фид Atom должен иметь корневой элемент по имени feed находящийся в пространстве имен http://www.w3.org/2005/Atom.

<feed xmlns='http://www.w3.org/2005/Atom' ① xml:lang='en'> ②

① http://www.w3.org/2005/Atom - пространство имён Atom

② Каждый элемент может содержать атрибут xml:lang который определяет язык элемента и его дочерних элементов. В данном случае атрибут xml:lang объявленный в корневом элементе задаёт английский язык для всего фида.

Фид Atom содержит дополнительную информацию о себе в дочерних элементах корневого элемента:

<feed xmlns='http://www.w3.org/2005/Atom' xml:lang='en'> <title>dive into mark</title> ① <subtitle>currently between addictions</subtitle> ② <id>tag:diveintomark.org,2001-07-29:/</id> ③ <updated>2009-03-27T21:56:07Z</updated> ④ <link rel='alternate' type='text/html' href='http://diveintomark.org/'/> ⑤

① Заголовок title содержит текст 'dive into mark'.

② Подзаголовок subtitle фида есть строка 'currently between addictions'.

③ Каждый фид должен иметь глобальный уникальный идентификатор. RFC 4151 содержит информацию как создавать такие идентификаторы.

④ Данный фид был обновлён последний раз 27 марта 2009 в 21:56 GMT. Обычно элемент updated эквивалентен дате последнего изменения какой-либо из статей на сайте.

⑤ А вот здесь начинается самое интересное. Элемент ссылки link не имеет текстового содержания, но имеет три атрибута: rel, type и href. Значение атрибута rel говорит о том какого типа ссылка. rel='alternate' значит, что это альтернативная ссылка этого фида. Атрибут type='text/html' говорит, что это ссылка на HTML страницу. И, собственно, путь ссылки содержится в атрибуте href.

Теперь мы знаем, что представленный выше фид получен с сайта «dive into mark». Сайт доступен по адресу http://diveintomark.org/ и последний раз был обновлён 27 марта 2009.

Хотя в некоторых XML документах порядок элементов может иметь значение, в фидах Atom порядок элементов - произвольный.

Продолжим дальше рассматривать строение фида: после метаинформации о фиде идёт список последних статей. Статья выглядит следующим образом:

<entry> <author> ① <name>Mark</name> <uri>http://diveintomark.org/</uri> </author> <title>Dive into history, 2009 edition</title> ② <link rel='alternate' type='text/html' ③ href='http://diveintomark.org/archives/2009/03/27/dive-into-history-2009-edition'/> <id>tag:diveintomark.org,2009-03-27:/archives/20090327172042</id> ④ <updated>2009-03-27T21:56:07Z</updated> ⑤ <published>2009-03-27T17:20:42Z</published> <category scheme='http://diveintomark.org' term='diveintopython'/> ⑥ <category scheme='http://diveintomark.org' term='docbook'/> <category scheme='http://diveintomark.org' term='html'/> <summary type='html'>Putting an entire chapter on one page sounds ⑦ bloated, but consider this &amp;mdash; my longest chapter so far would be 75 printed pages, and it loads in under 5 seconds&amp;hellip; On dialup.</summary></entry> ⑧

① Элемент author сообщает о том, кто написал статью: некоторый парень по имени Марк (Mark), который валяет дурака на сайте http://diveintomark.org/ (В данном случае ссылка на сайт автора совпадает с альтернативной ссылкой в метаинформации о фиде, но это не всегда правда, так как многие блоги имеют несколько авторов, у каждого из которых — свой сайт.)

② Элемент title содержит заголовок статьи «Dive into history, 2009 edition».

③ Как и с альтернативной ссылкой на фид, в элементе link находится адрес HTML версии данной статьи.

④ Элемент entry, подобно фидам, имеет уникальный идентификатор.

⑤ Элемент entry имеет две даты: дату первой публикации и дату последнего изменения.

⑥ Элементы entry могут иметь произвольное количество категорий category. Рассматриваемая статья попадёт в категории diveintopython, docbook и html.

⑦ Элемент summary даёт краткий обзор статьи. (Бывает также не представленный здесь элемент содержания content предназначенный для включения в фид полного текста статьи.) Данный элемент summary содержит специфичный для фидов Atom атрибут type='html' указывающий что содержимое элемента есть текст в формате HTML. Это важно, так как HTML-объекты &mdash; и &hellip; присутствующие в элементе должны отображаться как «—» и «…», а не печататься «как есть».

⑧ И, наконец, закрывающий тег элемента entry говорит о конце метаданных для этой статьи.

Синтаксический разбор XML

В Python документы XML могут быть обработаны c использованием разных библиотек. Язык имеет обычные синтаксические анализаторы DOM и SAX, но я буду использовать другую библиотеку ElementTree.

>>> import xml.etree.ElementTree as etree ①>>> tree = etree.parse('examples/feed.xml') ②>>> root = tree.getroot() ③>>> root ④<Element {http://www.w3.org/2005/Atom}feed at cd1eb0>

① Модуль ElementTree входит в стандартную библиотеку Python, путь для импорта xml.etree.ElementTree.

② Функция parse() — это базовая функция модуля ElementTree. Функция принимает имя файла или файлоподобный объект. Эта функция выполняет синтаксическй анализ документа за раз. Если разрабатываемая программа должна экономить память, то можно анализировать XML документ частями.

③ Функция parse() возращает объект, который является представлением всего документа. Однако объект tree не является корневым элементом. Чтобы получить ссылку на корневой элемент, необходимо вызвать метод getroot().

④ Как и следовало ожидать, корневой элемент есть элемент фида в пространстве имён http://www.w3.org/2005/Atom. Строковое представление объекта root ещё раз подчёркивает важный момент: XML элемент — это комбинация пространства имён и его имени-тега (так же называемого локальным именем). Каждый элемент в данном документе находится в пространстве Atom, поэтому корневой элемент представлен как {http://www.w3.org/2005/Atom}feed.

Модуль ElementTree всегда представляет элементы XML как '{пространство имён}локальное имя'. Вам неоднократно предстоит использовать этот формат при использовании API ElementTree.