Валидация XML и XHTML

20 октября 2008 года, 19:11

В 105-ом выпуске мы подробно рассмотрели формат DTD: чем является, где применяется и какая польза. На самом деле, эта статья была умышленно сфабрикована для того, чтобы мы смогли идти дальше по валидации разных языков программирования.

Сегодня мы постараемся погрузиться в валидацию до боли знакомых нам языков разметки: XML и XHTML. На первый взгляд, они такие похожие и должны рассматриваться как одно целое, но на самом деле они довольно разные и для них следует писать совершенно разные валидаторы. Можно даже выразиться следующим образом: проверка XHTML на XML-валидаторе будет недостаточной, а XML на XHTML-валидаторе — избыточной, и обе проверки покажут, что документ невалиден.

Общие шаги

Перед тем как переходить к частному, рассмотрим общие шаги на пути к становлению валидации. Для того, чтобы произвести валидацию содержимого, его сначала нужно получить. Источник (то, что мы должны проверить на соответствие набору определённых правил) может быть совершенно непредсказуемым:

  1. Файл;
  2. Строка;
  3. Удалённый источник.

Мы абстрагируемся от указанных выше источников, ведь на самом деле нам не так уж и важно, откуда мы получаем данные для валидации: все они в конечном итоге предстают в виде строки. После того, как мы получили строку, нам нужно её обработать таким образом, чтобы получить элементы, с которыми мы можем работать на том языке программирования, на котором мы программируем. Для начала мы должны определиться, в какие сущности мы можем превратить входные данные. Вспоминаем, что основной единицей в XML/XHTML является элемент. От него и будем отталкиваться. Помимо элемента, нам нужен контейнер элементов, который мы будем называть документом.

Каждый XML/XHTML-документ состоит из набора элементов, причём всегда есть корневой элемент, содержащий в себе все остальные элементы. Постойте! Но ведь это же обычное дерево! Да-да, всё правильно: мы видим перед собой дерево элементов. Мы пришли к достаточно важному выводу: любой XML-документ (и документ на любом XML-подобном языке) можно представить в виде дерева. После, с этим деревом мы можем выполнять самый разный набор операций: сравнение, удаление, перестановка, траверсинг (операция прохода по всем узлам дерева) и другие.

Как проверяется XML

Проверка XML несравненно проще проверки XHTML: нам необходимо лишь удостовериться в выполнении нескольких требований, что можно сделать совершенно спокойно, учитывая то, что у нас есть дерево элементов. Систематизируем необходимые правила:

  1. Первый элемент в документе — это всегда декларация заголовка XML вида , где […] — атрибуты заголовка XML;
  2. Все элементы должны быть названы верным образом и не должны содержать посторонних символов (пробелов, к примеру);
  3. Все атрибуты должны быть записаны в правильной форме (проверяется достаточно просто, тем же регулярным выражением);
  4. Документ должен содержать только один корневой элемент;
  5. Вложенность элементов должна быть соблюдена (проверка данного утверждения достигается за счёт использования стека элементов, с помощью которого мы проверяем соответствия открывающих и закрывающих элементов);

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

Если все вышеуказанные правила соблюдаются, то документ считается валидным XML-документом. В противном случае — документ содержит ошибки, список которых валидатор может вывести пользователю для ознакомления и исправления.

XHTML: лёгкие Интернета

Проверка XHTML основывается на валидации XML. Сначала мы должны удостовериться в том, что документ является валидным с точки зрения XML (то есть соблюдена вложенность тегов, правильно оформлены элементы и их атрибуты, и другие), и уже потом накладывать дополнительные правила. Если документ не является валидным с точки зрения XML, то он заведомо не является валидным и с точки зрения XHTML.

Чтобы применять какие-либо правила XHTML к документу, сначала нужно эти правила описать таким образом, чтобы их было легко получить и как трафарет наложить на документ. Для валидации XHTML-документов правила могут храниться в виде нескольких форматов:

  1. DTD-документы;
  2. XML Schema;
  3. Relax NG.

Независимо от формата, производится следующий набор проверок:

  • Проверка всех используемых элементов в документе на их наличие в XHTML (если элемент, указанный в документе, не существует, то выдаётся соответствующая ошибка);
  • Проверка на наличие обязательных атрибутов у соответствующих элементов;
  • Проверка типа содержимого некоторых атрибутов на соответствие тем типам, которые указаны в правилах;
  • Тип содержимого элемента должен совпдадать с тем, который указан в правилах;
  • Так как XHTML определяет классы элементов (блоковые и текстовые), то валидатор должен убедиться в том, что элементы одного класса (уровня) должны быть правильно вложены в элементы другого класса (уровня). Подобные закономерности также описываются в правилах.

После выполнения указанного набора правил можно говорить о том, является ли документ валидным или напротив: содержит какие-то ошибки, которые валидатор может указать пользователю.

Итоги

Логично было бы заметить, что отсутствует описание процесса обработки документов для их представления в виде дерева элементов (абстрактно или на конкретном языке программирования). Если таковой процесс интересен читателям, то он будет описан в отдельной статье, в противном случае будем двигаться дальше по намеченному вектору.

Мнения (15)

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

  • FX Poster

    20 октября 2008 г.20:31

    Проверка XML несравненно проще проверки XHTML: нам необходимо лишь удостовериться в выполнении нескольких требований, что можно сделать совершенно спокойно, учитывая то, что у нас есть дерево элементов.

    Или я чего-то не понимаю, или автор. Как может дерево элементов быть построено до валидации? Приведи пример дерева для следующего документа:

    <?xml version="1.0" encoding="utf-8" ?> <root> <element1> <element2> </element1> </element2> </root>

    XML невалиден, да. Вот только «построить дерево элементов», а потом «его использовать» мы не сможем, так как получим ошибку еще при построении.

  • Дин автор

    20 октября 2008 г.20:38

    Мы можем дерево построить в любом случае, но вот правильным ли будет это дерево?

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

    В случае возникновения любых ошибок обработки, мы всё равно получим дерево, какое бы оно ни было.

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

  • Miscђka

    21 октября 2008 г.10:02

    если у XML указан конкретный DTD, должен ли валидатор с ним сверяться? Если внешний DTD при этом недоступен?

  • Дин автор

    21 октября 2008 г.10:21

    Это зависит от валидатора: на его собственный выбор. Обычно валидаторы XHTML содержат в собственной комплектации все наборы DTD (или иных схем для валидации), а валидаторам XML следует их подгружать, если они указаны.

    XHTML — это, по сути, XML с собственным DTD, но в этом случае валидаторы XHTML не подгружают данные документы из какого-либо удалённого источника (так как считают его ненадёжным).

  • Makishvili

    22 октября 2008 г.13:22
    Если все вышеуказанные правила соблюдаются, то документ считается валидным XML-документом

    Разве речь идет о валидации XML-документа? Мне кажется, что правильнее говорить о велформности XML (well-formed).

  • Дин автор

    22 октября 2008 г.13:31

    @Makishvili, в данном случае я считаю, что можно говорить о синонимичности определений. Но это только я считаю: Ваша точка зрения может отличаться от моей.

  • Sannis

    22 октября 2008 г.23:04

    @Дин, а как ты называешь валидный документ, который ещё и соответствует своей схеме?

  • Дин автор

    22 октября 2008 г.23:08

    @Sannis, так и называю. Я не развожу понятие о правильности документа, хотя у меня есть понятие Semi-valid. Можете поискать по записям, если интересно. Не понимаю, зачем вводить отдельное понятие well-formed и не использую его.

    Опять же, никому не навязываю это.

  • Sannis

    24 октября 2008 г.03:29

    @Дин, просто думал о том, как ты их разделяешь, ничего больше. Всё-таки одно дело, когда это валидный XML, значит его можно распарсить, а другое, если он ещё и со схемой согласуется, значит можно из него полезные данные извлечь. Хотя, конечно, это уже лингвистические особенности, которые можно хоть каждый год менять :)

  • Максим

    02 ноября 2008 г.05:55

    Оффтоп — как получить приглашение на ХабраХабр?

  • Tenshi

    25 января 2009 г.09:49

    xml-декларация не является обязательной, хотя и строго рекомендуется к использованию.

  • Дин автор

    25 января 2009 г.15:15

    «Пролог» в документе обязателен.

  • Tenshi

    25 января 2009 г.18:12

    http://www.w3.org/TR/xml/#NT-prolog

  • ккккк

    10 ноября 2010 г.23:02

    апаапапап

  • fox

    22 мая 2012 г.21:01

    У меня и без валидатора ошибки находит

Я тоже знаю!

Для обращения к человеку используйте символ @, после которого следует имя того, к кому обращаетесь (пробелы заменяются на знак подчёркивания). Если вам интересно, можете подписаться на комментарии по RSS или по эл. почте. Ведите себя достойно, вы же не роботы, правда?

Вы можете использовать следующие XHTML-элементы в разметке комментария: strong, em, span[class=crossline], a[href=uri], code[type=язык], blockquote, ul и ol. В качестве языка кода может быть указан, например, javascript или css.