fix(xdto-info): рецепты создания по факту вида типа

Рецепт для вложенного объекта учил окольной форме там, где она не нужна.
Именованный тип берётся так же, как корневой — ФабрикаXDTO.Тип(ns, имя);
через Свойства.Получить(...).Тип идут только к анонимному, у которого имени
нет. Теперь строка выдаётся по факту: для именованного одна форма, для
анонимного другая, и обе с настоящими именами из пакета.

Убрано утверждение «Узел = ФабрикаXDTO.Создать(ТипУзла, Значение)» для типа
со значением элемента. По синтакс-помощнику Создать(<Тип>, <Значение>)
принимает ТипЗначенияXDTO, а такой узел — объектный тип, то есть форма была
просто неверной. Вместо неё проверяемый факт: значение лежит в свойстве
__content.

Зато для типа значения эта форма как раз корректна, а рецепта там не было
вовсе — добавлен.

Попутно: строка-заглушка «(раскрыт выше)» создавалась без новых ключей, и
py-порт падал с KeyError там, где PowerShell молча возвращает $null на
отсутствующем свойстве. Ключи добавлены, доступ переведён на .get().

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-26 13:52:52 +03:00
co-authored by Claude Opus 5
parent 6486f433de
commit 817ae0fea7
6 changed files with 66 additions and 22 deletions
+25 -7
View File
@@ -333,6 +333,10 @@ function Get-PropRows([System.Xml.XmlElement]$type, $pkg, [int]$depth, [int]$ind
$typeText = ""
$children = $null
$childPkg = $pkg
# Именованный вложенный тип берётся так же, как корневой; окольный путь
# через свойство владельца нужен только анонимному — имени у него нет
$objName = $null
$objNs = $null
$anon = $null
foreach ($c in $p.ChildNodes) {
@@ -342,6 +346,7 @@ function Get-PropRows([System.Xml.XmlElement]$type, $pkg, [int]$depth, [int]$ind
if ($anon) {
if ($anon.GetAttribute("type", $XSI_NS) -eq "ObjectType") {
$typeText = "объект (анонимный)"
$objName = "(анонимный)"
$children = $anon # анонимные раскрываем всегда: смотреть отдельно негде
} else {
$res = Resolve-Scalar $anon $pkg
@@ -363,6 +368,8 @@ function Get-PropRows([System.Xml.XmlElement]$type, $pkg, [int]$depth, [int]$ind
} elseif ($target.Element.get_LocalName() -eq "objectType") {
$typeText = "объект $($q.Local)"
if ($target.Package.Namespace -ne $pkg.Namespace) { $typeText += " · $($target.Package.Name)" }
$objName = $q.Local
$objNs = $target.Package.Namespace
$children = $target.Element
$childPkg = $target.Package
} else {
@@ -379,6 +386,7 @@ function Get-PropRows([System.Xml.XmlElement]$type, $pkg, [int]$depth, [int]$ind
[void]$rows.Add([pscustomobject]@{
Indent = $indent; Name = $pname; Type = $typeText
Flags = $flags; Notes = ($notes | Where-Object { $_ })
ObjName = $objName; ObjNs = $objNs
})
if ($children) {
@@ -548,6 +556,11 @@ function Show-Type($pkg, [string]$typeName) {
O "Допустимые значения ($($res.Enum.Count)):"
foreach ($v in $res.Enum) { O " $v" }
}
O ""
O "Создание:"
# Создать(<Тип>, <Значение>) принимает именно ТипЗначенияXDTO —
# для объектного типа эта форма неприменима
O " Значение = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(`"$($pkg.Namespace)`", `"$typeName`"), Значение);"
return
}
@@ -582,14 +595,19 @@ function Show-Type($pkg, [string]$typeName) {
O " Объект = ФабрикаXDTO.Создать(Тип);"
# Рецепты для вложенных и анонимных типов: имени у анонимного нет, через
# ФабрикаXDTO.Тип(ns, имя) его не получить — только от свойства владельца
$nested = @($rows | Where-Object { $_.Indent -eq 0 -and $_.Type -like "объект *" } | Select-Object -First 1)
if ($nested.Count -gt 0) {
O " Вложенный = ФабрикаXDTO.Создать(Тип.Свойства.Получить(`"$($nested[0].Name)`").Тип);"
$named = @($rows | Where-Object { $_.ObjName -and $_.ObjName -ne "(анонимный)" } | Select-Object -First 1)
if ($named.Count -gt 0) {
O " // вложенный именованный тип — так же, как корневой:"
O " $($named[0].Name) = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(`"$($named[0].ObjNs)`", `"$($named[0].ObjName)`"));"
}
$textProp = @($rows | Where-Object { $_.Flags -contains "значение элемента" } | Select-Object -First 1)
if ($textProp.Count -gt 0) {
O " // тип со значением элемента: значение задаётся при создании"
O " Узел = ФабрикаXDTO.Создать(ТипУзла, Значение);"
$anonRow = @($rows | Where-Object { $_.ObjName -eq "(анонимный)" } | Select-Object -First 1)
if ($anonRow.Count -gt 0) {
O " // у анонимного типа нет имени — только через свойство владельца:"
O " $($anonRow[0].Name) = ФабрикаXDTO.Создать(Тип.Свойства.Получить(`"$($anonRow[0].Name)`").Тип);"
}
$textRow = @($rows | Where-Object { $_.Flags -contains "значение элемента" } | Select-Object -First 1)
if ($textRow.Count -gt 0) {
O " // собственное значение узла лежит в свойстве $($textRow[0].Name)"
}
}
+26 -8
View File
@@ -352,12 +352,17 @@ def get_prop_rows(type_el, pkg, depth, indent, seen):
type_text = ""
children = None
child_pkg = pkg
# Именованный вложенный тип берётся так же, как корневой; окольный путь
# через свойство владельца нужен только анонимному — имени у него нет
obj_name = None
obj_ns = None
anon = next((c for c in p if isinstance(c.tag, str) and local(c) == "typeDef"), None)
if anon is not None:
if anon.get(f"{{{XSI_NS}}}type") == "ObjectType":
type_text = "объект (анонимный)"
obj_name = "(анонимный)"
children = anon # анонимные раскрываем всегда: смотреть отдельно негде
else:
res = resolve_scalar(anon, pkg)
@@ -380,6 +385,8 @@ def get_prop_rows(type_el, pkg, depth, indent, seen):
type_text = "объект " + q[1]
if target[1].Namespace != pkg.Namespace:
type_text += " · " + target[1].Name
obj_name = q[1]
obj_ns = target[1].Namespace
children = target[0]
child_pkg = target[1]
else:
@@ -391,7 +398,8 @@ def get_prop_rows(type_el, pkg, depth, indent, seen):
notes.append("значения: " + ", ".join(res["Enum"][:8]))
rows.append({"Indent": indent, "Name": pname, "Type": type_text,
"Flags": flags, "Notes": [n for n in notes if n]})
"Flags": flags, "Notes": [n for n in notes if n],
"ObjName": obj_name, "ObjNs": obj_ns})
if children is not None:
cname = children.get("name")
@@ -399,7 +407,7 @@ def get_prop_rows(type_el, pkg, depth, indent, seen):
is_anon = not cname
if not is_anon and key in seen:
rows.append({"Indent": indent + 1, "Name": "(раскрыт выше)", "Type": "",
"Flags": [], "Notes": []})
"Flags": [], "Notes": [], "ObjName": None, "ObjNs": None})
elif is_anon or depth > 1:
next_seen = set(seen)
if not is_anon:
@@ -549,6 +557,11 @@ def show_type(pkg, type_name):
O(f'Допустимые значения ({len(res["Enum"])}):')
for v in res["Enum"]:
O(" " + v)
O("")
O("Создание:")
# Создать(<Тип>, <Значение>) принимает именно ТипЗначенияXDTO —
# для объектного типа эта форма неприменима
O(f' Значение = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("{pkg.Namespace}", "{type_name}"), Значение);')
return
hdr = f"=== Тип XDTO: {type_name} ==="
@@ -585,12 +598,17 @@ def show_type(pkg, type_name):
O(" Объект = ФабрикаXDTO.Создать(Тип);")
# Рецепты для вложенных и анонимных типов: имени у анонимного нет, через
# ФабрикаXDTO.Тип(ns, имя) его не получить — только от свойства владельца
nested = next((r for r in rows if r["Indent"] == 0 and r["Type"].startswith("объект ")), None)
if nested:
O(f' Вложенный = ФабрикаXDTO.Создать(Тип.Свойства.Получить("{nested["Name"]}").Тип);')
if any("значение элемента" in r["Flags"] for r in rows):
O(" // тип со значением элемента: значение задаётся при создании")
O(" Узел = ФабрикаXDTO.Создать(ТипУзла, Значение);")
named = next((r for r in rows if r.get("ObjName") and r.get("ObjName") != "(анонимный)"), None)
if named:
O(" // вложенный именованный тип — так же, как корневой:")
O(f' {named["Name"]} = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("{named["ObjNs"]}", "{named["ObjName"]}"));')
anon_row = next((r for r in rows if r.get("ObjName") == "(анонимный)"), None)
if anon_row:
O(" // у анонимного типа нет имени — только через свойство владельца:")
O(f' {anon_row["Name"]} = ФабрикаXDTO.Создать(Тип.Свойства.Получить("{anon_row["Name"]}").Тип);')
text_row = next((r for r in rows if "значение элемента" in r["Flags"]), None)
if text_row:
O(f' // собственное значение узла лежит в свойстве {text_row["Name"]}')
def show_used_by(type_name, owner_pkg):
@@ -14,4 +14,5 @@
Создание:
Тип = ФабрикаXDTO.Тип("urn:test:uses", "Заявка");
Объект = ФабрикаXDTO.Создать(Тип);
Вложенный = ФабрикаXDTO.Создать(Тип.Свойства.Получить("Вид").Тип);
// вложенный именованный тип — так же, как корневой:
Вид = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("urn:test:common", "Справочник"));
@@ -18,6 +18,8 @@
Создание:
Тип = ФабрикаXDTO.Тип("urn:test:nested", "Документ");
Объект = ФабрикаXDTO.Создать(Тип);
Вложенный = ФабрикаXDTO.Создать(Тип.Свойства.Получить("Реквизиты").Тип);
// тип со значением элемента: значение задаётся при создании
Узел = ФабрикаXDTO.Создать(ТипУзла, Значение);
// вложенный именованный тип — так же, как корневой:
Реквизиты = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("urn:test:nested", "Реквизиты"));
// у анонимного типа нет имени — только через свойство владельца:
Встроенный = ФабрикаXDTO.Создать(Тип.Свойства.Получить("Встроенный").Тип);
// собственное значение узла лежит в свойстве __content
@@ -15,6 +15,8 @@
Создание:
Тип = ФабрикаXDTO.Тип("urn:test:nested", "Документ");
Объект = ФабрикаXDTO.Создать(Тип);
Вложенный = ФабрикаXDTO.Создать(Тип.Свойства.Получить("Реквизиты").Тип);
// тип со значением элемента: значение задаётся при создании
Узел = ФабрикаXDTO.Создать(ТипУзла, Значение);
// вложенный именованный тип — так же, как корневой:
Реквизиты = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("urn:test:nested", "Реквизиты"));
// у анонимного типа нет имени — только через свойство владельца:
Встроенный = ФабрикаXDTO.Создать(Тип.Свойства.Получить("Встроенный").Тип);
// собственное значение узла лежит в свойстве __content
@@ -6,3 +6,6 @@
Допустимые значения (2):
Поручение
Требование
Создание:
Значение = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("urn:test:types", "ВидДокумента"), Значение);