Журнал ВРМ World

Мировая история развития технологий управления эффективностью бизнеса – обзоры зарубежных публикаций

Представление нулевых значений в схеме XML

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

Введение

Компонентная объектная модель для Java, известная как Java beans, имеет определенные свойства, называемые полями. Эти поля могут иметь нулевые значения, если только они не являются полями примитивного типа. При преобразовании ("мэппировании") Java beans в XML эти поля становятся элементами или атрибутами. Простые элементы и атрибуты не могут иметь нулевых значений (их можно рассматривать как своего рода эквиваленты примитивным типам Java, которые также не могут иметь нулевых значений). Существует несколько способов изменить атрибуты и элементы XML таким образом, чтобы их экземпляры имели нулевое значение (или хотя бы логически были эквивалентны нулю):

  • для атрибутов:
    • использовать атрибут use="optional";
  • для элементов:
    • использовать атрибут nillable="true";
    • или использовать атрибут minOccurs="0".

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

Элементы и атрибуты

Прежде чем рассматривать представления нулевых значений, необходимо решить, что будет использоваться для поля объекта, - элемент или атрибут. В первую очередь нужно определить тип этого поля. В атрибутах могут использоваться только простые типы. Таким образом, при наличии сложного типа выбор однозначен - должен использоваться элемент. Но в случае простого типа вопрос остается: что лучше - атрибут или элемент? Например, при наличии структуры, приведенной в листинге 1, что окажется лучше: attrField или elemField?


Листинг 1. Схема AttributeOrElement


<complexType name="AttributeOrElement">
  <sequence>
    <element name="elemField" type="xsd:int"/>
  </sequence>
  <attribute name="attrField" type="xsd:int"/>
</complexType>


В листинге 2 представлен экземпляр схемы листинга 1.


Листинг 2. Экземпляр AttributeOrElement


<attributeOrElement attrField="5">
  <elemField>5</elemField>
</attributeOrElement>


Ясно видно, что поле атрибута занимает меньше места в экземпляре, чем поле элемента. Соответственно, сообщения SOAP, которые переносят документы в формате XML, содержащие атрибуты, также будут меньше, что сократит время их передачи. Таким образом, кажется, что атрибуты оказываются предпочтительнее элементов. Но те специалисты, кто уже давно работает со схемами, могли заметить, что атрибуты используются не так уж часто. Возникает вопрос: почему? Автор затрудняется назвать точную причину, но приводит несколько аргументов:

  • поскольку элементы в обязательном порядке используются для сложных типов, то для единообразия их используют и для простых типов. В результате схемы выглядят проще;
  • "свернутый" шаблон документ/буквенный требует, чтобы элемент верхнего уровня complexType не содержал атрибутов (см. статью "Какой стиль WSDL лучше использовать" (Which style of WSDL should I use?) в разделе Ресурсы). Поскольку список параметров того элемента может включать только элементы, то и все списки сложного типа также должны включать только элементы для соблюдения единообразия;
  • поскольку атрибуты и элементы не упорядочены (если только не используется тэг <all>), то существует вероятность того, что синтаксический разбор атрибутов может оказаться дороже, чем проверка элементов (хотя автор выражает сомнение в том, что это имеет значение для сложных парсеров XML).

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

Нулевой атрибут

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


Листинг 3. Схема TypeWithNullAttribute


<complexType name="TypeWithNullAttribute">
  <attribute name="attrField" type="xsd:int" use="optional"/>
</complexType>


Листинг 4. Экземпляры TypeWithNullAttribute

Атрибут со значением:


<typeWithNullAttribute attrField="5"/>


Атрибут, переданный как нулевой:


<typeWithNullAttribute/>


Из этих примеров видно, что в схеме нулевой атрибут объявлен очень просто. Экземпляр нулевого атрибута также выражен очень просто - он отсутствует.

Нулевые элементы

Существует два способа представить нулевое значение, используя элементы: с помощью атрибутов nillable="true" или minOccurs="0". В листинге 5 показана схема для оператора TypeWithNullElements, содержащая по одному элементу для каждого из стилей полей, которые могут иметь нулевое значение.


Листинг 5. Схема для TypeWithNullElements


<complexType name="TypeWithNullElements">
  <sequence>
    <element name="nillableElem" nillable="true" type="int"/>
    <element name="minOccursElem" minOccurs="0" type="int"/>
  </sequence>
</complexType>


В листинге 6 показаны экземпляры для TypeWithNullElements. Первая из них содержит нормальные значения, а вторая - нулевые.


Листинг 6. Экземпляры TypeWithNullElements

Элементы со значениями:


<typeWithNullElements>
  <nillableElem>5</nillableElem> 
  <minOccursElem>5</minOccursElem> 
</typeWithNullElements>


Элементы с нулевыми значениями:


<typeWithNullElements>
  <nillableElem xsi:nil="true"/>
</typeWithNullElements>


Как и необязательный атрибут, элемент с атрибутом minOccurs="0", имеющий нулевое значение, просто отсутствует в экземпляре XML. Это способствует уменьшению размера сообщения, в отличие от того варианта, когда элемент определяется с помощью атрибута nillable="true". Атрибут nillableElem, даже имея нулевое значение, включает поле для значения, которое показывает, что значение этого атрибута действительно равно нулю.

Когда атрибут nillable="true" оказывается полезен

Если атрибут minOccursElem настолько лучше, чем атрибут nillableElem, то зачем последний может вообще понадобиться? Как было только что сказано, нулевое значение атрибута nillableElem имеет определенное поле для значения. В каком случае это может оказаться полезным? Один из примеров - массив, в котором каждый элемент потенциально может иметь нулевое значение. Вот пример такого массива из четырех элементов: {0, null, 1, null}. Как можно представить этот массив, используя экземпляр элемента minOccursElem? Ответ - никак. Такой массив из четырех элементов будет неотличим от следующего массива из двух элементов: {0, 1}. При использовании элементов minOccurs="0" нет поля для нулевых элементов. Поэтому при данном сценарии обязательно нужно использовать элементы nillable="true". В листинге 7 показана схема для такого массива, а в листинге 8 - экземпляр XML для массива {0, null, 1, null}.


Листинг 7. Схема для элементов массива, значение которых может быть нулевым


<complexType name="nullableElementArray">
  <sequence>
    <element name="elem" type="int" maxOccurs="4" nillable="true"/>
  </sequence>
</complexType>


Листинг 8. Экземпляр XML для элементов массива, значение которых может быть нулевым


<nullableElementArray>
  <elem>1</elem>
  <elem xsi:nil="true"/>
  <elem>2</elem>
  <elem xsi:nil="true"/>
</nullableElement>


Заключение

Существует три способа представления нулевых полей в схеме XML: необязательные атрибуты, элементы minOccurs="0" и элементы nillable="true". Каждый из них используется в определенной ситуации. Необязательный атрибут используется в случае простого типа, значение которого может быть равно нулю; элемент minOccurs="0" - в случае сложного типа, значение которого может быть равно нулю, если требуется сэкономить место; элемент nillable="true" - если нулевое значение должно иметь определенное поле (например, когда оно входит в состав массива).

Ресурсы

  • Какой стиль WSDL лучше использовать (Which style of WSDL to use). - Описание сообщений WSDL и SOAP для каждого стиля.
  • Нулевой массив или пустой массив? (Array Gotcha - Null Array vs. Empty Array). - Описание различий между нулевым массивом и массивом, не имеющем элементов.

Об авторе

Расселл Бьютек (Russell Butek) является одним из разработчиков WebSphere - процессора компании IBM для Web-сервисов. Он также выполняет обязанности представителя IBM по JAX-RPC в экспертной группе по разработке спецификаций Java (Java Specification Request - JSR). Расселл участвовал во внедрении процессора AXIS SOAP компании Apache, занимаясь вопросами совмещения AXIS 1.0 и JAX-RPC 1.0. Ранее он являлся разработчиком CORBA ORB компании IBM, а также представителем IBM в различных рабочих группах OMG. С Расселлом Бьютеком можно связаться по адресу butek@us.ibm.com.

Автор: Расселл Бьютек (Russell Butek)