XML и Java: Возвращение к основам (исходники)

Бретт МакЛафлин

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

В результате встает общий вопрос: а не забыли ли мы, как правильно создавать XML-документы? И вообще, знаем ли мы что такое "хороший XML-документ"? В этой короткой статье я попытаюсь пересмотреть некоторые из 101 советов по XML с целью напомнить, что, несмотря на все вспомогательные технологии, важно следовать основным принципам создания документов.

Первые шаги: использование правильных конструкций в XML

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

Теги

По всей вероятности, авторам легче всего объяснить использование именно XML-тегов, причем по той причине, что зачастую они применяют их для всего что только возможно. Разумеется, это неправильный подход и, более того, у него существуют серьезные недостатки. Как правило, в XML (конечно не всегда, но мы же говорим об оптимальном использовании XML) теги применяются для представления каких-либо иерархических данных, или на крайний случай, данных, которые в принципе могут представлять собой иерархию. Но, к примеру, фамилия человека ни при каких условиях не является иерархической структурой - это просто строка и не более того. Однако использование тега name для представления полного имени может быть оправдано, т.к. он может состоять из нескольких компонентов: имени, фамилии, может отчества или обращения и т.д. Таким образом, нижеследующий фрагмент не является примером хорошего использования XML-тегов:

<firstName>Bob</firstName>

А вот этот - является:

<name firstName="Bob"
         lastName="Zemeckis"
         title="Mr." />

Если вам кажется странным, что я не использовал вложенные теги для представления firstName, lastName, и title, перечитайте предыдущий абзац еще раз. Мы еще вернемся к более детальному обсуждению этого вопроса в следующей главе, посвященной атрибутам.

В общем случае, если один и тот же тег не должен повторяться более одного раза в одном месте вашего документа, то лучше вместо него использовать атрибуты. Примерами обратной ситуации могут служить, скажем, тег address, т.к. вам может понадобиться несколько адресов разного типа ( домашний и рабочий), или тег author для хранения двух авторов одной книги. При этом важно, что для использования тега элемент не обязательно должен повторяться более одного раза - достаточно, чтобы это было в принципе возможно.

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

Атрибуты

Какой бы прописной истиной это не казалось, но атрибуты в XML должны использоваться для хранения исключительно атомарных значений. Например, если тег служит для представления информации о человеке, проанализируйте, какие сведения о нем являются атомарными - скорее всего, они-то и должны быть представлены в атрибутах. Номера социального страхования, удостоверения личности и дата рождения-вот вам отличные кандидаты для использования атрибутов.

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

<person>
  <ssn>489098723</ssn>
</person>

Но это лишено всякого смысла: номер социального страхования - это классический пример атомарного значения. Хуже того, использование в этом случае тега негативно сказывается на производительности, т.к. для доступа к значению вложенного тега придется сначала получить родительский тег, затем список дочерних для последующего итерирования. Совершенно не факт, что нужный тег будет первым в списке дочерних тегов, он вполне может оказаться и последним. Более того, после этого еще придется запросить дочерние элементы и этого тега (несмотря на то, что единственный дочерний элемент будет всего-навсего текстовой строкой) и перебрать их значения. Так что весь процесс будет состоять из нескольких этапов:

  1. Получить ссылку на родительский элемент (в нашем случае, тег person).
  2. Получить список его дочерних элементов.
  3. Проитерировать по списку пока не будет найден искомый тег (в нашем случае, ssn).
  4. Возможно, привести список дочерних элементов тега к нормальному виду, чтобы упростить дальнейшее использование.
  5. Получить список дочерних элементов искомого тега.
  6. Извлечь текстовое содержимое тега.

А теперь сравните с доступом к нужному значению при использовании атрибутов:

  1. Получить ссылку на родительский элемент (в нашем случае, тег person).
  2. Получить список его атрибутов.
  3. Проитерировать по списку пока не будет найден искомый атрибут (в нашем случае, ssn).
  4. Получить значение атрибута.

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

Таким образом, несмотря на несколько менее приятный внешний вид, мне гораздо больше нравятся документы, подобные следующему:

<person ssn="489098723"
        firstName="Bobby"
        lastName="McKenza"
>
  <occupation>
    <occupation-type status="part-time"
                     job="author" />
    <occupation-type status="part-time"
                     job="programmer" />
  </occupation>
  <address type="home"
           street="112 E. Harney Way"
           city="New York"
           state="NY"
           zip="10012" />
  <!-- etc... -->
</person>

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

Инструкции по обработке

Я нечасто использую инструкции по обработке (processing instructions - PI), но при этом меня раздражают различные API для работы с XML, которые требуют помешения инструкций в комментарии или использования специфических пространств имен, а то и вовсе - вложения инструкций в специальные теги. Если вам необходимо указать в своем документе, каким образом он должен обрабатываться неким API, то для этого существует строго определенный способ - инструкции по обработке .

Вы наверняка видели инструкции подобно этим, особенно при использовании XSL:

<?xml version="1.0"?>
<?xml-stylesheet href="classic.xsl" type="text/html"?>
<?xml-stylesheet href="alternate.xsl" type="text/xml" alternate="yes"?>
<article>
  <!-- etc ... -->
</article>

В данном случае, в PI указывается, какие именно таблицы стилей процессор XSLT должен применить к документу XML. Несмотря на то, что многие API игнорируют данную возможность (первым делом в голову приходит JAXB), вам стоит пользоваться именно PI, т.к. это гораздо лучше, чем документы типа такого:

<?xml version="1.0"?>

<!-- xml-stylesheet url="classic.xsl" document-type="text/html" -->
<!-- xml-stylesheet url="alternate.xsl" document-type="text/xml" -->
<article>
  <!-- etc ... -->
</article>

Мне постоянно встречаются подобные документы. Помните, что комментарии не должны нести никакой важной для обработки информации, и их использование в таком качестве крайне опасно. Например, API для генерирования документации по Java-классам (javadoc) используют комментарии. Но, по крайней мере, они служат только для создания документации, а не для какой-либо реальной обработки данных. Конечно, если вы вынуждены использовать подобные API, то ничего не поделаешь, но вы должны четко отдавать себе отчет, что XML не предназначен для подобных действий. В данном случае, я считаю, что разработчики спецификации XML совершенно правы.

Заключение

Наверное, стоило оговориться, что я никоим образом не являюсь пуристом языка XML. Более того, я считаю, что многие вещи в XML сделаны неразумно, неподходящим образом или же попросту неправильно. Но при всем при этом, я убежден , что если уж вы выбрали XML для своих целей, то стоит придерживаться определенных принципов в работе с ним; в противном случае - зачем вообще его использовать? Если вы не используете теги для сложных, структурированных данных, практически не применяете атрибуты, неверно или вообще не используете инструкции по обработке, то в какой-то момент вам стоит задуматься о разработке собственного языка и парсера для представления ваших данных. Иначе вам придется иметь дело со всеми проблемами XML, такими как некомпактность синтаксиса, странно выглядящие документы, беда с кодировками и т.д., не получая при этом пользы от его преимуществ: быстрых парсеров, оптимизированных под специальные задачи.

Так что поразмыслите над моими советами, причем не потому, что, следуя им, вы гарантированно будете правильно использовать XML и не ради задабривания неких семантических божеств (ради этого не стоит делать вообще ничего в программировании). Смысл в том, что таким образом вы сможете более эффективно использовать преимущества XML, а также писать более производительное программное обеспечение. Так что не бойтесь идти в обход правил... но только если это действительно необходимо!


Страница сайта http://www.interface.ru
Оригинал находится по адресу http://www.interface.ru/home.asp?artId=18353