mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-31 00:37:47 +03:00
feat(meta-compile,meta-decompile): ChoiceParameterLinks + ChoiceParameters реквизита (v1.22/v0.15)
Ограничение выбора реквизита (связи/параметры) — порт из form-compile
(структура реквизита ⟷ элемента формы совпадает для Links). DSL-ключи:
• choiceParameterLinks — [{name, dataPath, valueChange?}] ИЛИ строки
"name=dataPath[:DontChange]"; valueChange дефолт Clear.
• choiceParameters — [{name, value?}] ИЛИ строки "name=value"; значение
bool/число/строка/DTR ИЛИ массив (→ FixedArray); без value → nil.
ВАЖНО: в метаданных значение ChoiceParameters ПРЯМОЕ на app:value
(xsi:type=тип), БЕЗ обёртки FormChoiceListDesTimeValue/Presentation (в отличие
от формы) — подтверждено survey (0 wrapper на 591 значений). Массив → app:value
xsi:type=v8:FixedArray с детьми v8:Value. Декомпилятор захватывает оба блока
(namespace app; valueChange=Clear → компактная строка).
remaining ChoiceParameterLinks/ChoiceParameters/value=0 на выборке (rt-cp),
регресс 43/43 ps1+py, ps1↔py идентичны. spec §4.2, кейс catalog-attr-choice-params.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9fec03bfb6
commit
65de4e5c97
@@ -1,4 +1,4 @@
|
||||
# meta-compile v1.21 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.22 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -826,6 +826,8 @@ function Parse-AttributeShorthand {
|
||||
hasFillValue = ($val.PSObject -and $val.PSObject.Properties -and ($val.PSObject.Properties.Name -contains 'fillValue'))
|
||||
fillValue = $val.fillValue
|
||||
linkByType = $val.linkByType
|
||||
choiceParameterLinks = $val.choiceParameterLinks
|
||||
choiceParameters = $val.choiceParameters
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1154,6 +1156,133 @@ function Emit-LinkByType {
|
||||
X "$indent</LinkByType>"
|
||||
}
|
||||
|
||||
# --- Параметры/связи выбора (порт из form-compile; структура реквизита ⟷ элемента формы совпадает) ---
|
||||
|
||||
# Свойство из dict/PSCustomObject по списку синонимов (первый найденный, иначе $null).
|
||||
function Get-ChElProp {
|
||||
param($obj, [string[]]$names)
|
||||
if ($null -eq $obj) { return $null }
|
||||
foreach ($n in $names) {
|
||||
if ($obj -is [System.Collections.IDictionary]) { if ($obj.Contains($n)) { return $obj[$n] } }
|
||||
elseif ($obj.PSObject -and $obj.PSObject.Properties[$n]) { return $obj.PSObject.Properties[$n].Value }
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
# Строковый литерал shorthand → скаляр: true/false→bool, целое/дробное→число, иначе строка.
|
||||
function ConvertTo-ChScalar {
|
||||
param([string]$s)
|
||||
$t = "$s".Trim()
|
||||
if ($t -match '^(?i:true|истина)$') { return $true }
|
||||
if ($t -match '^(?i:false|ложь)$') { return $false }
|
||||
if ($t -match '^-?\d+$') { return [int]$t }
|
||||
if ($t -match '^-?\d+\.\d+$') { return [double]::Parse($t, [System.Globalization.CultureInfo]::InvariantCulture) }
|
||||
return $t
|
||||
}
|
||||
|
||||
# Значение параметра выбора → @{XsiType; Text}. Авто-детект по значению (без типа реквизита).
|
||||
function Normalize-ChoiceValue {
|
||||
param($value)
|
||||
if ($value -is [bool]) { return @{ XsiType='xs:boolean'; Text=$(if ($value) { 'true' } else { 'false' }) } }
|
||||
if ($value -is [int] -or $value -is [long] -or $value -is [double] -or $value -is [decimal]) {
|
||||
return @{ XsiType='xs:decimal'; Text=(Format-FillNum $value) }
|
||||
}
|
||||
$s = "$value"
|
||||
if ($s -eq '') { return @{ XsiType='xs:string'; Text='' } }
|
||||
if ($s -match '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$') { return @{ XsiType='xs:dateTime'; Text=$s } }
|
||||
$ref = Normalize-FillRef $s
|
||||
if ($ref) { return @{ XsiType='xr:DesignTimeRef'; Text=$ref } }
|
||||
return @{ XsiType='xs:string'; Text=$s }
|
||||
}
|
||||
|
||||
# Shorthand "name=value" | "name=v1, v2" → {name, value}. "name=path" для links.
|
||||
function ConvertFrom-ChParamShorthand {
|
||||
param([string]$s)
|
||||
$eq = $s.IndexOf('=')
|
||||
if ($eq -lt 0) { return @{ name = $s.Trim() } }
|
||||
$name = $s.Substring(0, $eq).Trim(); $rest = $s.Substring($eq + 1)
|
||||
if ($rest -match ',') {
|
||||
$vals = @(); foreach ($p in ($rest -split ',')) { $vals += ,(ConvertTo-ChScalar $p) }
|
||||
return @{ name = $name; value = $vals }
|
||||
}
|
||||
return @{ name = $name; value = (ConvertTo-ChScalar $rest) }
|
||||
}
|
||||
function ConvertFrom-ChLinkShorthand {
|
||||
param([string]$s)
|
||||
$eq = $s.IndexOf('=')
|
||||
if ($eq -lt 0) { return @{ name = $s.Trim() } }
|
||||
$o = @{ name = $s.Substring(0, $eq).Trim() }; $rest = $s.Substring($eq + 1).Trim()
|
||||
if ($rest -match '^(.*):(?i:(Clear|DontChange|очистить|неизменять))$') { $o['dataPath'] = $matches[1].Trim(); $o['valueChange'] = $matches[2] }
|
||||
else { $o['dataPath'] = $rest }
|
||||
return $o
|
||||
}
|
||||
|
||||
# <ChoiceParameters> — [{name, value?}]. Значение ПРЯМО на app:value (xsi:type=тип); массив → v8:FixedArray
|
||||
# с детьми v8:Value; без value → app:value nil.
|
||||
function Emit-ChoiceParameters {
|
||||
param([string]$indent, $cp)
|
||||
if (-not $cp -or @($cp).Count -eq 0) { X "$indent<ChoiceParameters/>"; return }
|
||||
X "$indent<ChoiceParameters>"
|
||||
foreach ($item in @($cp)) {
|
||||
if ($item -is [string]) { $item = ConvertFrom-ChParamShorthand $item }
|
||||
$name = Get-ChElProp $item @('name','имя')
|
||||
$hasVal = $false; $val = $null
|
||||
if ($item -is [System.Collections.IDictionary]) {
|
||||
if ($item.Contains('value')) { $hasVal = $true; $val = $item['value'] }
|
||||
elseif ($item.Contains('значение')) { $hasVal = $true; $val = $item['значение'] }
|
||||
} elseif ($item.PSObject) {
|
||||
if ($item.PSObject.Properties['value']) { $hasVal = $true; $val = $item.PSObject.Properties['value'].Value }
|
||||
elseif ($item.PSObject.Properties['значение']) { $hasVal = $true; $val = $item.PSObject.Properties['значение'].Value }
|
||||
}
|
||||
$valIsArray = ($val -is [System.Array]) -or ($val -is [System.Collections.IList] -and $val -isnot [string])
|
||||
X "$indent`t<app:item name=`"$(Esc-Xml "$name")`">"
|
||||
if (-not $hasVal) {
|
||||
X "$indent`t`t<app:value xsi:nil=`"true`"/>"
|
||||
} elseif ($valIsArray) {
|
||||
X "$indent`t`t<app:value xsi:type=`"v8:FixedArray`">"
|
||||
foreach ($v in $val) {
|
||||
$norm = Normalize-ChoiceValue -value $v
|
||||
if ([string]::IsNullOrEmpty($norm.Text)) { X "$indent`t`t`t<v8:Value xsi:type=`"$($norm.XsiType)`"/>" }
|
||||
else { X "$indent`t`t`t<v8:Value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</v8:Value>" }
|
||||
}
|
||||
X "$indent`t`t</app:value>"
|
||||
} else {
|
||||
$norm = Normalize-ChoiceValue -value $val
|
||||
if ([string]::IsNullOrEmpty($norm.Text)) { X "$indent`t`t<app:value xsi:type=`"$($norm.XsiType)`"/>" }
|
||||
else { X "$indent`t`t<app:value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</app:value>" }
|
||||
}
|
||||
X "$indent`t</app:item>"
|
||||
}
|
||||
X "$indent</ChoiceParameters>"
|
||||
}
|
||||
|
||||
# <ChoiceParameterLinks> — [{name, dataPath, valueChange?}]. valueChange дефолт Clear.
|
||||
function Emit-ChoiceParameterLinks {
|
||||
param([string]$indent, $cpl)
|
||||
if (-not $cpl -or @($cpl).Count -eq 0) { X "$indent<ChoiceParameterLinks/>"; return }
|
||||
X "$indent<ChoiceParameterLinks>"
|
||||
foreach ($lk in @($cpl)) {
|
||||
if ($lk -is [string]) { $lk = ConvertFrom-ChLinkShorthand $lk }
|
||||
$name = Get-ChElProp $lk @('name','имя')
|
||||
$dp = Get-ChElProp $lk @('dataPath','path','путь')
|
||||
$vcRaw = Get-ChElProp $lk @('valueChange','режимИзменения')
|
||||
$vc = 'Clear'
|
||||
if ($vcRaw) {
|
||||
$vc = switch -Regex ("$vcRaw".ToLower()) {
|
||||
'^(clear|очистить|очистка)$' { 'Clear'; break }
|
||||
'^(dontchange|неизменять|неменять|нет)$' { 'DontChange'; break }
|
||||
default { "$vcRaw" }
|
||||
}
|
||||
}
|
||||
X "$indent`t<xr:Link>"
|
||||
X "$indent`t`t<xr:Name>$(Esc-Xml "$name")</xr:Name>"
|
||||
X "$indent`t`t<xr:DataPath xsi:type=`"xs:string`">$(Esc-Xml "$dp")</xr:DataPath>"
|
||||
X "$indent`t`t<xr:ValueChange>$vc</xr:ValueChange>"
|
||||
X "$indent`t</xr:Link>"
|
||||
}
|
||||
X "$indent</ChoiceParameterLinks>"
|
||||
}
|
||||
|
||||
function Emit-Attribute {
|
||||
param([string]$indent, $parsed, [string]$context)
|
||||
# $context: "catalog", "document", "object", "processor", "tabular", "processor-tabular", "register"
|
||||
@@ -1221,8 +1350,8 @@ function Emit-Attribute {
|
||||
X "$indent`t`t<FillChecking>$fillChecking</FillChecking>"
|
||||
|
||||
X "$indent`t`t<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems>"
|
||||
X "$indent`t`t<ChoiceParameterLinks/>"
|
||||
X "$indent`t`t<ChoiceParameters/>"
|
||||
Emit-ChoiceParameterLinks "$indent`t`t" $parsed.choiceParameterLinks
|
||||
Emit-ChoiceParameters "$indent`t`t" $parsed.choiceParameters
|
||||
$qc = if ($parsed.quickChoice) { $parsed.quickChoice } else { "Auto" }
|
||||
X "$indent`t`t<QuickChoice>$qc</QuickChoice>"
|
||||
$coi = if ($parsed.createOnInput) { $parsed.createOnInput } else { "Auto" }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-compile v1.21 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.22 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -850,6 +850,8 @@ def parse_attribute_shorthand(val):
|
||||
'hasFillValue': ('fillValue' in val),
|
||||
'fillValue': val.get('fillValue'),
|
||||
'linkByType': val.get('linkByType'),
|
||||
'choiceParameterLinks': val.get('choiceParameterLinks'),
|
||||
'choiceParameters': val.get('choiceParameters'),
|
||||
}
|
||||
|
||||
def parse_enum_value_shorthand(val):
|
||||
@@ -1200,6 +1202,133 @@ def emit_link_by_type(indent, spec):
|
||||
X(f'{indent}\t<xr:LinkItem>{li}</xr:LinkItem>')
|
||||
X(f'{indent}</LinkByType>')
|
||||
|
||||
# --- Параметры/связи выбора (порт из form-compile) ---
|
||||
|
||||
def ch_el_prop(obj, names):
|
||||
if obj is None:
|
||||
return None
|
||||
if isinstance(obj, dict):
|
||||
for n in names:
|
||||
if n in obj:
|
||||
return obj[n]
|
||||
return None
|
||||
|
||||
def convert_to_ch_scalar(s):
|
||||
t = str(s).strip()
|
||||
if re.match(r'^(?i:true|истина)$', t):
|
||||
return True
|
||||
if re.match(r'^(?i:false|ложь)$', t):
|
||||
return False
|
||||
if re.match(r'^-?\d+$', t):
|
||||
return int(t)
|
||||
if re.match(r'^-?\d+\.\d+$', t):
|
||||
return float(t)
|
||||
return t
|
||||
|
||||
def normalize_choice_value(value):
|
||||
"""Значение параметра выбора → (xsi_type, text). Авто-детект по значению."""
|
||||
if isinstance(value, bool):
|
||||
return ('xs:boolean', 'true' if value else 'false')
|
||||
if isinstance(value, (int, float)):
|
||||
return ('xs:decimal', format_fill_num(value))
|
||||
s = str(value)
|
||||
if s == '':
|
||||
return ('xs:string', '')
|
||||
if re.match(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$', s):
|
||||
return ('xs:dateTime', s)
|
||||
ref = normalize_fill_ref(s)
|
||||
if ref:
|
||||
return ('xr:DesignTimeRef', ref)
|
||||
return ('xs:string', s)
|
||||
|
||||
def convert_from_ch_param_shorthand(s):
|
||||
eq = s.find('=')
|
||||
if eq < 0:
|
||||
return {'name': s.strip()}
|
||||
name = s[:eq].strip()
|
||||
rest = s[eq + 1:]
|
||||
if ',' in rest:
|
||||
return {'name': name, 'value': [convert_to_ch_scalar(p) for p in rest.split(',')]}
|
||||
return {'name': name, 'value': convert_to_ch_scalar(rest)}
|
||||
|
||||
def convert_from_ch_link_shorthand(s):
|
||||
eq = s.find('=')
|
||||
if eq < 0:
|
||||
return {'name': s.strip()}
|
||||
o = {'name': s[:eq].strip()}
|
||||
rest = s[eq + 1:].strip()
|
||||
m = re.match(r'^(.*):(?i:(Clear|DontChange|очистить|неизменять))$', rest)
|
||||
if m:
|
||||
o['dataPath'] = m.group(1).strip()
|
||||
o['valueChange'] = m.group(2)
|
||||
else:
|
||||
o['dataPath'] = rest
|
||||
return o
|
||||
|
||||
def emit_choice_parameters(indent, cp):
|
||||
if not cp:
|
||||
X(f'{indent}<ChoiceParameters/>')
|
||||
return
|
||||
if isinstance(cp, (str, dict)):
|
||||
cp = [cp]
|
||||
X(f'{indent}<ChoiceParameters>')
|
||||
for item in cp:
|
||||
if isinstance(item, str):
|
||||
item = convert_from_ch_param_shorthand(item)
|
||||
name = ch_el_prop(item, ['name', 'имя'])
|
||||
has_val = isinstance(item, dict) and ('value' in item or 'значение' in item)
|
||||
val = item.get('value', item.get('значение')) if has_val else None
|
||||
val_is_array = isinstance(val, (list, tuple))
|
||||
X(f'{indent}\t<app:item name="{esc_xml(str(name))}">')
|
||||
if not has_val:
|
||||
X(f'{indent}\t\t<app:value xsi:nil="true"/>')
|
||||
elif val_is_array:
|
||||
X(f'{indent}\t\t<app:value xsi:type="v8:FixedArray">')
|
||||
for v in val:
|
||||
xt, tx = normalize_choice_value(v)
|
||||
if tx == '' or tx is None:
|
||||
X(f'{indent}\t\t\t<v8:Value xsi:type="{xt}"/>')
|
||||
else:
|
||||
X(f'{indent}\t\t\t<v8:Value xsi:type="{xt}">{esc_xml(tx)}</v8:Value>')
|
||||
X(f'{indent}\t\t</app:value>')
|
||||
else:
|
||||
xt, tx = normalize_choice_value(val)
|
||||
if tx == '' or tx is None:
|
||||
X(f'{indent}\t\t<app:value xsi:type="{xt}"/>')
|
||||
else:
|
||||
X(f'{indent}\t\t<app:value xsi:type="{xt}">{esc_xml(tx)}</app:value>')
|
||||
X(f'{indent}\t</app:item>')
|
||||
X(f'{indent}</ChoiceParameters>')
|
||||
|
||||
def emit_choice_parameter_links(indent, cpl):
|
||||
if not cpl:
|
||||
X(f'{indent}<ChoiceParameterLinks/>')
|
||||
return
|
||||
if isinstance(cpl, (str, dict)):
|
||||
cpl = [cpl]
|
||||
X(f'{indent}<ChoiceParameterLinks>')
|
||||
for lk in cpl:
|
||||
if isinstance(lk, str):
|
||||
lk = convert_from_ch_link_shorthand(lk)
|
||||
name = ch_el_prop(lk, ['name', 'имя'])
|
||||
dp = ch_el_prop(lk, ['dataPath', 'path', 'путь'])
|
||||
vc_raw = ch_el_prop(lk, ['valueChange', 'режимИзменения'])
|
||||
vc = 'Clear'
|
||||
if vc_raw:
|
||||
low = str(vc_raw).lower()
|
||||
if re.match(r'^(clear|очистить|очистка)$', low):
|
||||
vc = 'Clear'
|
||||
elif re.match(r'^(dontchange|неизменять|неменять|нет)$', low):
|
||||
vc = 'DontChange'
|
||||
else:
|
||||
vc = str(vc_raw)
|
||||
X(f'{indent}\t<xr:Link>')
|
||||
X(f'{indent}\t\t<xr:Name>{esc_xml(str(name))}</xr:Name>')
|
||||
X(f'{indent}\t\t<xr:DataPath xsi:type="xs:string">{esc_xml(str(dp))}</xr:DataPath>')
|
||||
X(f'{indent}\t\t<xr:ValueChange>{vc}</xr:ValueChange>')
|
||||
X(f'{indent}\t</xr:Link>')
|
||||
X(f'{indent}</ChoiceParameterLinks>')
|
||||
|
||||
def emit_attribute(indent, parsed, context):
|
||||
attr_name = parsed['name']
|
||||
ctx_reserved = RESERVED_BY_CONTEXT.get(context)
|
||||
@@ -1254,8 +1383,8 @@ def emit_attribute(indent, parsed, context):
|
||||
fill_checking = parsed['fillChecking']
|
||||
X(f'{indent}\t\t<FillChecking>{fill_checking}</FillChecking>')
|
||||
X(f'{indent}\t\t<ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems>')
|
||||
X(f'{indent}\t\t<ChoiceParameterLinks/>')
|
||||
X(f'{indent}\t\t<ChoiceParameters/>')
|
||||
emit_choice_parameter_links(f'{indent}\t\t', parsed.get('choiceParameterLinks'))
|
||||
emit_choice_parameters(f'{indent}\t\t', parsed.get('choiceParameters'))
|
||||
X(f'{indent}\t\t<QuickChoice>{parsed.get("quickChoice") or "Auto"}</QuickChoice>')
|
||||
X(f'{indent}\t\t<CreateOnInput>{parsed.get("createOnInput") or "Auto"}</CreateOnInput>')
|
||||
X(f'{indent}\t\t<ChoiceForm/>')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-decompile v0.14 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# meta-decompile v0.15 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
#
|
||||
# Пилот: только Catalog. Инверс meta-compile (omit-on-default: ключ эмитим только
|
||||
@@ -79,6 +79,7 @@ $nsm.AddNamespace('md', 'http://v8.1c.ru/8.3/MDClasses')
|
||||
$nsm.AddNamespace('v8', 'http://v8.1c.ru/8.1/data/core')
|
||||
$nsm.AddNamespace('xr', 'http://v8.1c.ru/8.3/xcf/readable')
|
||||
$nsm.AddNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance')
|
||||
$nsm.AddNamespace('app', 'http://v8.1c.ru/8.2/managed-application/core')
|
||||
|
||||
$rootEl = $doc.DocumentElement
|
||||
if ($rootEl.LocalName -ne 'MetaDataObject') {
|
||||
@@ -183,6 +184,31 @@ function Get-TypeShorthand {
|
||||
return ($parts -join ' + ')
|
||||
}
|
||||
|
||||
# Скалярное значение параметра выбора (<Value xsi:type=...>) → JSON-значение (bool/число/строка).
|
||||
# string/dateTime/DesignTimeRef → строка (компилятор auto-детектит обратно).
|
||||
function Convert-ChScalarNode {
|
||||
param($vN)
|
||||
$xt = $vN.GetAttribute('type', 'http://www.w3.org/2001/XMLSchema-instance')
|
||||
$txt = $vN.InnerText
|
||||
if ($xt -match 'boolean$') { return ($txt -eq 'true') }
|
||||
if ($xt -match 'decimal$') {
|
||||
if ($txt -match '^-?\d+$') { return [int]$txt }
|
||||
return [double]::Parse($txt, [System.Globalization.CultureInfo]::InvariantCulture)
|
||||
}
|
||||
return $txt
|
||||
}
|
||||
# app:value (тип прямо на узле) → значение ЛИБО массив (v8:FixedArray с детьми v8:Value).
|
||||
function Get-ChoiceParamValue {
|
||||
param($valNode)
|
||||
$xt = $valNode.GetAttribute('type', 'http://www.w3.org/2001/XMLSchema-instance')
|
||||
if ($xt -match 'FixedArray$') {
|
||||
$arr = [System.Collections.ArrayList]@()
|
||||
foreach ($sub in @($valNode.SelectNodes('v8:Value', $nsm))) { [void]$arr.Add((Convert-ChScalarNode $sub)) }
|
||||
return $arr
|
||||
}
|
||||
return Convert-ChScalarNode $valNode
|
||||
}
|
||||
|
||||
# --- Реквизит → DSL: shorthand-строка "Имя: Тип | флаги" ЛИБО object-форма при кастомном синониме.
|
||||
# (Синоним ≠ авто → object {name, type, synonym, [flags]}; иначе компактный shorthand.) ---
|
||||
function Attr-ToDsl {
|
||||
@@ -263,6 +289,46 @@ function Attr-ToDsl {
|
||||
}
|
||||
}
|
||||
|
||||
# ChoiceParameterLinks — [{name, dataPath, valueChange?}]. valueChange=Clear → компактно строкой "name=dataPath".
|
||||
$cplNode = $ap.SelectSingleNode('md:ChoiceParameterLinks', $nsm)
|
||||
if ($cplNode) {
|
||||
$links = @($cplNode.SelectNodes('xr:Link', $nsm))
|
||||
if ($links.Count -gt 0) {
|
||||
$arr = [System.Collections.ArrayList]@()
|
||||
foreach ($lk in $links) {
|
||||
$lName = $lk.SelectSingleNode('xr:Name', $nsm).InnerText
|
||||
$lDp = $lk.SelectSingleNode('xr:DataPath', $nsm).InnerText
|
||||
$vcN = $lk.SelectSingleNode('xr:ValueChange', $nsm)
|
||||
$vcv = if ($vcN) { $vcN.InnerText } else { 'Clear' }
|
||||
if ($vcv -eq 'Clear') { [void]$arr.Add("$lName=$lDp") }
|
||||
else { [void]$arr.Add([ordered]@{ name = $lName; dataPath = $lDp; valueChange = $vcv }) }
|
||||
}
|
||||
$extra['choiceParameterLinks'] = $arr
|
||||
}
|
||||
}
|
||||
|
||||
# ChoiceParameters — [{name, value?}]. app:value nil → без value; иначе типизированное значение.
|
||||
$cpNode = $ap.SelectSingleNode('md:ChoiceParameters', $nsm)
|
||||
if ($cpNode) {
|
||||
$items = @($cpNode.SelectNodes('app:item', $nsm))
|
||||
if ($items.Count -gt 0) {
|
||||
$arr = [System.Collections.ArrayList]@()
|
||||
foreach ($it in $items) {
|
||||
$pName = $it.GetAttribute('name')
|
||||
$valN = $it.SelectSingleNode('app:value', $nsm)
|
||||
$nilAttr = if ($valN) { $valN.GetAttribute('nil', 'http://www.w3.org/2001/XMLSchema-instance') } else { '' }
|
||||
if (-not $valN -or $nilAttr -eq 'true') {
|
||||
[void]$arr.Add([ordered]@{ name = $pName })
|
||||
} else {
|
||||
$o = [ordered]@{ name = $pName }
|
||||
$o['value'] = Get-ChoiceParamValue $valN
|
||||
[void]$arr.Add($o)
|
||||
}
|
||||
}
|
||||
$extra['choiceParameters'] = $arr
|
||||
}
|
||||
}
|
||||
|
||||
if ($synCustom -or ($null -ne $ttVal) -or $extra.Count -gt 0) {
|
||||
$o = [ordered]@{ name = $nm }
|
||||
if ($ts) { $o['type'] = $ts }
|
||||
|
||||
Reference in New Issue
Block a user