__toc__

Майже кожен розділ цієї книги обертається навколо шматка демонстраційного коду. Але суть XML не в коді, а в даних. Одним з типових використань XML є "синдикація фідів" які перелічують останні статті блогу, форуму, чи іншого частооновлюваного веб-сайту. Більшість популярних блогових платформ можуть генерувати фід і оновлювати його як тільки нові статті чи обговорення публікуються. Можна читати блог "підписавшись" на його фід, і можна читати кілька блогів за раз, за допомогою спеціальної програми - агрегатора фідів, такої наприклад як Google Reader.

Ось тут дані XML з якими ми будемо працювати в цьому розділі. Це фід, а якщо точніше, то фід Atom.

<?xml version='1.0' encoding='utf-8'?> <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/'/> <link rel='self' type='application/atom+xml' href='http://diveintomark.org/feed/'/> <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 &mdash; my longest chapter so far would be 75 printed pages, and it loads in under 5 seconds&hellip; On dialup.</summary> </entry> <entry> <author> <name>Mark</name> <uri>http://diveintomark.org/</uri> </author> <title>Accessibility is a harsh mistress</title> <link rel='alternate' type='text/html' href='http://diveintomark.org/archives/2009/03/21/accessibility-is-a-harsh-mistress'/> <id>tag:diveintomark.org,2009-03-21:/archives/20090321200928</id> <updated>2009-03-22T01:05:37Z</updated> <published>2009-03-21T20:09:28Z</published> <category scheme='http://diveintomark.org' term='accessibility'/> <summary type='html'>The accessibility orthodoxy does not permit people to question the value of features that are rarely useful and rarely used.</summary> </entry> <entry> <author> <name>Mark</name> </author> <title>A gentle introduction to video encoding, part 1: container formats</title> <link rel='alternate' type='text/html' href='http://diveintomark.org/archives/2008/12/18/give-part-1-container-formats'/> <id>tag:diveintomark.org,2008-12-18:/archives/20081218155422</id> <updated>2009-01-11T19:39:22Z</updated> <published>2008-12-18T15:54:22Z</published> <category scheme='http://diveintomark.org' term='asf'/> <category scheme='http://diveintomark.org' term='avi'/> <category scheme='http://diveintomark.org' term='encoding'/> <category scheme='http://diveintomark.org' term='flv'/> <category scheme='http://diveintomark.org' term='GIVE'/> <category scheme='http://diveintomark.org' term='mp4'/> <category scheme='http://diveintomark.org' term='ogg'/> <category scheme='http://diveintomark.org' term='video'/> <summary type='html'>These notes will eventually become part of a tech talk on video encoding.</summary> </entry> </feed>

П'ятихвилинний ввідний курс XML Якщо ви вже знаєте XML, можете пропустити цей розділ.

XML - це узагальнений спосіб опису даних з ієрархічною структурою. Документ XML містить один чи більше елементів, які обмежуються відкриваючим та закриваючим тегами. Ось завершений (хоча й нудний) документ XML:

<foo> </foo>

В першому рядку відкриваючий тег, а в другому - відповідний йому закриваючий. Як і дужки при написанні математичних виразів чи коду, кожен відкриваючий тег має бути закритим відповідним закриваючим.

Елементи можна вставляти один в одного довільну кількість разів. Елемент bar всередині елементу foo називається піделементом або дитиною тегу foo.

<foo> <bar></bar> </foo>

Перший елемент в кожному XML документі називається кореневим. Документ XML може мати лише один кореневий елемент. Внизу ви бачите текст який не є документом XML, тому що він має два кореневі елементи:

<foo></foo> <bar></bar>

Елементи можуть мати атрибути, які є парами ключ - значення. Атрибути перелічуються всередині відкриваючого тега елемента і розділяються пропуском. Імена атрибутів не повинні повторюватись в межах одного елемента. Значення атрибутів повинні поміщуватись в лапки. Можна використовувати як одинарні, так і подвійні лапки.

<foo lang='en'> <bar id='papayawhip' lang="fr"></bar> </foo>

Елемент foo має один атрибут який називається lang. Значенням атрибута lang - en. Елемент bar має два атрибути, названі id та lang. Значенням атрибута lang є fr. Це жодним чином не конфліктує з елементом foo, бо кожен елемент має свій власний набір атрибутів.

Порядок атрибутів не має значення. Атрибути елемента утворюють невпорядковану множину пар, на зразок словника мови Python. Немає обмеження на кількість атрибутів які можна описати для кожного елемента.

Елементи можуть мати текстовий вміст.

<foo lang='en'> <bar lang='fr'>PapayaWhip</bar> </foo>

Елементи що не містять тексту і дітей називаються порожніми.

<foo></foo>

Існує скорочення для запису порожніх елементів. Вставляючи символ / наприкінці відкриваючого тегу, ви можете пропустити закриваючий тег. XML з попереднього прикладу може бути записаний наступним чином:

<foo/>

Так як і функції Python можуть бути описаними в різних модулях, елементи XML можуть бути описаними в різних просторах імен. Простори імен зазвичай виглядають як URL. Ви можете використати декларацію xmlns для того щоб задати простір імен за замовчуванням. Ця декларація схожа на атрибут, але вона має іншу мету.

<feed xmlns='http://www.w3.org/2005/Atom'> <title>dive into mark</title> </feed>

Елемент feed знаходиться в просторі імен http://www.w3.org/2005/Atom. Елемент title також знаходиться в просторі імен http://www.w3.org/2005/Atom. Декларація простору імен впливає на елемент в якому вона описується а також на всі дочірні.

Також ви можете використати декларацію xmlns:prefix щоб описати простір імен, і пов'язати його з префіксом prefix. Тепер кожен елемент в тому просторі імен повинен оголошуватись з явним простором імен. Ось так:

<atom:feed xmlns:atom='http://www.w3.org/2005/Atom'> <atom:title>dive into mark</atom:title> </atom:feed>

З точки зору XML парсера попередні два XML документи ідентичні. Простір імен та назва елемента разом дають XML ідентичність. Префікси створені тільки для того щоб посилатись на простори імен, тому саме ім'я префікса (atom:) не має значення. Простори імен співпадають, імена елементів співпадають, атрибути (чи їх відсутність) співпадають, і вміст кожного елемента теж збігається, тому документи XML однакові.

Нарешті, документи XML можуть містити інформацію про кодування в першому рядку, перед кореневим елементом (Якщо вам цікаво як документ може містити інформацію яка повинна бути відомою до того як документ можна буде прочитати, Секція F специфікації XML містить деталі як розв'язати цю пастку 22.)

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

І тепер ви знаєте достатньо XML щоб бути небезпечним.

Структура фіду Atom Подумайте про блог, чи фактично будь-який сайт з вмістом що часто оновлюється, такий як CNN.com. Сам сайт має заголовок ("CNN.com"), підзаголовки ("Breaking News, U.S., World, Weather, Entertainment & Video News"), дату останнього оновлення ("updated 12:43 p.m. EDT, Sat May 16, 2009") та список статтей опублікованих в різні моменти часу. Кожна стаття також має заголовок, дату початкової публікації (та можливо дату останнього оновлення, якщо вони публікували доповнення чи виправлення), та унікальну адресу URL.

Формат синдикації Atom створений аби зібрати всю цю інформацію в стандартній формі. Мій блог, та CNN.com дуже відрізняються своїм стилем, тематикою та аудиторією, але вони обидва мають подібну базову структуру. CNN.com має заголовок, мій блог має заголовок. 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.

<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/'/> ⑤

① Заголовок фіду "dive into mark" записується в елементі <title>.

② Підзаголовок, "currently between addictions" - в елементі <subtitle>.

③ Кожен фід повинен мати глобально унікальний ідентифікатор. Дивіться RFC 4151 аби дізнатись як такий створити.

④ Цей фід востаннє був оновлений 27 березня, 2009, в 21:56 за Гринвічем. Зазвичай цей час дорівнює часу останнього оновлення найновішої статті.

⑤ Тепер речі стають цікавими. Цей елемент не має текстового вмісту, але має три атрибути: rel, type, and href. Значення rel вказує нам на тип посилання; rel='alternate' означає що це посилання на альтернативне представлення цього фіду. type='text/html' означає що це посилання на HTML-сторінку. Ну, а сама адреса посилання дається нам в атрибуті href.

Таким чином ми знаємо що це фід для сайту з заголовком "dive into mark" який доступний за адресою http://diveintomark.org/ та востаннє оновлювався в березні 27, 2009.

Після метаданих фіду йде список недавніх публікацій. Публікація виглядає наступним чином:

<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 &mdash; my longest chapter so far would be 75 printed pages, and it loads in under 5 seconds&hellip; On dialup.</summary> </entry> ⑧

① Елемент author повідомляє хто написав цю статтю: якийсь чувак на ім’я Марк, якого можна знайти за адресою http://diveintomark.org/. (Це така сама адреса як і адреса альтернативного представлення фіду, але не обов’язково повинна бути такою. Багато блогів мають по кілька авторів, кожен з яких може мати власний сайт.)

② Елемент title дає нам заголовок публікації, "Dive into history, 2009 edition".

③ Як і з посиланням на альтернативне представлення фіду, цей елемент link дає нам адресу HTML версії публікації.

④ Публікації, як і фіди, потребують унікального ідентифікатора.

⑤ Публікації мають по дві дати: дату першої публікації (published) та дату останньої зміни (updated).

⑥ Публікації можуть мати довільне число категорій. В цій, наприклад, є категорії: diveintopython, docbook, та html.