Почему порядок элементов в XML-файле важен для схем xs:sequence в 1С EnterpriseData и какие есть альтернативы?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с интеграцией данных в системах 1С, особенно через стандарт EnterpriseData, мы часто сталкиваемся с XML-схемами (XSD), которые определяют структуру передаваемых данных. Одним из ключевых элементов в этих схемах является xs:sequence. Давайте подробно рассмотрим, почему порядок элементов в XML-файле становится критически важным при использовании этого элемента в схеме, и какие существуют альтернативы, а также причины выбора именно xs:sequence.

Понимание элемента xs:sequence и его влияние на порядок элементов

Предположим, мы имеем следующую XSD схему для раздела оплаты платежными картами, как это было предложено в исходном сообщении:


<xs:complexType name="ОплатаПлатежнымиКартами.Строка">
    <xs:sequence>
        <xs:element name="СуммаОплаты" type="tns:ТипСумма"/>
        <xs:element name="ВидКарты" type="xs:string" minOccurs="0"/>
        <xs:element name="НомерКарты" type="xs:string"/>
        <xs:element name="Эквайрер" type="tns:КлючевыеСвойстваКонтрагент" minOccurs="0"/>
        <xs:element name="ДоговорЭквайринга" type="tns:КлючевыеСвойстваДоговор" minOccurs="0"/>
        <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:anyAttribute namespace="##any" processContents="lax"/>
</xs:complexType>

В этой схеме ключевым элементом является <xs:sequence>. Он явно указывает, что дочерние элементы, перечисленные внутри него (СуммаОплаты, ВидКарты, НомерКарты и так далее), должны располагаться в XML-документе строго в том порядке, в котором они объявлены в схеме. Если мы нарушим этот порядок, например, попытаемся поставить ВидКарты перед СуммаОплаты, то при валидации XML-документа по данной XSD схеме мы получим ошибку. Это подтверждает правильность первоначального понимания автора сообщения.

Таким образом, если в XML-документе сначала будет идти элемент ВидКарты, а затем СуммаОплаты, хотя в схеме они определены в обратном порядке, система валидации, использующая эту XSD, сообщит об ошибке. Этот строгий порядок является фундаментальным свойством xs:sequence.

Обратите внимание на атрибуты minOccurs и maxOccurs. Они определяют количество вхождений элемента. Например, minOccurs="0" означает, что элемент может отсутствовать, а maxOccurs="unbounded" (как для xs:any в нашем примере) позволяет элементу повторяться неограниченное количество раз.

Альтернативы xs:sequence: xs:all и xs:choice

Возникает логичный вопрос: а нельзя ли было использовать такую конструкцию XSD, которая не требовала бы строгого порядка элементов? Да, такие композиторы существуют:

  1. xs:all

    Элемент xs:all позволяет элементам в группе быть (или не быть) в любом порядке в составе родительского элемента. Он был бы идеальным решением для сценариев, где порядок не важен. Например, если бы мы хотели, чтобы СуммаОплаты, ВидКарты и НомерКарты могли идти в любой последовательности.

    Однако, в широко используемом стандарте XSD 1.0, у xs:all есть существенные ограничения, которые делают его непригодным для многих реальных сценариев, особенно в EnterpriseData:

    • Каждый дочерний элемент внутри xs:all может встречаться только один раз. То есть, minOccurs может быть "0" или "1", а maxOccurs всегда должен быть "1". Это означает, что мы не можем определить повторяющиеся элементы (списки, табличные части) с помощью xs:all в XSD 1.0.
    • xs:all не может содержать другие композиторы (такие как xs:sequence или xs:choice) или элемент xs:any в качестве дочерних. В нашей схеме есть xs:any для дополнительных реквизитов, что сразу исключает использование xs:all в XSD 1.0.

    Эти ограничения были смягчены в XSD 1.1, где xs:all стал более гибким, позволяя maxOccurs больше "1" и включая xs:any. Однако поддержка XSD 1.1 не является повсеместной, и многие системы, включая 1С EnterpriseData, продолжают использовать XSD 1.0.

  2. xs:choice

    Элемент xs:choice позволяет использовать только один из дочерних элементов, перечисленных в его декларации. Это полезно, когда, например, поле может быть либо одним типом данных, либо другим, или если есть несколько возможных структур для одной и той же точки в схеме, но только одна из них может присутствовать. В нашем случае, когда все элементы (СуммаОплаты, ВидКарты, НомерКарты и т.д.) должны присутствовать (или могут отсутствовать), но не взаимоисключать друг друга, xs:choice не подходит.

Почему xs:sequence является прагматичным выбором для EnterpriseData

Учитывая ограничения xs:all в XSD 1.0, использование xs:sequence в EnterpriseData, несмотря на кажущуюся негибкость порядка, часто является наиболее практичным и обоснованным решением. Рассмотрим подробнее основные причины:

  1. Гибкость в определении количества вхождений

    В отличие от xs:all в XSD 1.0, xs:sequence позволяет каждому дочернему элементу иметь maxOccurs="unbounded" или любое другое значение, отличное от "1". Это критически важно для определения списков, табличных частей или коллекций элементов, где количество вхождений заранее не определено. В нашей схеме, элемент xs:any внутри xs:sequence имеет maxOccurs="unbounded", что позволяет включать любое количество дополнительных реквизитов.

  2. Простота реализации парсеров и валидаторов

    Валидация и парсинг XML-документов с использованием xs:sequence часто проще и быстрее для программного обеспечения. Когда порядок элементов строго задан, парсеру не требуется сложный алгоритм для определения всех возможных перестановок элементов. Это упрощает логику обработки и снижает вероятность ошибок при разработке интеграционных решений.

    Хотя для объектной модели XDTO в 1С порядок полей может казаться несущественным на уровне бизнес-логики (XDTO-объект загружается целиком, и доступ к его свойствам осуществляется по имени, а не по порядку), на низком уровне парсинга XML-файла и его валидации порядок, заданный xs:sequence, играет ключевую роль. Кроме XDTO, существуют и другие способы чтения XML, где порядок также может быть важен.

  3. Историческая совместимость и поддержка инструментами

    XSD 1.0 был стандартом в течение многих лет, и подавляющее большинство инструментов и библиотек XML-парсинга полностью поддерживают его ограничения. Выбор xs:sequence обеспечивает широкую совместимость с существующими платформами и упрощает взаимодействие между различными системами, использующими XSD 1.0.

  4. Читаемость и предсказуемость схемы

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

  5. Включение xs:any для расширяемости

    В приведенной схеме присутствует элемент <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>. Этот элемент позволяет включать любые XML-элементы из любых пространств имен в данную часть документа. Это очень важная функция для обеспечения расширяемости схемы, позволяющая добавлять "дополнительные реквизиты" или новые поля без изменения основной XSD. xs:any может быть легко включен в xs:sequence, что невозможно в xs:all по стандарту XSD 1.0.

    Атрибут processContents="lax" означает, что валидатор попытается валидировать элементы, указанные в xs:any, если он сможет найти подходящую схему для их пространства имен. Если схема не найдена, валидация будет продолжена без ошибок.

Заключение

Таким образом, выбор xs:sequence в схемах EnterpriseData, несмотря на его требование к строгому порядку элементов, является обоснованным решением. Он обусловлен комбинацией практических ограничений XSD 1.0 (особенно в отношении xs:all), необходимостью обеспечения гибкости в определении повторяющихся элементов (через maxOccurs) и расширяемости (через xs:any), а также упрощением разработки и тестирования интеграционных решений. Нарушение заданного порядка элементов в XML-документе при использовании xs:sequence неизбежно приведет к ошибкам валидации, что подтверждает важность соблюдения структуры, определенной в XSD.

← На главную