12 подписчиков
Что интересного тут еще есть, поле inn имеет кастомный тип, который "базируется" на типе string, но имеет определенный паттерн, описанный с помощью регулярного выражения. Таким образом мы получили обязательное поле, которое будет валидно только в том случае, если его заполнить 12-ю или 10-ю цифрами.
Кстати, об обязательности, тут я устраивал викторины про minOccurs и maxOccurs. minOccurs отвечает за минимальное количество повторений элемента, а maxOccurs – за максимальное. По умолчанию значения этих атрибутов равно единице. А теперь на нашем примере, что это означает?
⏩Все поля без этих атрибутов являются обязательными;
⏩Все поля с minOccurs=0 являются необязательными;
⏩Поле contact является необязательным массивом.
Еще хочу обратить внимание на "индикаторы" sequence и all. Эти индикаторы отвечают за установку порядка. То есть при использовании sequence элементы четко закреплены за своими местами(имеют обязательную последовательность), соответственно их нельзя менять местами. При использовании индикатора all поля могут идти в любом порядке. Для наглядности в примере XML взгляните на элементы внутри user, они как объявлены в XSD, так и идут в примере. Далее взгляните на массив contactList, который используется с индикатором all, видно как поля type и value чередуются и это абсолютно корректно.
Помимо этих 2 индикаторов порядка еще есть choice, который тоже очень удобен и используется как оператор "исключающего ИЛИ". То есть в примере, если бы вместо all использовался choice, то в XML был бы либо элемент type, либо элемент value. choice очень удобно использовать, когда одна XSD используется для описания всех API микросервиса. Например:
<xs:choice>
<xs:element name="GetClientDataByIdRequest" type="GetClientDataByIdRequestType" />
<xs:element name="GetClientDataByIdResponse" type="GetClientDataByIdResponseType" />
<xs:element name="SendNotificationRequest" type="SendNotificationRequestType" />
<xs:element name="SendNotificationResponse" type="SendNotificationResponseType" />
<xs:element name="CheckClientRequest" type="CheckClientRequestType" />
<xs:element name="CheckClientResponse" type="CheckClientResponseType" />
</xs:choice>
Еще из интересного, в 2 местах схемы я использовал Enum'ы. Суть примерно та же, что и у элемента inn, поле также базируется на типе string, однако вместо паттерна, используется ограничение в виде возможных вариантов заполнения. Например, поле type элемента contact, может быть заполнено исключительно тремя значениями:
🟢EMAIL
🟢PHONE
🟢TELEGRAM
Конечно же, в XSD-схему можно добавлять описание для полей. Делается это так:
<xs:annotation>
<xs:documentation>Текст с описанием элемента</xs:documentation>
</xs:annotation>
Также стоит упомянуть, что можно использовать атрибуты. Вот так они описываются по схеме(один из вариантов):
<xs:element name="product">
<xs:complexType>
<xs:simpleContent>
<xs:restriction base="xs:string">
<xs:attribute name="coast" type="xs:boolean" use="required"/>
<xs:attribute name="sale" type="xs:boolean"/>
<xs:attribute name="size" type="xs:integer"/>
<xs:attribute name="model" type="xs:string"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
</xs:element>
А вот так это будет выглядеть в XML-примере:
<product coast="12000" sale="false" size="24" model="Asus">Монитор</product>
Но я считаю, что использование атрибутов, хоть и круто расширяет возможности XML относительно формата JSON, зато по факту ухудшает читаемость(не всегда и везде, но ухудшает), а также заведомо запрещает формировать JSON на основе схемы.
PS, да-да не смотря на то, что XSD используется в первую очередь для описания структуры сообщения/запроса в формате XML, но на самом деле на его основе можно также формировать и JSON. Ты по сути указываешь программе структуру документа – XSD, а далее говоришь в какой формат эту структуру зарендерить – XML или JSON.
#быстростатья часть 2
3 минуты
7 октября