mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-27 07:01:02 +03:00
Три навыка для работы с пакетами XDTO. Формат описания — обычная XSD, своего DSL нет: рутину снимает конвертер (локальные объявления префиксов dNpM на каждой ссылке, инвертированная кратность lowerBound/upperBound, фасеты атрибутами вместо дочерних элементов, обязательный порядок элементов верхнего уровня). То, чего XSD выразить не может — nillable у атрибута, qualified у свойства, «атрибут записан явно» — едет атрибутами из пространства имён модели XDTO по правилу «то же имя, что в Package.bin». Свойства объекта метаданных живут в xs:appinfo, поэтому пара decompile → compile замыкается без потерь. Инвариант bin → xsd → bin проверен побайтово на 760 пакетах выгрузок Бухгалтерии и ERP 8.3.24 (харнесс debug/xdto/roundtrip-corpus.mjs). Сборка из рукописной XSD проверена загрузкой в базу 8.3.24 — именно она вскрыла обязательный порядок import→property→valueType→objectType, невидимый для корпусной сверки: все выгрузки уже канонические. xdto-validate ловит два класса тихих дефектов, которые платформа не диагностирует: подмену неразрешённого чужого типа на xs:anyType при импорте XML-схемы и nillable у свойства-атрибута, теряемый экспортом схемы в Конфигураторе. Тесты: 18 снэпшот-кейсов на синтетических схемах (типовые конфигурации в репозиторий не тащим), паритет PS↔PY на общих эталонах. Раннер получил caseFiles — копирование файлов кейса в workDir для навыков с файловым, а не JSON входом. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
174 lines
10 KiB
Markdown
174 lines
10 KiB
Markdown
# Спецификация XDTO DSL — XML Schema как формат описания пакета
|
||
|
||
Навыки `/xdto-compile` (XSD → пакет) и `/xdto-decompile` (пакет → XSD) используют в качестве
|
||
формата описания **обычную XML-схему**. Отдельного DSL нет: XSD и модель XDTO выражают одно и
|
||
то же, различаясь синтаксисом и умолчаниями, а схема в реальных задачах обычно уже есть —
|
||
прислана контрагентом.
|
||
|
||
> Формат самих исходников (`Package.bin`, объект метаданных, схема префиксов) —
|
||
> [1c-xdto-spec.md](1c-xdto-spec.md).
|
||
|
||
## Пример
|
||
|
||
```xml
|
||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||
xmlns:tns="urn:1C.ru:ObmenSBankom"
|
||
targetNamespace="urn:1C.ru:ObmenSBankom"
|
||
elementFormDefault="qualified">
|
||
<xs:simpleType name="СуммаТип">
|
||
<xs:restriction base="xs:decimal">
|
||
<xs:totalDigits value="18"/>
|
||
<xs:fractionDigits value="2"/>
|
||
</xs:restriction>
|
||
</xs:simpleType>
|
||
|
||
<xs:complexType name="Платёж">
|
||
<xs:sequence>
|
||
<xs:element name="Дата" type="xs:date"/>
|
||
<xs:element name="Сумма" type="tns:СуммаТип"/>
|
||
<xs:element name="Назначение" type="xs:string" minOccurs="0"/>
|
||
</xs:sequence>
|
||
<xs:attribute name="Номер" type="xs:string"/>
|
||
</xs:complexType>
|
||
</xs:schema>
|
||
```
|
||
|
||
---
|
||
|
||
## 1. Таблица соответствий
|
||
|
||
| XML Schema | Модель XDTO |
|
||
|---|---|
|
||
| `xs:schema/@targetNamespace` | `package/@targetNamespace` |
|
||
| `elementFormDefault="qualified"` | `elementFormQualified="true"` |
|
||
| `attributeFormDefault="qualified"` | `attributeFormQualified="true"` |
|
||
| `xs:import/@namespace` | `import/@namespace` |
|
||
| `xs:complexType` | `objectType` |
|
||
| `xs:simpleType` | `valueType` |
|
||
| `xs:element` (глобальный) | `property` в `package` |
|
||
| `xs:attribute` (глобальный) | `property form="Attribute"` в `package` |
|
||
| `xs:element` (локальный) | `property` |
|
||
| `xs:attribute` (локальный) | `property form="Attribute"` |
|
||
| `@minOccurs` | `@lowerBound` |
|
||
| `@maxOccurs="unbounded"` | `@upperBound="-1"` |
|
||
| `@nillable`, `@default`, `@fixed` | те же имена |
|
||
| `xs:element/@ref` | `property/@ref` |
|
||
| анонимный `xs:simpleType` в объявлении | `typeDef xsi:type="ValueType"` |
|
||
| анонимный `xs:complexType` в объявлении | `typeDef xsi:type="ObjectType"` |
|
||
| `xs:complexContent/xs:extension/@base` | `objectType/@base` |
|
||
| `@abstract="true"`, `@mixed="true"` | те же имена |
|
||
| `xs:choice` | `ordered="false"` |
|
||
| `xs:sequence` | порядок по умолчанию |
|
||
| `xs:any` + `xs:anyAttribute` | `open="true"` |
|
||
| `xs:simpleContent/xs:extension/@base` | свойство `__content` с `form="Text"` |
|
||
| `xs:restriction/@base` + дочерние фасеты | `@base` + фасеты **атрибутами** |
|
||
| `xs:pattern`, `xs:enumeration` | `<pattern>`, `<enumeration>` — значение в тексте узла |
|
||
| `xs:list/@itemType` | `variety="List"` + `@itemType` |
|
||
| `xs:union/@memberTypes` | `variety="Union"` + `@memberTypes` |
|
||
|
||
Ловушки, на которых модель ошибается чаще всего:
|
||
|
||
- **Кратность инвертирована по смыслу**: `lowerBound="0"` = необязательный, `upperBound="-1"` = неограниченный.
|
||
- **Фасеты в XDTO — атрибуты**, а не дочерние элементы: `maxLength="30"`, не `<xs:maxLength value="30"/>`.
|
||
- **Каждая ссылка на тип требует локального объявления префикса** `dNpM` — в том числе на
|
||
собственный `targetNamespace`.
|
||
|
||
Всё это делает компилятор; писать вручную ничего из перечисленного не нужно.
|
||
|
||
---
|
||
|
||
## 2. Аннотации `xdto:`
|
||
|
||
Две вещи XDTO выражает, а XML Schema — нет:
|
||
|
||
- `nillable` у атрибута (спецификация XSD допускает его только у элементов);
|
||
- `qualified` у отдельного свойства.
|
||
|
||
Плюс XSD не различает «атрибут записан явно» и «атрибут опущен, действует умолчание»,
|
||
хотя в реальных пакетах встречаются оба написания одного смысла.
|
||
|
||
Такие случаи описываются атрибутами из пространства имён самой модели XDTO —
|
||
`http://v8.1c.ru/8.1/xdto`. Правило одно:
|
||
|
||
> **Чего XSD сказать не может — пиши атрибутом `xdto:` с тем же именем, что в `Package.bin`.**
|
||
|
||
```xml
|
||
<xs:attribute name="Представление" type="xs:string"
|
||
xmlns:xdto="http://v8.1c.ru/8.1/xdto" xdto:nillable="true"/>
|
||
```
|
||
|
||
Такая схема остаётся валидной: XML Schema разрешает атрибуты из чужих пространств имён
|
||
на объявлениях (`anyAttribute namespace="##other"` в схеме схем). Валидаторы их игнорируют.
|
||
|
||
Аннотации строго опциональны — подавляющее большинство схем обходится без единой.
|
||
|
||
| Аннотация | Где | Назначение |
|
||
|---|---|---|
|
||
| `xdto:nillable` | `xs:attribute` | `nillable` у свойства-атрибута |
|
||
| `xdto:lowerBound`, `xdto:upperBound` | `xs:attribute` | кратность свойства-атрибута |
|
||
| `xdto:qualified` | объявление | переопределение `*FormQualified` |
|
||
| `xdto:form` | `xs:element` | записать `form` явно (например `form="Element"`) |
|
||
| `xdto:name` | объявление | имя свойства, если XML-имя не является идентификатором 1С; тогда XML-имя уходит в `localName` |
|
||
| `xdto:variety` | `xs:restriction`, `xs:list`, `xs:union` | записать `variety` явно |
|
||
| `xdto:memberTypesForm="prefixed"` | `xs:union` | писать `memberTypes` префиксами, а не нотацией Кларка |
|
||
| `xdto:open`, `xdto:abstract`, `xdto:mixed`, `xdto:ordered`, `xdto:sequenced` | `xs:complexType` | значения, не выводимые из модели содержимого |
|
||
| `xdto:order` | `xs:complexType` | исходный порядок свойств, если он не «атрибуты первыми»; имена через `\|` |
|
||
| `xdto:textName`, `xdto:textlowerBound`, `xdto:textupperBound`, `xdto:textnillable` | `xs:extension` в `xs:simpleContent` | параметры свойства `form="Text"`, если оно названо не `__content` |
|
||
| `xdto:elementFormQualified`, `xdto:attributeFormQualified` | `xs:schema` | записать флаги явно |
|
||
| `xdto:type` | `xs:enumeration` | `xsi:type` литерала перечисления |
|
||
| `xdto:prefix` | объявление | осмысленный префикс пространства имён вместо генерируемого `dNpM` (например `dcsset`) |
|
||
|
||
### Что выводится само
|
||
|
||
Аннотация нужна только там, где вывод невозможен:
|
||
|
||
| Свойство XDTO | Выводится из |
|
||
|---|---|
|
||
| `open="true"` | наличие `xs:any` / `xs:anyAttribute` |
|
||
| `ordered="false"` | `xs:choice` вместо `xs:sequence` |
|
||
| `abstract`, `mixed` | одноимённые атрибуты `xs:complexType` |
|
||
| `variety="List"` / `"Union"` | `xs:list` / `xs:union` |
|
||
| порядок свойств | атрибуты первыми, затем остальные |
|
||
|
||
`sequenced` из XSD не выводится (в корпусе он не коррелирует однозначно ни с одной
|
||
конструкцией) и всегда приходит аннотацией.
|
||
|
||
---
|
||
|
||
## 3. Свойства объекта метаданных
|
||
|
||
`Name`, `Synonym` и `Comment` живут в `xs:annotation/xs:appinfo` — штатном месте XML Schema
|
||
для инструментальных метаданных. `Namespace` не дублируется: его единственный источник —
|
||
`targetNamespace`.
|
||
|
||
```xml
|
||
<xs:annotation>
|
||
<xs:appinfo>
|
||
<xdto:package xmlns:xdto="http://v8.1c.ru/8.1/xdto">
|
||
<xdto:name>ОбменСБанком</xdto:name>
|
||
<xdto:synonym lang="ru">Обмен с банком</xdto:synonym>
|
||
<xdto:comment>Формат 1С:Предприятие — Клиент банка</xdto:comment>
|
||
</xdto:package>
|
||
</xs:appinfo>
|
||
</xs:annotation>
|
||
```
|
||
|
||
Блок опционален. Параметры `-Name`, `-Synonym`, `-Comment` навыка `/xdto-compile`
|
||
имеют приоритет над ним. Без того и другого имя берётся из имени файла XSD.
|
||
|
||
Благодаря этому блоку пара `/xdto-decompile` → `/xdto-compile` замыкается без потерь,
|
||
включая свойства объекта метаданных.
|
||
|
||
---
|
||
|
||
## 4. Прощающий ввод
|
||
|
||
Компилятор принимает и не вполне канонические схемы:
|
||
|
||
- **Имя типа без префикса** (`type="Платёж"`) трактуется как тип целевого пространства имён.
|
||
- **`form="qualified"` на глобальном объявлении** — так экспортирует XML-схему сам
|
||
Конфигуратор, хотя спецификация XSD допускает `form` только у локальных объявлений.
|
||
Такие файлы читаются; сам навык пишет корректно.
|
||
- **`xs:include`** игнорируется (в модели XDTO соответствия нет).
|
||
- Порядок объявлений верхнего уровня произвольный и сохраняется как есть.
|