mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-03 10:10:21 +03:00
feat(meta-decompile,meta-compile): поддержка WebService и полнота его формата
meta-decompile не знал тип WebService — 18 сервисов УТ не проходили раундтрип.
Добавлен разбор (оба порта): namespace, состав XDTO-пакетов, дескриптор,
операции с параметрами.
Компилятор поддерживал тип поверхностно; раундтрип на реальных сервисах
показал, чего не хватало:
- XDTOPackages эмитился скаляром, а это СПИСОК элементов: ссылка на пакет
конфигурации (xr:MDObjectRef) либо URI внешнего пространства имён
(xs:string). Presentation пуст, CheckState 0 — 19/19 по корпусу;
- DescriptorFileName не эмитился вовсе, хотя есть у всех 18 сервисов и НЕ
выводится из имени (DMILService -> dmil.1cws) — нужен явный ключ;
- DataLockControlMode не эмитился (Managed у всех 192 операций);
- Comment не эмитился ни у сервиса, ни у операций и параметров;
- типы из собственного пространства имён (81 случай) писались без локального
xmlns. В DSL задаются нотацией Кларка "{uri}ИмяТипа", компилятор объявляет
xmlns сам — как это делает платформа.
Nillable захватывается явно у операций и параметров: по корпусу значения
смешанные (операции 103/89, параметры 128/395), дефолт угадать нельзя.
Порядок операций и параметров приведён к порядку DSL в обоих портах — PS шёл
в порядке хеш-таблицы, py сортировал.
Проверка: 25 сервисов УТ (18 WebService + 7 HTTPService) 25/25 без
расхождений; JSON декомпилятора побайтово совпадает у PS и py на всех 25;
сюита 76/76 на обоих портах; 1С-сертификация обоих кейсов пройдена.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
01c45581ef
commit
87f97e986a
@@ -7,16 +7,21 @@
|
||||
| Ключ | Умолчание | Значения |
|
||||
|------|-----------|----------|
|
||||
| `rootURL` | `= name` (в нижнем регистре) | корневой URL |
|
||||
| `reuseSessions` | `DontUse` | `DontUse` / `AutoUse` |
|
||||
| `reuseSessions` | `DontUse` | `DontUse` / `Use` / `AutoUse` |
|
||||
| `sessionMaxAge` | `20` | время жизни сессии, сек |
|
||||
| `urlTemplates` | `{}` | шаблоны URL (см. ниже) |
|
||||
|
||||
`urlTemplates` — объект `{ "ИмяШаблона": def }`, где `def`:
|
||||
- строка — URL-путь без методов: `"/health"`;
|
||||
- объект: `template` (путь с параметрами `{id}`, по умолчанию `/имяшаблона`), `methods` — `{ "ИмяМетода": "HTTPMethod" }`.
|
||||
- объект: `template` (путь с параметрами `{id}`, по умолчанию `/имяшаблона`), `synonym`, `comment`,
|
||||
`methods` — `{ "ИмяМетода": def }`.
|
||||
|
||||
`methods` — значение либо строка (только HTTP-метод), либо объект: `httpMethod`, `handler`,
|
||||
`synonym`, `comment`.
|
||||
|
||||
HTTP-методы: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `CONNECT`, `TRACE`, `MERGE`.
|
||||
Обработчик метода в модуле именуется `{ИмяШаблона}{ИмяМетода}`.
|
||||
Обработчик по умолчанию именуется `{ИмяШаблона}{ИмяМетода}`; в типовых конфигурациях он часто
|
||||
произвольный — тогда задавайте `handler` явно.
|
||||
|
||||
```json
|
||||
{ "type": "HTTPService", "name": "API", "rootURL": "api",
|
||||
@@ -31,21 +36,29 @@ HTTP-методы: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `
|
||||
| Ключ | Умолчание | Значения |
|
||||
|------|-----------|----------|
|
||||
| `namespace` | пусто | URI пространства имён WSDL |
|
||||
| `xdtoPackages` | пусто | XDTO-пакеты |
|
||||
| `reuseSessions` | `DontUse` | `DontUse` / `AutoUse` |
|
||||
| `xdtoPackages` | пусто | список пакетов (см. ниже) |
|
||||
| `descriptorFileName` | `= name` + `.1cws` | имя файла дескриптора |
|
||||
| `reuseSessions` | `DontUse` | `DontUse` / `Use` / `AutoUse` |
|
||||
| `sessionMaxAge` | `20` | время жизни сессии, сек |
|
||||
| `operations` | `{}` | операции (см. ниже) |
|
||||
|
||||
`xdtoPackages` — **массив** значений: `"XDTOPackage.Имя"` — пакет конфигурации, любое другое
|
||||
значение — URI внешнего пространства имён (например `"http://v8.1c.ru/8.3/data/ext"`).
|
||||
|
||||
`operations` — объект `{ "ИмяОперации": def }`, где `def`:
|
||||
- строка — XDTO-тип возврата без параметров: `"xs:string"`;
|
||||
- объект: `returnType` (по умолчанию `xs:string`), `nillable` (bool), `transactioned` (bool),
|
||||
`handler` (имя процедуры, по умолчанию = имя операции), `parameters`.
|
||||
`procedureName` (имя процедуры, по умолчанию = имя операции; синоним ключа — `handler`),
|
||||
`dataLockControlMode` (по умолчанию `Managed`), `synonym`, `comment`, `parameters`.
|
||||
|
||||
`parameters` — объект `{ "ИмяПараметра": def }`, где `def`:
|
||||
- строка — XDTO-тип (`direction` = `In`);
|
||||
- объект: `type` (по умолчанию `xs:string`), `nillable` (bool, по умолчанию `true`), `direction` (`In` / `Out` / `InOut`).
|
||||
- объект: `type` (по умолчанию `xs:string`), `nillable` (bool, по умолчанию `true`),
|
||||
`direction` (`In` / `Out` / `InOut`), `synonym`, `comment`.
|
||||
|
||||
XDTO-типы: `xs:string`, `xs:boolean`, `xs:int`, `xs:long`, `xs:decimal`, `xs:dateTime`, `xs:base64Binary`.
|
||||
Тип из собственного пространства имён задаётся в нотации Кларка — `"{http://ваш.uri}ИмяТипа"`;
|
||||
компилятор сам объявит локальный `xmlns` в теге, как это делает платформа.
|
||||
|
||||
```json
|
||||
{ "type": "WebService", "name": "DataExchange", "namespace": "http://www.1c.ru/DataExchange",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-compile v1.71 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.72 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -3812,19 +3812,51 @@ function Emit-HTTPServiceProperties {
|
||||
X "$i<SessionMaxAge>$sessionMaxAge</SessionMaxAge>"
|
||||
}
|
||||
|
||||
# XDTO-тип значения: "{uri}Local" (нотация Кларка) → тег с ЛОКАЛЬНЫМ объявлением xmlns, как пишет
|
||||
# платформа (<XDTOValueType xmlns:d1p1="uri">d1p1:Local</...>). Простой "xs:string" — как есть.
|
||||
function Emit-XDTOType {
|
||||
param([string]$indent, [string]$tag, [string]$value)
|
||||
if ($value -match '^\{([^}]+)\}(.+)$') {
|
||||
$uri = $Matches[1]; $local = $Matches[2]
|
||||
X "$indent<$tag xmlns:d1p1=`"$(Esc-Xml $uri)`">d1p1:$(Esc-Xml $local)</$tag>"
|
||||
} else {
|
||||
X "$indent<$tag>$(Esc-Xml $value)</$tag>"
|
||||
}
|
||||
}
|
||||
|
||||
function Emit-WebServiceProperties {
|
||||
param([string]$indent)
|
||||
$i = $indent
|
||||
|
||||
X "$i<Name>$(Esc-Xml $objName)</Name>"
|
||||
Emit-MLText $i "Synonym" $synonym
|
||||
X "$i<Comment/>"
|
||||
if ($def.comment) { X "$i<Comment>$(Esc-Xml "$($def.comment)")</Comment>" } else { X "$i<Comment/>" }
|
||||
|
||||
$namespace = if ($def.namespace) { "$($def.namespace)" } else { "" }
|
||||
X "$i<Namespace>$(Esc-Xml $namespace)</Namespace>"
|
||||
|
||||
$xdtoPackages = if ($def.xdtoPackages) { "$($def.xdtoPackages)" } else { "" }
|
||||
if ($xdtoPackages) { X "$i<XDTOPackages>$xdtoPackages</XDTOPackages>" } else { X "$i<XDTOPackages/>" }
|
||||
# XDTOPackages — СПИСОК элементов, а не скаляр: значение либо ссылка на пакет конфигурации
|
||||
# (xr:MDObjectRef "XDTOPackage.Имя"), либо URI внешнего пространства имён (xs:string).
|
||||
# Presentation всегда пуст, CheckState всегда 0 (проверено на корпусе: 19/19).
|
||||
$pkgs = @()
|
||||
if ($def.xdtoPackages) { $pkgs = @($def.xdtoPackages) }
|
||||
if ($pkgs.Count -gt 0) {
|
||||
X "$i<XDTOPackages>"
|
||||
foreach ($p in $pkgs) {
|
||||
$pv = "$p"
|
||||
$xt = if ($pv -like 'XDTOPackage.*') { 'xr:MDObjectRef' } else { 'xs:string' }
|
||||
X "$i`t<xr:Item>"
|
||||
X "$i`t`t<xr:Presentation/>"
|
||||
X "$i`t`t<xr:CheckState>0</xr:CheckState>"
|
||||
X "$i`t`t<xr:Value xsi:type=`"$xt`">$(Esc-Xml $pv)</xr:Value>"
|
||||
X "$i`t</xr:Item>"
|
||||
}
|
||||
X "$i</XDTOPackages>"
|
||||
} else { X "$i<XDTOPackages/>" }
|
||||
|
||||
# Имя файла дескриптора не выводится из имени сервиса (DMILService → dmil.1cws) — только дефолт.
|
||||
$descriptor = if ($def.descriptorFileName) { "$($def.descriptorFileName)" } else { "$objName.1cws" }
|
||||
X "$i<DescriptorFileName>$(Esc-Xml $descriptor)</DescriptorFileName>"
|
||||
|
||||
$reuseSessions = Get-EnumProp "ReuseSessions" "reuseSessions" "DontUse"
|
||||
X "$i<ReuseSessions>$reuseSessions</ReuseSessions>"
|
||||
@@ -3952,7 +3984,10 @@ function Emit-Operation {
|
||||
$nillable = "false"
|
||||
$transactioned = "false"
|
||||
$handler = $opName
|
||||
$params = @{}
|
||||
$opComment = ""
|
||||
$dataLock = "Managed" # у всех 192 операций корпуса
|
||||
# [ordered]: порядок параметров — как в DSL (он же порядок исходного XML).
|
||||
$params = [ordered]@{}
|
||||
|
||||
if ($opDef -is [string]) {
|
||||
$returnType = "$opDef"
|
||||
@@ -3961,6 +3996,10 @@ function Emit-Operation {
|
||||
if ($opDef.nillable -eq $true) { $nillable = "true" }
|
||||
if ($opDef.transactioned -eq $true) { $transactioned = "true" }
|
||||
if ($opDef.handler) { $handler = "$($opDef.handler)" }
|
||||
if ($opDef.procedureName) { $handler = "$($opDef.procedureName)" }
|
||||
if ($opDef.synonym) { $opSynonym = "$($opDef.synonym)" }
|
||||
if ($opDef.comment) { $opComment = "$($opDef.comment)" }
|
||||
if ($opDef.dataLockControlMode) { $dataLock = "$($opDef.dataLockControlMode)" }
|
||||
if ($opDef.parameters) {
|
||||
$opDef.parameters.PSObject.Properties | ForEach-Object {
|
||||
$params[$_.Name] = $_.Value
|
||||
@@ -3972,11 +4011,12 @@ function Emit-Operation {
|
||||
X "$indent`t<Properties>"
|
||||
X "$indent`t`t<Name>$(Esc-Xml $opName)</Name>"
|
||||
Emit-MLText "$indent`t`t" "Synonym" $opSynonym
|
||||
X "$indent`t`t<Comment/>"
|
||||
X "$indent`t`t<XDTOReturningValueType>$returnType</XDTOReturningValueType>"
|
||||
if ($opComment) { X "$indent`t`t<Comment>$(Esc-Xml $opComment)</Comment>" } else { X "$indent`t`t<Comment/>" }
|
||||
Emit-XDTOType "$indent`t`t" "XDTOReturningValueType" $returnType
|
||||
X "$indent`t`t<Nillable>$nillable</Nillable>"
|
||||
X "$indent`t`t<Transactioned>$transactioned</Transactioned>"
|
||||
X "$indent`t`t<ProcedureName>$(Esc-Xml $handler)</ProcedureName>"
|
||||
X "$indent`t`t<DataLockControlMode>$dataLock</DataLockControlMode>"
|
||||
X "$indent`t</Properties>"
|
||||
|
||||
if ($params.Count -gt 0) {
|
||||
@@ -3988,6 +4028,7 @@ function Emit-Operation {
|
||||
$paramType = "xs:string"
|
||||
$paramNillable = "true"
|
||||
$paramDir = "In"
|
||||
$paramComment = ""
|
||||
|
||||
if ($paramDef -is [string]) {
|
||||
$paramType = "$paramDef"
|
||||
@@ -3995,13 +4036,16 @@ function Emit-Operation {
|
||||
if ($paramDef.type) { $paramType = "$($paramDef.type)" }
|
||||
if ($paramDef.nillable -eq $false) { $paramNillable = "false" }
|
||||
if ($paramDef.direction) { $paramDir = "$($paramDef.direction)" }
|
||||
if ($paramDef.synonym) { $paramSynonym = "$($paramDef.synonym)" }
|
||||
if ($paramDef.comment) { $paramComment = "$($paramDef.comment)" }
|
||||
}
|
||||
|
||||
X "$indent`t`t<Parameter uuid=`"$paramUuid`">"
|
||||
X "$indent`t`t`t<Properties>"
|
||||
X "$indent`t`t`t`t<Name>$(Esc-Xml $paramName)</Name>"
|
||||
Emit-MLText "$indent`t`t`t`t" "Synonym" $paramSynonym
|
||||
X "$indent`t`t`t`t<XDTOValueType>$paramType</XDTOValueType>"
|
||||
if ($paramComment) { X "$indent`t`t`t`t<Comment>$(Esc-Xml $paramComment)</Comment>" } else { X "$indent`t`t`t`t<Comment/>" }
|
||||
Emit-XDTOType "$indent`t`t`t`t" "XDTOValueType" $paramType
|
||||
X "$indent`t`t`t`t<Nillable>$paramNillable</Nillable>"
|
||||
X "$indent`t`t`t`t<TransferDirection>$paramDir</TransferDirection>"
|
||||
X "$indent`t`t`t</Properties>"
|
||||
@@ -4408,7 +4452,8 @@ if ($objType -eq "HTTPService") {
|
||||
|
||||
# --- WebService: Operations ---
|
||||
if ($objType -eq "WebService") {
|
||||
$operations = @{}
|
||||
# [ordered]: порядок операций — как в DSL (он же порядок исходного XML).
|
||||
$operations = [ordered]@{}
|
||||
if ($def.operations) {
|
||||
$def.operations.PSObject.Properties | ForEach-Object {
|
||||
$operations[$_.Name] = $_.Value
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-compile v1.71 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.72 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -3737,18 +3737,44 @@ def emit_http_service_properties(indent):
|
||||
session_max_age = str(defn['sessionMaxAge']) if defn.get('sessionMaxAge') is not None else '20'
|
||||
X(f'{i}<SessionMaxAge>{session_max_age}</SessionMaxAge>')
|
||||
|
||||
def emit_xdto_type(indent, tag, value):
|
||||
"""XDTO-тип значения: "{uri}Local" (нотация Кларка) -> тег с ЛОКАЛЬНЫМ объявлением xmlns,
|
||||
как пишет платформа. Простой "xs:string" — как есть."""
|
||||
m = re.match(r'^\{([^}]+)\}(.+)$', value or '')
|
||||
if m:
|
||||
X(f'{indent}<{tag} xmlns:d1p1="{esc_xml(m.group(1))}">d1p1:{esc_xml(m.group(2))}</{tag}>')
|
||||
else:
|
||||
X(f'{indent}<{tag}>{esc_xml(value)}</{tag}>')
|
||||
|
||||
|
||||
def emit_web_service_properties(indent):
|
||||
i = indent
|
||||
X(f'{i}<Name>{esc_xml(obj_name)}</Name>')
|
||||
emit_mltext(i, 'Synonym', synonym)
|
||||
X(f'{i}<Comment/>')
|
||||
X(f'{i}<Comment>{esc_xml(str(defn["comment"]))}</Comment>' if defn.get('comment') else f'{i}<Comment/>')
|
||||
namespace = str(defn['namespace']) if defn.get('namespace') else ''
|
||||
X(f'{i}<Namespace>{esc_xml(namespace)}</Namespace>')
|
||||
xdto_packages = str(defn['xdtoPackages']) if defn.get('xdtoPackages') else ''
|
||||
if xdto_packages:
|
||||
X(f'{i}<XDTOPackages>{xdto_packages}</XDTOPackages>')
|
||||
# XDTOPackages — СПИСОК элементов: ссылка на пакет конфигурации (xr:MDObjectRef) либо URI
|
||||
# внешнего пространства имён (xs:string). Presentation пуст, CheckState 0 (корпус: 19/19).
|
||||
pkgs = defn.get('xdtoPackages') or []
|
||||
if not isinstance(pkgs, list):
|
||||
pkgs = [pkgs]
|
||||
if pkgs:
|
||||
X(f'{i}<XDTOPackages>')
|
||||
for p in pkgs:
|
||||
pv = str(p)
|
||||
xt = 'xr:MDObjectRef' if pv.startswith('XDTOPackage.') else 'xs:string'
|
||||
X(f'{i}\t<xr:Item>')
|
||||
X(f'{i}\t\t<xr:Presentation/>')
|
||||
X(f'{i}\t\t<xr:CheckState>0</xr:CheckState>')
|
||||
X(f'{i}\t\t<xr:Value xsi:type="{xt}">{esc_xml(pv)}</xr:Value>')
|
||||
X(f'{i}\t</xr:Item>')
|
||||
X(f'{i}</XDTOPackages>')
|
||||
else:
|
||||
X(f'{i}<XDTOPackages/>')
|
||||
# Имя файла дескриптора не выводится из имени сервиса (DMILService -> dmil.1cws) — только дефолт.
|
||||
descriptor = str(defn['descriptorFileName']) if defn.get('descriptorFileName') else f'{obj_name}.1cws'
|
||||
X(f'{i}<DescriptorFileName>{esc_xml(descriptor)}</DescriptorFileName>')
|
||||
reuse_sessions = get_enum_prop('ReuseSessions', 'reuseSessions', 'DontUse')
|
||||
X(f'{i}<ReuseSessions>{reuse_sessions}</ReuseSessions>')
|
||||
session_max_age = str(defn['sessionMaxAge']) if defn.get('sessionMaxAge') is not None else '20'
|
||||
@@ -3858,6 +3884,8 @@ def emit_operation(indent, op_name, op_def):
|
||||
nillable = 'false'
|
||||
transactioned = 'false'
|
||||
handler = op_name
|
||||
op_comment = ''
|
||||
data_lock = 'Managed' # у всех 192 операций корпуса
|
||||
params = {}
|
||||
if isinstance(op_def, str):
|
||||
return_type = op_def
|
||||
@@ -3870,6 +3898,14 @@ def emit_operation(indent, op_name, op_def):
|
||||
transactioned = 'true'
|
||||
if op_def.get('handler'):
|
||||
handler = str(op_def['handler'])
|
||||
if op_def.get('procedureName'):
|
||||
handler = str(op_def['procedureName'])
|
||||
if op_def.get('synonym'):
|
||||
op_synonym = str(op_def['synonym'])
|
||||
if op_def.get('comment'):
|
||||
op_comment = str(op_def['comment'])
|
||||
if op_def.get('dataLockControlMode'):
|
||||
data_lock = str(op_def['dataLockControlMode'])
|
||||
if op_def.get('parameters'):
|
||||
for k, v in op_def['parameters'].items():
|
||||
params[k] = v
|
||||
@@ -3877,20 +3913,23 @@ def emit_operation(indent, op_name, op_def):
|
||||
X(f'{indent}\t<Properties>')
|
||||
X(f'{indent}\t\t<Name>{esc_xml(op_name)}</Name>')
|
||||
emit_mltext(f'{indent}\t\t', 'Synonym', op_synonym)
|
||||
X(f'{indent}\t\t<Comment/>')
|
||||
X(f'{indent}\t\t<XDTOReturningValueType>{return_type}</XDTOReturningValueType>')
|
||||
X(f'{indent}\t\t<Comment>{esc_xml(op_comment)}</Comment>' if op_comment else f'{indent}\t\t<Comment/>')
|
||||
emit_xdto_type(f'{indent}\t\t', 'XDTOReturningValueType', return_type)
|
||||
X(f'{indent}\t\t<Nillable>{nillable}</Nillable>')
|
||||
X(f'{indent}\t\t<Transactioned>{transactioned}</Transactioned>')
|
||||
X(f'{indent}\t\t<ProcedureName>{esc_xml(handler)}</ProcedureName>')
|
||||
X(f'{indent}\t\t<DataLockControlMode>{data_lock}</DataLockControlMode>')
|
||||
X(f'{indent}\t</Properties>')
|
||||
if params:
|
||||
X(f'{indent}\t<ChildObjects>')
|
||||
for param_name, param_def in sorted(params.items()):
|
||||
# Порядок — как в DSL (он же порядок исходного XML), а не отсортированный.
|
||||
for param_name, param_def in params.items():
|
||||
param_uuid = new_uuid()
|
||||
param_synonym = split_camel_case(param_name)
|
||||
param_type = 'xs:string'
|
||||
param_nillable = 'true'
|
||||
param_dir = 'In'
|
||||
param_comment = ''
|
||||
if isinstance(param_def, str):
|
||||
param_type = param_def
|
||||
else:
|
||||
@@ -3900,11 +3939,16 @@ def emit_operation(indent, op_name, op_def):
|
||||
param_nillable = 'false'
|
||||
if param_def.get('direction'):
|
||||
param_dir = str(param_def['direction'])
|
||||
if param_def.get('synonym'):
|
||||
param_synonym = str(param_def['synonym'])
|
||||
if param_def.get('comment'):
|
||||
param_comment = str(param_def['comment'])
|
||||
X(f'{indent}\t\t<Parameter uuid="{param_uuid}">')
|
||||
X(f'{indent}\t\t\t<Properties>')
|
||||
X(f'{indent}\t\t\t\t<Name>{esc_xml(param_name)}</Name>')
|
||||
emit_mltext(f'{indent}\t\t\t\t', 'Synonym', param_synonym)
|
||||
X(f'{indent}\t\t\t\t<XDTOValueType>{param_type}</XDTOValueType>')
|
||||
X(f'{indent}\t\t\t\t<Comment>{esc_xml(param_comment)}</Comment>' if param_comment else f'{indent}\t\t\t\t<Comment/>')
|
||||
emit_xdto_type(f'{indent}\t\t\t\t', 'XDTOValueType', param_type)
|
||||
X(f'{indent}\t\t\t\t<Nillable>{param_nillable}</Nillable>')
|
||||
X(f'{indent}\t\t\t\t<TransferDirection>{param_dir}</TransferDirection>')
|
||||
X(f'{indent}\t\t\t</Properties>')
|
||||
@@ -4297,7 +4341,8 @@ if obj_type == 'WebService':
|
||||
if operations:
|
||||
has_children = True
|
||||
X('\t\t<ChildObjects>')
|
||||
for op_name in sorted(op_order):
|
||||
# Порядок — как в DSL (он же порядок исходного XML), а не отсортированный.
|
||||
for op_name in op_order:
|
||||
emit_operation('\t\t\t', op_name, operations[op_name])
|
||||
X('\t\t</ChildObjects>')
|
||||
else:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-decompile v0.57 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# meta-decompile v0.58 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
#
|
||||
# Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document,
|
||||
@@ -92,7 +92,7 @@ foreach ($c in $rootEl.ChildNodes) { if ($c.NodeType -eq 'Element') { $objNode =
|
||||
if (-not $objNode) { [Console]::Error.WriteLine("meta-decompile: пустой MetaDataObject"); exit 3 }
|
||||
$objType = $objNode.LocalName
|
||||
|
||||
if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption', 'DocumentJournal', 'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage', 'CommonModule', 'EventSubscription', 'ScheduledJob', 'CommonForm', 'SessionParameter', 'CommonCommand', 'CommandGroup', 'CommonAttribute', 'FunctionalOptionsParameter', 'WSReference', 'CommonPicture', 'CommonTemplate', 'HTTPService')) {
|
||||
if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption', 'DocumentJournal', 'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage', 'CommonModule', 'EventSubscription', 'ScheduledJob', 'CommonForm', 'SessionParameter', 'CommonCommand', 'CommandGroup', 'CommonAttribute', 'FunctionalOptionsParameter', 'WSReference', 'CommonPicture', 'CommonTemplate', 'HTTPService', 'WebService')) {
|
||||
[Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (…, CommonPicture, CommonTemplate)"); exit 3
|
||||
}
|
||||
|
||||
@@ -781,6 +781,34 @@ if ($objType -eq 'CommonCommand') {
|
||||
Add-BoolProp 'modifiesData' 'ModifiesData' $false
|
||||
Add-EnumProp 'onMainServerUnavalableBehavior' 'OnMainServerUnavalableBehavior' 'Auto'
|
||||
}
|
||||
# XDTO-тип из элемента: если значение с префиксом (d6p1:Local) — разворачиваем префикс в URI и
|
||||
# отдаём в нотации Кларка "{uri}Local"; префиксы платформы (dNpM) произвольны и переносу не подлежат.
|
||||
function Get-XDTOTypeValue {
|
||||
param($node)
|
||||
if (-not $node) { return $null }
|
||||
$txt = $node.InnerText
|
||||
if ($txt -match '^([\w.-]+):(.+)$') {
|
||||
$prefix = $Matches[1]; $local = $Matches[2]
|
||||
$uri = $node.GetNamespaceOfPrefix($prefix)
|
||||
# xs: и прочие стандартные оставляем как есть — компилятор их пишет дословно.
|
||||
if ($uri -and $prefix -notin @('xs','xsi','v8','xr')) { return "{$uri}$local" }
|
||||
}
|
||||
return $txt
|
||||
}
|
||||
# WebService — пространство имён, состав XDTO-пакетов, дескриптор, операции с параметрами.
|
||||
if ($objType -eq 'WebService') {
|
||||
$ns = P 'Namespace'; if ($ns) { $dsl['namespace'] = $ns }
|
||||
$pkgNodes = @($props.SelectNodes('md:XDTOPackages/xr:Item/xr:Value', $nsm))
|
||||
if ($pkgNodes.Count -gt 0) {
|
||||
$pkgs = [System.Collections.ArrayList]@()
|
||||
foreach ($pn in $pkgNodes) { [void]$pkgs.Add($pn.InnerText) }
|
||||
$dsl['xdtoPackages'] = $pkgs
|
||||
}
|
||||
$dfn = P 'DescriptorFileName'
|
||||
if ($dfn -and $dfn -cne "$objName.1cws") { $dsl['descriptorFileName'] = $dfn }
|
||||
Add-EnumProp 'reuseSessions' 'ReuseSessions' 'DontUse'
|
||||
Add-IntProp 'sessionMaxAge' 'SessionMaxAge' 20
|
||||
}
|
||||
# HTTPService — корневой URL, повторное использование сеансов, время жизни сеанса.
|
||||
# Шаблоны URL с методами разбираются в блоке ChildObjects.
|
||||
if ($objType -eq 'HTTPService') {
|
||||
@@ -1129,6 +1157,56 @@ if ($saNode) {
|
||||
# --- ChildObjects: Attributes + TabularSections ---
|
||||
$childObjs = $objNode.SelectSingleNode('md:ChildObjects', $nsm)
|
||||
if ($childObjs) {
|
||||
# WebService: операции с параметрами. Строчное сокращение — только тип возврата (когда всё
|
||||
# остальное дефолтно); иначе объект с nillable/transactioned/procedureName/параметрами.
|
||||
$opNodes = @($childObjs.SelectNodes('md:Operation', $nsm))
|
||||
if ($opNodes.Count -gt 0) {
|
||||
$ops = [ordered]@{}
|
||||
foreach ($op in $opNodes) {
|
||||
$op_p = $op.SelectSingleNode('md:Properties', $nsm)
|
||||
$opName = ($op_p.SelectSingleNode('md:Name', $nsm)).InnerText
|
||||
$o = [ordered]@{}
|
||||
$rt = Get-XDTOTypeValue ($op_p.SelectSingleNode('md:XDTOReturningValueType', $nsm))
|
||||
if ($rt -and $rt -cne 'xs:string') { $o['returnType'] = $rt }
|
||||
$nil = $op_p.SelectSingleNode('md:Nillable', $nsm)
|
||||
if ($nil -and $nil.InnerText -eq 'true') { $o['nillable'] = $true }
|
||||
$tr = $op_p.SelectSingleNode('md:Transactioned', $nsm)
|
||||
if ($tr -and $tr.InnerText -eq 'true') { $o['transactioned'] = $true }
|
||||
$pn = $op_p.SelectSingleNode('md:ProcedureName', $nsm)
|
||||
if ($pn -and $pn.InnerText -cne $opName) { $o['procedureName'] = $pn.InnerText }
|
||||
$dl = $op_p.SelectSingleNode('md:DataLockControlMode', $nsm)
|
||||
if ($dl -and $dl.InnerText -cne 'Managed') { $o['dataLockControlMode'] = $dl.InnerText }
|
||||
$osyn = Get-MLValue ($op_p.SelectSingleNode('md:Synonym', $nsm))
|
||||
if ($null -ne $osyn -and "$osyn" -cne (Split-CamelWords $opName)) { $o['synonym'] = $osyn }
|
||||
$ocmt = $op_p.SelectSingleNode('md:Comment', $nsm)
|
||||
if ($ocmt -and $ocmt.InnerText) { $o['comment'] = $ocmt.InnerText }
|
||||
|
||||
$parNodes = @($op.SelectNodes('md:ChildObjects/md:Parameter', $nsm))
|
||||
if ($parNodes.Count -gt 0) {
|
||||
$pars = [ordered]@{}
|
||||
foreach ($par in $parNodes) {
|
||||
$pp = $par.SelectSingleNode('md:Properties', $nsm)
|
||||
$parName = ($pp.SelectSingleNode('md:Name', $nsm)).InnerText
|
||||
$po = [ordered]@{}
|
||||
$pt = Get-XDTOTypeValue ($pp.SelectSingleNode('md:XDTOValueType', $nsm))
|
||||
if ($pt) { $po['type'] = $pt }
|
||||
$pnil = $pp.SelectSingleNode('md:Nillable', $nsm)
|
||||
if ($pnil -and $pnil.InnerText -eq 'false') { $po['nillable'] = $false }
|
||||
$pdir = $pp.SelectSingleNode('md:TransferDirection', $nsm)
|
||||
if ($pdir -and $pdir.InnerText -cne 'In') { $po['direction'] = $pdir.InnerText }
|
||||
$psyn = Get-MLValue ($pp.SelectSingleNode('md:Synonym', $nsm))
|
||||
if ($null -ne $psyn -and "$psyn" -cne (Split-CamelWords $parName)) { $po['synonym'] = $psyn }
|
||||
$pcmt = $pp.SelectSingleNode('md:Comment', $nsm)
|
||||
if ($pcmt -and $pcmt.InnerText) { $po['comment'] = $pcmt.InnerText }
|
||||
# Только тип и дефолтное остальное → строчное сокращение.
|
||||
if ($po.Count -eq 1 -and $po.Contains('type')) { $pars[$parName] = $po['type'] } else { $pars[$parName] = $po }
|
||||
}
|
||||
$o['parameters'] = $pars
|
||||
}
|
||||
if ($o.Count -eq 1 -and $o.Contains('returnType')) { $ops[$opName] = $o['returnType'] } else { $ops[$opName] = $o }
|
||||
}
|
||||
$dsl['operations'] = $ops
|
||||
}
|
||||
# HTTPService: шаблоны URL и их методы. Шаблон — {template, methods{}}, метод — строка (только
|
||||
# HTTP-метод, когда обработчик совпадает с авто-выводом ИмяШаблона+ИмяМетода) либо объект.
|
||||
$tmplNodes = @($childObjs.SelectNodes('md:URLTemplate', $nsm))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-decompile v0.57 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# meta-decompile v0.58 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
#
|
||||
# Зеркало meta-decompile.ps1 (КАНОН). Структура 1:1 — те же имена функций, порядок, комментарии.
|
||||
@@ -58,6 +58,14 @@ def _text(node):
|
||||
return ''.join(node.itertext())
|
||||
|
||||
|
||||
def _ns_of_prefix(node, prefix):
|
||||
"""URI по префиксу — зеркало GetNamespaceOfPrefix из PS. lxml отдаёт nsmap с учётом
|
||||
унаследованных объявлений, поэтому локальный xmlns:dNpM на самом теге тоже виден."""
|
||||
if node is None:
|
||||
return None
|
||||
return node.nsmap.get(prefix)
|
||||
|
||||
|
||||
def _attr(node, name, ns=None):
|
||||
"""GetAttribute(name[, ns]) — .NET возвращает '' для отсутствующего атрибута, lxml → None."""
|
||||
if node is None:
|
||||
@@ -290,6 +298,25 @@ def get_type_shorthand(type_node):
|
||||
|
||||
|
||||
# Скалярное значение параметра выбора (<Value xsi:type=...>) → JSON-значение (bool/число/строка).
|
||||
def get_xdto_type_value(node):
|
||||
"""XDTO-тип: префиксное значение (d6p1:Local) -> нотация Кларка "{uri}Local".
|
||||
|
||||
Префиксы платформы (dNpM) произвольны и переносу не подлежат; стандартные (xs:, v8:, xr:)
|
||||
оставляем дословно — компилятор их так и пишет.
|
||||
"""
|
||||
if node is None:
|
||||
return None
|
||||
txt = _text(node)
|
||||
m = re.match(r'^([\w.\-]+):(.+)$', txt or '')
|
||||
if m:
|
||||
prefix, local = m.group(1), m.group(2)
|
||||
if prefix not in ('xs', 'xsi', 'v8', 'xr'):
|
||||
uri = _ns_of_prefix(node, prefix)
|
||||
if uri:
|
||||
return '{%s}%s' % (uri, local)
|
||||
return txt
|
||||
|
||||
|
||||
def convert_ch_scalar_node(vN):
|
||||
# nil-элемент массива (<v8:Value xsi:nil="true"/>) -> JSON null. Без этого он приезжал пустой
|
||||
# строкой и компилятор эмитил xs:string вместо nil.
|
||||
@@ -1191,6 +1218,26 @@ def build_dsl():
|
||||
get_picture_to_dsl(props, dsl)
|
||||
add_enum_prop('category', 'Category', 'NavigationPanel')
|
||||
# CommonCommand.
|
||||
# WebService — пространство имён, состав XDTO-пакетов, дескриптор.
|
||||
if obj_type == 'WebService':
|
||||
ns_ = P('Namespace')
|
||||
if ns_:
|
||||
dsl['namespace'] = ns_
|
||||
pkg_nodes = _nodes(props, 'md:XDTOPackages/xr:Item/xr:Value')
|
||||
if len(pkg_nodes) > 0:
|
||||
dsl['xdtoPackages'] = [_text(pn) for pn in pkg_nodes]
|
||||
dfn = P('DescriptorFileName')
|
||||
if dfn and dfn != f'{obj_name}.1cws':
|
||||
dsl['descriptorFileName'] = dfn
|
||||
add_enum_prop('reuseSessions', 'ReuseSessions', 'DontUse')
|
||||
add_int_prop('sessionMaxAge', 'SessionMaxAge', 20)
|
||||
# HTTPService — корневой URL, повторное использование сеансов, время жизни сеанса.
|
||||
if obj_type == 'HTTPService':
|
||||
ru = P('RootURL')
|
||||
if ru and ru != obj_name.lower():
|
||||
dsl['rootURL'] = ru
|
||||
add_enum_prop('reuseSessions', 'ReuseSessions', 'DontUse')
|
||||
add_int_prop('sessionMaxAge', 'SessionMaxAge', 20)
|
||||
if obj_type == 'CommonCommand':
|
||||
grp = P('Group')
|
||||
if grp:
|
||||
@@ -1618,6 +1665,100 @@ def build_dsl():
|
||||
# --- ChildObjects: Attributes + TabularSections ---
|
||||
child_objs = _single(obj_node, 'md:ChildObjects')
|
||||
if child_objs is not None:
|
||||
# WebService: операции с параметрами. Строчное сокращение — только тип возврата.
|
||||
op_nodes = _nodes(child_objs, 'md:Operation')
|
||||
if len(op_nodes) > 0:
|
||||
ops = {}
|
||||
for op in op_nodes:
|
||||
op_p = _single(op, 'md:Properties')
|
||||
op_name = _text(_single(op_p, 'md:Name'))
|
||||
o = {}
|
||||
rt = get_xdto_type_value(_single(op_p, 'md:XDTOReturningValueType'))
|
||||
if rt and rt != 'xs:string':
|
||||
o['returnType'] = rt
|
||||
if _text(_single(op_p, 'md:Nillable')) == 'true':
|
||||
o['nillable'] = True
|
||||
if _text(_single(op_p, 'md:Transactioned')) == 'true':
|
||||
o['transactioned'] = True
|
||||
pn = _text(_single(op_p, 'md:ProcedureName'))
|
||||
if pn and pn != op_name:
|
||||
o['procedureName'] = pn
|
||||
dl = _text(_single(op_p, 'md:DataLockControlMode'))
|
||||
if dl and dl != 'Managed':
|
||||
o['dataLockControlMode'] = dl
|
||||
osyn = get_ml_value(_single(op_p, 'md:Synonym'))
|
||||
if osyn is not None and str(osyn) != split_camel_words(op_name):
|
||||
o['synonym'] = osyn
|
||||
ocmt = _text(_single(op_p, 'md:Comment'))
|
||||
if ocmt:
|
||||
o['comment'] = ocmt
|
||||
par_nodes = _nodes(op, 'md:ChildObjects/md:Parameter')
|
||||
if len(par_nodes) > 0:
|
||||
pars = {}
|
||||
for par in par_nodes:
|
||||
pp = _single(par, 'md:Properties')
|
||||
par_name = _text(_single(pp, 'md:Name'))
|
||||
po = {}
|
||||
pt = get_xdto_type_value(_single(pp, 'md:XDTOValueType'))
|
||||
if pt:
|
||||
po['type'] = pt
|
||||
if _text(_single(pp, 'md:Nillable')) == 'false':
|
||||
po['nillable'] = False
|
||||
pdir = _text(_single(pp, 'md:TransferDirection'))
|
||||
if pdir and pdir != 'In':
|
||||
po['direction'] = pdir
|
||||
psyn = get_ml_value(_single(pp, 'md:Synonym'))
|
||||
if psyn is not None and str(psyn) != split_camel_words(par_name):
|
||||
po['synonym'] = psyn
|
||||
pcmt = _text(_single(pp, 'md:Comment'))
|
||||
if pcmt:
|
||||
po['comment'] = pcmt
|
||||
pars[par_name] = po['type'] if list(po.keys()) == ['type'] else po
|
||||
o['parameters'] = pars
|
||||
ops[op_name] = o['returnType'] if list(o.keys()) == ['returnType'] else o
|
||||
dsl['operations'] = ops
|
||||
# HTTPService: шаблоны URL и их методы.
|
||||
tmpl_nodes = _nodes(child_objs, 'md:URLTemplate')
|
||||
if len(tmpl_nodes) > 0:
|
||||
tmpls = {}
|
||||
for t in tmpl_nodes:
|
||||
tp = _single(t, 'md:Properties')
|
||||
t_name = _text(_single(tp, 'md:Name'))
|
||||
t_obj = {}
|
||||
t_template = _text(_single(tp, 'md:Template'))
|
||||
if t_template:
|
||||
t_obj['template'] = t_template
|
||||
t_syn = get_ml_value(_single(tp, 'md:Synonym'))
|
||||
if t_syn is not None and str(t_syn) != split_camel_words(t_name):
|
||||
t_obj['synonym'] = t_syn
|
||||
t_cmt = _text(_single(tp, 'md:Comment'))
|
||||
if t_cmt:
|
||||
t_obj['comment'] = t_cmt
|
||||
m_nodes = _nodes(t, 'md:ChildObjects/md:Method')
|
||||
if len(m_nodes) > 0:
|
||||
methods = {}
|
||||
for m in m_nodes:
|
||||
mp = _single(m, 'md:Properties')
|
||||
m_name = _text(_single(mp, 'md:Name'))
|
||||
http_val = _text(_single(mp, 'md:HTTPMethod')) or 'GET'
|
||||
handler_val = _text(_single(mp, 'md:Handler')) or ''
|
||||
m_syn = get_ml_value(_single(mp, 'md:Synonym'))
|
||||
m_cmt = _text(_single(mp, 'md:Comment'))
|
||||
syn_default = m_syn is None or str(m_syn) == split_camel_words(m_name)
|
||||
if handler_val == f'{t_name}{m_name}' and syn_default and not m_cmt:
|
||||
methods[m_name] = http_val
|
||||
else:
|
||||
mo = {'httpMethod': http_val}
|
||||
if handler_val:
|
||||
mo['handler'] = handler_val
|
||||
if not syn_default:
|
||||
mo['synonym'] = m_syn
|
||||
if m_cmt:
|
||||
mo['comment'] = m_cmt
|
||||
methods[m_name] = mo
|
||||
t_obj['methods'] = methods
|
||||
tmpls[t_name] = t_obj
|
||||
dsl['urlTemplates'] = tmpls
|
||||
attrs = _nodes(child_objs, 'md:Attribute')
|
||||
if len(attrs) > 0:
|
||||
arr = []
|
||||
@@ -1938,7 +2079,7 @@ SUPPORTED_TYPES = (
|
||||
'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption', 'DocumentJournal', 'Sequence',
|
||||
'FilterCriterion', 'DocumentNumerator', 'SettingsStorage', 'CommonModule', 'EventSubscription', 'ScheduledJob',
|
||||
'CommonForm', 'SessionParameter', 'CommonCommand', 'CommandGroup', 'CommonAttribute', 'FunctionalOptionsParameter',
|
||||
'WSReference', 'CommonPicture', 'CommonTemplate',
|
||||
'WSReference', 'CommonPicture', 'CommonTemplate', 'HTTPService', 'WebService',
|
||||
)
|
||||
|
||||
|
||||
|
||||
+79
-15
@@ -11,7 +11,19 @@
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<Namespace>http://example.com/exchange</Namespace>
|
||||
<XDTOPackages/>
|
||||
<XDTOPackages>
|
||||
<xr:Item>
|
||||
<xr:Presentation/>
|
||||
<xr:CheckState>0</xr:CheckState>
|
||||
<xr:Value xsi:type="xs:string">http://v8.1c.ru/8.3/data/ext</xr:Value>
|
||||
</xr:Item>
|
||||
<xr:Item>
|
||||
<xr:Presentation/>
|
||||
<xr:CheckState>0</xr:CheckState>
|
||||
<xr:Value xsi:type="xs:string">http://example.com/exchange</xr:Value>
|
||||
</xr:Item>
|
||||
</XDTOPackages>
|
||||
<DescriptorFileName>exchange.1cws</DescriptorFileName>
|
||||
<ReuseSessions>AutoUse</ReuseSessions>
|
||||
<SessionMaxAge>20</SessionMaxAge>
|
||||
</Properties>
|
||||
@@ -30,23 +42,10 @@
|
||||
<Nillable>true</Nillable>
|
||||
<Transactioned>false</Transactioned>
|
||||
<ProcedureName>ПолучитьДанные</ProcedureName>
|
||||
<DataLockControlMode>Managed</DataLockControlMode>
|
||||
</Properties>
|
||||
<ChildObjects>
|
||||
<Parameter uuid="UUID-003">
|
||||
<Properties>
|
||||
<Name>ДатаНачала</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Дата начала</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<XDTOValueType>xs:dateTime</XDTOValueType>
|
||||
<Nillable>true</Nillable>
|
||||
<TransferDirection>In</TransferDirection>
|
||||
</Properties>
|
||||
</Parameter>
|
||||
<Parameter uuid="UUID-004">
|
||||
<Properties>
|
||||
<Name>ИдентификаторЗапроса</Name>
|
||||
<Synonym>
|
||||
@@ -55,11 +54,76 @@
|
||||
<v8:content>Идентификатор запроса</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<XDTOValueType>xs:string</XDTOValueType>
|
||||
<Nillable>true</Nillable>
|
||||
<TransferDirection>In</TransferDirection>
|
||||
</Properties>
|
||||
</Parameter>
|
||||
<Parameter uuid="UUID-004">
|
||||
<Properties>
|
||||
<Name>ДатаНачала</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Дата начала</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<XDTOValueType>xs:dateTime</XDTOValueType>
|
||||
<Nillable>true</Nillable>
|
||||
<TransferDirection>In</TransferDirection>
|
||||
</Properties>
|
||||
</Parameter>
|
||||
</ChildObjects>
|
||||
</Operation>
|
||||
<Operation uuid="UUID-005">
|
||||
<Properties>
|
||||
<Name>ОбменСообщениями</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Обмен сообщениями</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment>Основная операция</Comment>
|
||||
<XDTOReturningValueType xmlns:d1p1="http://example.com/exchange">d1p1:MessageExchange</XDTOReturningValueType>
|
||||
<Nillable>false</Nillable>
|
||||
<Transactioned>false</Transactioned>
|
||||
<ProcedureName>ВыполнитьОбмен</ProcedureName>
|
||||
<DataLockControlMode>Managed</DataLockControlMode>
|
||||
</Properties>
|
||||
<ChildObjects>
|
||||
<Parameter uuid="UUID-006">
|
||||
<Properties>
|
||||
<Name>Сообщение</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Сообщение</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<XDTOValueType xmlns:d1p1="http://example.com/exchange">d1p1:MessageExchange</XDTOValueType>
|
||||
<Nillable>false</Nillable>
|
||||
<TransferDirection>In</TransferDirection>
|
||||
</Properties>
|
||||
</Parameter>
|
||||
<Parameter uuid="UUID-007">
|
||||
<Properties>
|
||||
<Name>Ошибка</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Ошибка</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<XDTOValueType>xs:string</XDTOValueType>
|
||||
<Nillable>false</Nillable>
|
||||
<TransferDirection>Out</TransferDirection>
|
||||
</Properties>
|
||||
</Parameter>
|
||||
</ChildObjects>
|
||||
</Operation>
|
||||
</ChildObjects>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
"name": "СервисОбмена",
|
||||
"namespace": "http://example.com/exchange",
|
||||
"reuseSessions": "AutoUse",
|
||||
"descriptorFileName": "exchange.1cws",
|
||||
"xdtoPackages": ["http://v8.1c.ru/8.3/data/ext", "http://example.com/exchange"],
|
||||
"operations": {
|
||||
"ПолучитьДанные": {
|
||||
"returnType": "xs:string",
|
||||
@@ -14,6 +16,15 @@
|
||||
"ИдентификаторЗапроса": "xs:string",
|
||||
"ДатаНачала": "xs:dateTime"
|
||||
}
|
||||
},
|
||||
"ОбменСообщениями": {
|
||||
"returnType": "{http://example.com/exchange}MessageExchange",
|
||||
"procedureName": "ВыполнитьОбмен",
|
||||
"comment": "Основная операция",
|
||||
"parameters": {
|
||||
"Сообщение": { "type": "{http://example.com/exchange}MessageExchange", "nillable": false },
|
||||
"Ошибка": { "type": "xs:string", "nillable": false, "direction": "Out" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user