mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-20 00:45:54 +03:00
fix(form,skd,init,meta-edit): развести экранирование атрибута и текста
esc_xml был один на две задачи, и в атрибутном контексте применялся текстовый вариант без ". form-compile с choiceParameters, имя которого содержит кавычку, выдавал <app:item name="Отбор.Наименование "кавычка"">: lxml падает с attributes construct error, то есть файл невалиден как XML. Затронуто 9 мест в form-compile и 3 в skd-compile, одинаково в обоих портах. Раундтрип через базу показал границу: в ТЕКСТЕ элемента платформа экранирует только & < > (кавычка и апостроф возвращаются сырыми байт-в-байт), а в ЗНАЧЕНИИ АТРИБУТА пишет " — внутри "..." литеральная кавычка невалидна. Поэтому две функции с говорящими именами, а не одна с флагом: esc_xml — значение атрибута: & < > " esc_xml_text — текст элемента: & < > Заодно закрыто расхождение портов в init-навыках: PY экранировал текст с ", PS1 — через SecurityElement::Escape (ещё и '), а epf-init/erf-init в PS1 не экранировали вовсе, из-за чего амперсанд в синониме давал невалидный XML. Кейсы: form-compile/attr-value-escaping, skd-compile/additional-properties-escaping, cf-init/synonym-escaping — все три проверены негативным прогоном на обоих портах и верификацией снэпшотов на платформе. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3c50d3caa0
commit
974ca3aac9
@@ -1,4 +1,4 @@
|
||||
# skd-edit v1.34 — Atomic 1C DCS editor (+resolve_type_str: срезание префикса cfg:/d5p1:)
|
||||
# skd-edit v1.35 — Atomic 1C DCS editor (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
# NB: парный .py собирает выражения автодат вне f-string ради совместимости с python 3.9 (PEP 701).
|
||||
param(
|
||||
@@ -183,6 +183,12 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) {
|
||||
Assert-EditAllowed $resolvedPath 'editable'
|
||||
|
||||
function Esc-Xml {
|
||||
param([string]$s)
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>').Replace('"','"')
|
||||
}
|
||||
|
||||
function Esc-XmlText {
|
||||
param([string]$s)
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>')
|
||||
}
|
||||
@@ -1008,16 +1014,16 @@ function Build-ValueTypeXml {
|
||||
}
|
||||
|
||||
if ($typeStr -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef)\.') {
|
||||
$lines += "$indent<v8:Type xmlns:d5p1=`"http://v8.1c.ru/8.1/data/enterprise/current-config`">d5p1:$(Esc-Xml $typeStr)</v8:Type>"
|
||||
$lines += "$indent<v8:Type xmlns:d5p1=`"http://v8.1c.ru/8.1/data/enterprise/current-config`">d5p1:$(Esc-XmlText $typeStr)</v8:Type>"
|
||||
return $lines -join "`n"
|
||||
}
|
||||
|
||||
if ($typeStr.Contains('.')) {
|
||||
$lines += "$indent<v8:Type xmlns:d5p1=`"http://v8.1c.ru/8.1/data/enterprise/current-config`">d5p1:$(Esc-Xml $typeStr)</v8:Type>"
|
||||
$lines += "$indent<v8:Type xmlns:d5p1=`"http://v8.1c.ru/8.1/data/enterprise/current-config`">d5p1:$(Esc-XmlText $typeStr)</v8:Type>"
|
||||
return $lines -join "`n"
|
||||
}
|
||||
|
||||
$lines += "$indent<v8:Type>$(Esc-Xml $typeStr)</v8:Type>"
|
||||
$lines += "$indent<v8:Type>$(Esc-XmlText $typeStr)</v8:Type>"
|
||||
return $lines -join "`n"
|
||||
}
|
||||
|
||||
@@ -1073,7 +1079,7 @@ function Build-MLTextXml {
|
||||
$lines += "$indent<$tag xsi:type=`"v8:LocalStringType`">"
|
||||
$lines += "$indent`t<v8:item>"
|
||||
$lines += "$indent`t`t<v8:lang>ru</v8:lang>"
|
||||
$lines += "$indent`t`t<v8:content>$(Esc-Xml $text)</v8:content>"
|
||||
$lines += "$indent`t`t<v8:content>$(Esc-XmlText $text)</v8:content>"
|
||||
$lines += "$indent`t</v8:item>"
|
||||
$lines += "$indent</$tag>"
|
||||
return $lines -join "`n"
|
||||
@@ -1085,7 +1091,7 @@ function Build-MLTextXml {
|
||||
# If no ru item exists, one is prepended before the first existing item.
|
||||
function Patch-MLTextRu {
|
||||
param([string]$rawOuterXml, [string]$newRuText, [string]$indent)
|
||||
$escaped = Esc-Xml $newRuText
|
||||
$escaped = Esc-XmlText $newRuText
|
||||
$ruItemPat = '(<v8:item>\s*<v8:lang>ru</v8:lang>\s*<v8:content>)[^<]*(</v8:content>\s*</v8:item>)'
|
||||
if ([regex]::IsMatch($rawOuterXml, $ruItemPat)) {
|
||||
return [regex]::Replace($rawOuterXml, $ruItemPat, { param($m) $m.Groups[1].Value + $escaped + $m.Groups[2].Value })
|
||||
@@ -1148,8 +1154,8 @@ function Build-FieldFragment {
|
||||
$i = $indent
|
||||
$lines = @()
|
||||
$lines += "$i<field xsi:type=`"DataSetFieldField`">"
|
||||
$lines += "$i`t<dataPath>$(Esc-Xml $parsed.dataPath)</dataPath>"
|
||||
$lines += "$i`t<field>$(Esc-Xml $parsed.field)</field>"
|
||||
$lines += "$i`t<dataPath>$(Esc-XmlText $parsed.dataPath)</dataPath>"
|
||||
$lines += "$i`t<field>$(Esc-XmlText $parsed.field)</field>"
|
||||
|
||||
# Title: prefer raw multi-lang title (preserves en/uk/etc.). When shorthand provides
|
||||
# a new ru text, patch ru content inside the raw title; otherwise emit raw as-is.
|
||||
@@ -1199,8 +1205,8 @@ function Build-TotalFragment {
|
||||
$i = $indent
|
||||
$lines = @()
|
||||
$lines += "$i<totalField>"
|
||||
$lines += "$i`t<dataPath>$(Esc-Xml $parsed.dataPath)</dataPath>"
|
||||
$lines += "$i`t<expression>$(Esc-Xml $parsed.expression)</expression>"
|
||||
$lines += "$i`t<dataPath>$(Esc-XmlText $parsed.dataPath)</dataPath>"
|
||||
$lines += "$i`t<expression>$(Esc-XmlText $parsed.expression)</expression>"
|
||||
$lines += "$i</totalField>"
|
||||
return $lines -join "`n"
|
||||
}
|
||||
@@ -1211,8 +1217,8 @@ function Build-CalcFieldFragment {
|
||||
$i = $indent
|
||||
$lines = @()
|
||||
$lines += "$i<calculatedField>"
|
||||
$lines += "$i`t<dataPath>$(Esc-Xml $parsed.dataPath)</dataPath>"
|
||||
$lines += "$i`t<expression>$(Esc-Xml $parsed.expression)</expression>"
|
||||
$lines += "$i`t<dataPath>$(Esc-XmlText $parsed.dataPath)</dataPath>"
|
||||
$lines += "$i`t<expression>$(Esc-XmlText $parsed.expression)</expression>"
|
||||
|
||||
if ($parsed.title) {
|
||||
$lines += (Build-MLTextXml -tag "title" -text $parsed.title -indent "$i`t")
|
||||
@@ -1244,7 +1250,7 @@ function Build-ParamValueXml {
|
||||
|
||||
if ($type -eq "StandardPeriod") {
|
||||
$lines += "$i<$open xsi:type=`"v8:StandardPeriod`">"
|
||||
$lines += "$i`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml $valStr)</v8:variant>"
|
||||
$lines += "$i`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-XmlText $valStr)</v8:variant>"
|
||||
$lines += "$i`t<v8:startDate>0001-01-01T00:00:00</v8:startDate>"
|
||||
$lines += "$i`t<v8:endDate>0001-01-01T00:00:00</v8:endDate>"
|
||||
$lines += "$i</$open>"
|
||||
@@ -1270,7 +1276,7 @@ function Build-ParamValueXml {
|
||||
else { $xsi = "xs:string" }
|
||||
}
|
||||
|
||||
$lines += "$i<$open xsi:type=`"$xsi`">$(Esc-Xml $valStr)</$open>"
|
||||
$lines += "$i<$open xsi:type=`"$xsi`">$(Esc-XmlText $valStr)</$open>"
|
||||
return $lines
|
||||
}
|
||||
|
||||
@@ -1291,7 +1297,7 @@ function Build-AvailableValueFragment {
|
||||
$lines += "$indent`t<presentation xsi:type=`"v8:LocalStringType`">"
|
||||
$lines += "$indent`t`t<v8:item>"
|
||||
$lines += "$indent`t`t`t<v8:lang>ru</v8:lang>"
|
||||
$lines += "$indent`t`t`t<v8:content>$(Esc-Xml $item.presentation)</v8:content>"
|
||||
$lines += "$indent`t`t`t<v8:content>$(Esc-XmlText $item.presentation)</v8:content>"
|
||||
$lines += "$indent`t`t</v8:item>"
|
||||
$lines += "$indent`t</presentation>"
|
||||
}
|
||||
@@ -1307,7 +1313,7 @@ function Build-ParamFragment {
|
||||
|
||||
$lines = @()
|
||||
$lines += "$i<parameter>"
|
||||
$lines += "$i`t<name>$(Esc-Xml $parsed.name)</name>"
|
||||
$lines += "$i`t<name>$(Esc-XmlText $parsed.name)</name>"
|
||||
|
||||
if ($parsed.title) {
|
||||
$lines += (Build-MLTextXml -tag "title" -text $parsed.title -indent "$i`t")
|
||||
@@ -1373,7 +1379,7 @@ function Build-ParamFragment {
|
||||
$bLines += "$i`t</valueType>"
|
||||
$bLines += "$i`t<value xsi:type=`"xs:dateTime`">0001-01-01T00:00:00</value>"
|
||||
$bLines += "$i`t<useRestriction>true</useRestriction>"
|
||||
$bLines += "$i`t<expression>$(Esc-Xml "&$paramName.ДатаНачала")</expression>"
|
||||
$bLines += "$i`t<expression>$(Esc-XmlText "&$paramName.ДатаНачала")</expression>"
|
||||
$bLines += "$i</parameter>"
|
||||
$fragments += ($bLines -join "`n")
|
||||
|
||||
@@ -1386,7 +1392,7 @@ function Build-ParamFragment {
|
||||
$eLines += "$i`t</valueType>"
|
||||
$eLines += "$i`t<value xsi:type=`"xs:dateTime`">0001-01-01T00:00:00</value>"
|
||||
$eLines += "$i`t<useRestriction>true</useRestriction>"
|
||||
$eLines += "$i`t<expression>$(Esc-Xml "&$paramName.ДатаОкончания")</expression>"
|
||||
$eLines += "$i`t<expression>$(Esc-XmlText "&$paramName.ДатаОкончания")</expression>"
|
||||
$eLines += "$i</parameter>"
|
||||
$fragments += ($eLines -join "`n")
|
||||
}
|
||||
@@ -1405,21 +1411,21 @@ function Build-FilterItemFragment {
|
||||
$lines += "$i`t<dcsset:use>false</dcsset:use>"
|
||||
}
|
||||
|
||||
$lines += "$i`t<dcsset:left xsi:type=`"dcscor:Field`">$(Esc-Xml $parsed.field)</dcsset:left>"
|
||||
$lines += "$i`t<dcsset:comparisonType>$(Esc-Xml $parsed.op)</dcsset:comparisonType>"
|
||||
$lines += "$i`t<dcsset:left xsi:type=`"dcscor:Field`">$(Esc-XmlText $parsed.field)</dcsset:left>"
|
||||
$lines += "$i`t<dcsset:comparisonType>$(Esc-XmlText $parsed.op)</dcsset:comparisonType>"
|
||||
|
||||
if ($null -ne $parsed.value) {
|
||||
$vt = if ($parsed["valueType"]) { $parsed["valueType"] } else { "xs:string" }
|
||||
$lines += "$i`t<dcsset:right xsi:type=`"$vt`">$(Esc-Xml "$($parsed.value)")</dcsset:right>"
|
||||
$lines += "$i`t<dcsset:right xsi:type=`"$vt`">$(Esc-XmlText "$($parsed.value)")</dcsset:right>"
|
||||
}
|
||||
|
||||
if ($parsed.viewMode) {
|
||||
$lines += "$i`t<dcsset:viewMode>$(Esc-Xml $parsed.viewMode)</dcsset:viewMode>"
|
||||
$lines += "$i`t<dcsset:viewMode>$(Esc-XmlText $parsed.viewMode)</dcsset:viewMode>"
|
||||
}
|
||||
|
||||
if ($parsed.userSettingID) {
|
||||
$uid = if ($parsed.userSettingID -eq "auto") { [System.Guid]::NewGuid().ToString() } else { $parsed.userSettingID }
|
||||
$lines += "$i`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
|
||||
$lines += "$i`t<dcsset:userSettingID>$(Esc-XmlText $uid)</dcsset:userSettingID>"
|
||||
}
|
||||
|
||||
$lines += "$i</dcsset:item>"
|
||||
@@ -1448,20 +1454,20 @@ function Build-SelectionItemFragment {
|
||||
$lines += "$i`t<dcsset:lwsTitle>"
|
||||
$lines += "$i`t`t<v8:item>"
|
||||
$lines += "$i`t`t`t<v8:lang>ru</v8:lang>"
|
||||
$lines += "$i`t`t`t<v8:content>$(Esc-Xml $title)</v8:content>"
|
||||
$lines += "$i`t`t`t<v8:content>$(Esc-XmlText $title)</v8:content>"
|
||||
$lines += "$i`t`t</v8:item>"
|
||||
$lines += "$i`t</dcsset:lwsTitle>"
|
||||
}
|
||||
foreach ($item in $items) {
|
||||
$lines += "$i`t<dcsset:item xsi:type=`"dcsset:SelectedItemField`">"
|
||||
$lines += "$i`t`t<dcsset:field>$(Esc-Xml $item)</dcsset:field>"
|
||||
$lines += "$i`t`t<dcsset:field>$(Esc-XmlText $item)</dcsset:field>"
|
||||
$lines += "$i`t</dcsset:item>"
|
||||
}
|
||||
$lines += "$i`t<dcsset:placement>Auto</dcsset:placement>"
|
||||
$lines += "$i</dcsset:item>"
|
||||
} else {
|
||||
$lines += "$i<dcsset:item xsi:type=`"dcsset:SelectedItemField`">"
|
||||
$lines += "$i`t<dcsset:field>$(Esc-Xml $fieldName)</dcsset:field>"
|
||||
$lines += "$i`t<dcsset:field>$(Esc-XmlText $fieldName)</dcsset:field>"
|
||||
$lines += "$i</dcsset:item>"
|
||||
}
|
||||
return $lines -join "`n"
|
||||
@@ -1478,33 +1484,33 @@ function Build-DataParamFragment {
|
||||
$lines += "$i`t<dcscor:use>false</dcscor:use>"
|
||||
}
|
||||
|
||||
$lines += "$i`t<dcscor:parameter>$(Esc-Xml $parsed.parameter)</dcscor:parameter>"
|
||||
$lines += "$i`t<dcscor:parameter>$(Esc-XmlText $parsed.parameter)</dcscor:parameter>"
|
||||
|
||||
if ($null -ne $parsed.value) {
|
||||
if ($parsed.value -is [hashtable] -and $parsed.value.variant) {
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"v8:StandardPeriod`">"
|
||||
$lines += "$i`t`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml $parsed.value.variant)</v8:variant>"
|
||||
$lines += "$i`t`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-XmlText $parsed.value.variant)</v8:variant>"
|
||||
$lines += "$i`t`t<v8:startDate>0001-01-01T00:00:00</v8:startDate>"
|
||||
$lines += "$i`t`t<v8:endDate>0001-01-01T00:00:00</v8:endDate>"
|
||||
$lines += "$i`t</dcscor:value>"
|
||||
} elseif (Test-EmptyValue $parsed.value) {
|
||||
$lines += "$i`t<dcscor:value xsi:nil=`"true`"/>"
|
||||
} elseif ("$($parsed.value)" -match '^\d{4}-\d{2}-\d{2}T') {
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"xs:dateTime`">$(Esc-Xml "$($parsed.value)")</dcscor:value>"
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"xs:dateTime`">$(Esc-XmlText "$($parsed.value)")</dcscor:value>"
|
||||
} elseif ("$($parsed.value)" -eq "true" -or "$($parsed.value)" -eq "false") {
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"xs:boolean`">$(Esc-Xml "$($parsed.value)")</dcscor:value>"
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"xs:boolean`">$(Esc-XmlText "$($parsed.value)")</dcscor:value>"
|
||||
} else {
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml "$($parsed.value)")</dcscor:value>"
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"xs:string`">$(Esc-XmlText "$($parsed.value)")</dcscor:value>"
|
||||
}
|
||||
}
|
||||
|
||||
if ($parsed.viewMode) {
|
||||
$lines += "$i`t<dcsset:viewMode>$(Esc-Xml $parsed.viewMode)</dcsset:viewMode>"
|
||||
$lines += "$i`t<dcsset:viewMode>$(Esc-XmlText $parsed.viewMode)</dcsset:viewMode>"
|
||||
}
|
||||
|
||||
if ($parsed.userSettingID) {
|
||||
$uid = if ($parsed.userSettingID -eq "auto") { [System.Guid]::NewGuid().ToString() } else { $parsed.userSettingID }
|
||||
$lines += "$i`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
|
||||
$lines += "$i`t<dcsset:userSettingID>$(Esc-XmlText $uid)</dcsset:userSettingID>"
|
||||
}
|
||||
|
||||
$lines += "$i</dcscor:item>"
|
||||
@@ -1520,7 +1526,7 @@ function Build-OrderItemFragment {
|
||||
$lines += "$i<dcsset:item xsi:type=`"dcsset:OrderItemAuto`"/>"
|
||||
} else {
|
||||
$lines += "$i<dcsset:item xsi:type=`"dcsset:OrderItemField`">"
|
||||
$lines += "$i`t<dcsset:field>$(Esc-Xml $parsed.field)</dcsset:field>"
|
||||
$lines += "$i`t<dcsset:field>$(Esc-XmlText $parsed.field)</dcsset:field>"
|
||||
$lines += "$i`t<dcsset:orderType>$($parsed.direction)</dcsset:orderType>"
|
||||
$lines += "$i</dcsset:item>"
|
||||
}
|
||||
@@ -1533,12 +1539,12 @@ function Build-DataSetLinkFragment {
|
||||
$i = $indent
|
||||
$lines = @()
|
||||
$lines += "$i<dataSetLink>"
|
||||
$lines += "$i`t<sourceDataSet>$(Esc-Xml $parsed.source)</sourceDataSet>"
|
||||
$lines += "$i`t<destinationDataSet>$(Esc-Xml $parsed.dest)</destinationDataSet>"
|
||||
$lines += "$i`t<sourceExpression>$(Esc-Xml $parsed.sourceExpr)</sourceExpression>"
|
||||
$lines += "$i`t<destinationExpression>$(Esc-Xml $parsed.destExpr)</destinationExpression>"
|
||||
$lines += "$i`t<sourceDataSet>$(Esc-XmlText $parsed.source)</sourceDataSet>"
|
||||
$lines += "$i`t<destinationDataSet>$(Esc-XmlText $parsed.dest)</destinationDataSet>"
|
||||
$lines += "$i`t<sourceExpression>$(Esc-XmlText $parsed.sourceExpr)</sourceExpression>"
|
||||
$lines += "$i`t<destinationExpression>$(Esc-XmlText $parsed.destExpr)</destinationExpression>"
|
||||
if ($parsed.parameter) {
|
||||
$lines += "$i`t<parameter>$(Esc-Xml $parsed.parameter)</parameter>"
|
||||
$lines += "$i`t<parameter>$(Esc-XmlText $parsed.parameter)</parameter>"
|
||||
}
|
||||
$lines += "$i</dataSetLink>"
|
||||
return $lines -join "`n"
|
||||
@@ -1550,9 +1556,9 @@ function Build-DataSetQueryFragment {
|
||||
$i = $indent
|
||||
$lines = @()
|
||||
$lines += "$i<dataSet xsi:type=`"DataSetQuery`">"
|
||||
$lines += "$i`t<name>$(Esc-Xml $parsed.name)</name>"
|
||||
$lines += "$i`t<dataSource>$(Esc-Xml $parsed.dataSource)</dataSource>"
|
||||
$lines += "$i`t<query>$(Esc-Xml $parsed.query)</query>"
|
||||
$lines += "$i`t<name>$(Esc-XmlText $parsed.name)</name>"
|
||||
$lines += "$i`t<dataSource>$(Esc-XmlText $parsed.dataSource)</dataSource>"
|
||||
$lines += "$i`t<query>$(Esc-XmlText $parsed.query)</query>"
|
||||
$lines += "$i</dataSet>"
|
||||
return $lines -join "`n"
|
||||
}
|
||||
@@ -1563,7 +1569,7 @@ function Build-VariantFragment {
|
||||
$i = $indent
|
||||
$lines = @()
|
||||
$lines += "$i<settingsVariant>"
|
||||
$lines += "$i`t<dcsset:name>$(Esc-Xml $parsed.name)</dcsset:name>"
|
||||
$lines += "$i`t<dcsset:name>$(Esc-XmlText $parsed.name)</dcsset:name>"
|
||||
$lines += (Build-MLTextXml -tag "dcsset:presentation" -text $parsed.presentation -indent "$i`t")
|
||||
$lines += "$i`t<dcsset:settings xmlns:style=`"http://v8.1c.ru/8.1/data/ui/style`" xmlns:sys=`"http://v8.1c.ru/8.1/data/ui/fonts/system`" xmlns:web=`"http://v8.1c.ru/8.1/data/ui/colors/web`" xmlns:win=`"http://v8.1c.ru/8.1/data/ui/colors/windows`">"
|
||||
$lines += "$i`t`t<dcsset:selection>"
|
||||
@@ -1587,11 +1593,11 @@ function Emit-FilterComparison {
|
||||
param($f, [string]$indent)
|
||||
$lines = @()
|
||||
$lines += "$indent<dcsset:item xsi:type=`"dcsset:FilterItemComparison`">"
|
||||
$lines += "$indent`t<dcsset:left xsi:type=`"dcscor:Field`">$(Esc-Xml $f.field)</dcsset:left>"
|
||||
$lines += "$indent`t<dcsset:comparisonType>$(Esc-Xml $f.op)</dcsset:comparisonType>"
|
||||
$lines += "$indent`t<dcsset:left xsi:type=`"dcscor:Field`">$(Esc-XmlText $f.field)</dcsset:left>"
|
||||
$lines += "$indent`t<dcsset:comparisonType>$(Esc-XmlText $f.op)</dcsset:comparisonType>"
|
||||
if ($null -ne $f.value) {
|
||||
$vt = if ($f["valueType"]) { $f["valueType"] } else { "xs:string" }
|
||||
$lines += "$indent`t<dcsset:right xsi:type=`"$vt`">$(Esc-Xml "$($f.value)")</dcsset:right>"
|
||||
$lines += "$indent`t<dcsset:right xsi:type=`"$vt`">$(Esc-XmlText "$($f.value)")</dcsset:right>"
|
||||
}
|
||||
$lines += "$indent</dcsset:item>"
|
||||
return $lines
|
||||
@@ -1609,7 +1615,7 @@ function Build-ConditionalAppearanceItemFragment {
|
||||
$lines += "$i`t<dcsset:selection>"
|
||||
foreach ($fld in $parsed.fields) {
|
||||
$lines += "$i`t`t<dcsset:item>"
|
||||
$lines += "$i`t`t`t<dcsset:field>$(Esc-Xml $fld)</dcsset:field>"
|
||||
$lines += "$i`t`t`t<dcsset:field>$(Esc-XmlText $fld)</dcsset:field>"
|
||||
$lines += "$i`t`t</dcsset:item>"
|
||||
}
|
||||
$lines += "$i`t</dcsset:selection>"
|
||||
@@ -1641,21 +1647,21 @@ function Build-ConditionalAppearanceItemFragment {
|
||||
|
||||
$val = $parsed.value
|
||||
$lines += "$i`t`t<dcscor:item xsi:type=`"dcsset:SettingsParameterValue`">"
|
||||
$lines += "$i`t`t`t<dcscor:parameter>$(Esc-Xml $parsed.param)</dcscor:parameter>"
|
||||
$lines += "$i`t`t`t<dcscor:parameter>$(Esc-XmlText $parsed.param)</dcscor:parameter>"
|
||||
|
||||
if ($val -match '^(web|style|win):') {
|
||||
$lines += "$i`t`t`t<dcscor:value xsi:type=`"v8ui:Color`">$(Esc-Xml $val)</dcscor:value>"
|
||||
$lines += "$i`t`t`t<dcscor:value xsi:type=`"v8ui:Color`">$(Esc-XmlText $val)</dcscor:value>"
|
||||
} elseif ($val -eq "true" -or $val -eq "false") {
|
||||
$lines += "$i`t`t`t<dcscor:value xsi:type=`"xs:boolean`">$(Esc-Xml $val)</dcscor:value>"
|
||||
$lines += "$i`t`t`t<dcscor:value xsi:type=`"xs:boolean`">$(Esc-XmlText $val)</dcscor:value>"
|
||||
} elseif ($parsed.param -eq "Формат" -or $parsed.param -eq "Текст" -or $parsed.param -eq "Заголовок") {
|
||||
$lines += "$i`t`t`t<dcscor:value xsi:type=`"v8:LocalStringType`">"
|
||||
$lines += "$i`t`t`t`t<v8:item>"
|
||||
$lines += "$i`t`t`t`t`t<v8:lang>ru</v8:lang>"
|
||||
$lines += "$i`t`t`t`t`t<v8:content>$(Esc-Xml $val)</v8:content>"
|
||||
$lines += "$i`t`t`t`t`t<v8:content>$(Esc-XmlText $val)</v8:content>"
|
||||
$lines += "$i`t`t`t`t</v8:item>"
|
||||
$lines += "$i`t`t`t</dcscor:value>"
|
||||
} else {
|
||||
$lines += "$i`t`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml $val)</dcscor:value>"
|
||||
$lines += "$i`t`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-XmlText $val)</dcscor:value>"
|
||||
}
|
||||
|
||||
$lines += "$i`t`t</dcscor:item>"
|
||||
@@ -1674,7 +1680,7 @@ function Build-StructureItemFragment {
|
||||
|
||||
# name
|
||||
if ($item["name"]) {
|
||||
$lines += "$i`t<dcsset:name>$(Esc-Xml $item["name"])</dcsset:name>"
|
||||
$lines += "$i`t<dcsset:name>$(Esc-XmlText $item["name"])</dcsset:name>"
|
||||
}
|
||||
|
||||
# groupItems
|
||||
@@ -1685,7 +1691,7 @@ function Build-StructureItemFragment {
|
||||
$lines += "$i`t<dcsset:groupItems>"
|
||||
foreach ($field in $groupBy) {
|
||||
$lines += "$i`t`t<dcsset:item xsi:type=`"dcsset:GroupItemField`">"
|
||||
$lines += "$i`t`t`t<dcsset:field>$(Esc-Xml $field)</dcsset:field>"
|
||||
$lines += "$i`t`t`t<dcsset:field>$(Esc-XmlText $field)</dcsset:field>"
|
||||
$lines += "$i`t`t`t<dcsset:groupType>Items</dcsset:groupType>"
|
||||
$lines += "$i`t`t`t<dcsset:periodAdditionType>None</dcsset:periodAdditionType>"
|
||||
$lines += "$i`t`t`t<dcsset:periodAdditionBegin xsi:type=`"xs:dateTime`">0001-01-01T00:00:00</dcsset:periodAdditionBegin>"
|
||||
@@ -1728,17 +1734,17 @@ function Build-OutputParamFragment {
|
||||
|
||||
$lines = @()
|
||||
$lines += "$i<dcscor:item xsi:type=`"dcsset:SettingsParameterValue`">"
|
||||
$lines += "$i`t<dcscor:parameter>$(Esc-Xml $key)</dcscor:parameter>"
|
||||
$lines += "$i`t<dcscor:parameter>$(Esc-XmlText $key)</dcscor:parameter>"
|
||||
|
||||
if ($ptype -eq "mltext") {
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"v8:LocalStringType`">"
|
||||
$lines += "$i`t`t<v8:item>"
|
||||
$lines += "$i`t`t`t<v8:lang>ru</v8:lang>"
|
||||
$lines += "$i`t`t`t<v8:content>$(Esc-Xml $val)</v8:content>"
|
||||
$lines += "$i`t`t`t<v8:content>$(Esc-XmlText $val)</v8:content>"
|
||||
$lines += "$i`t`t</v8:item>"
|
||||
$lines += "$i`t</dcscor:value>"
|
||||
} else {
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"$ptype`">$(Esc-Xml $val)</dcscor:value>"
|
||||
$lines += "$i`t<dcscor:value xsi:type=`"$ptype`">$(Esc-XmlText $val)</dcscor:value>"
|
||||
}
|
||||
|
||||
$lines += "$i</dcscor:item>"
|
||||
@@ -1888,7 +1894,7 @@ function Set-OrCreateChildElement($parent, [string]$localName, [string]$nsUri, [
|
||||
} else {
|
||||
$prefix = $parent.GetPrefixOfNamespace($nsUri)
|
||||
$qualName = if ($prefix) { "${prefix}:$localName" } else { $localName }
|
||||
$fragXml = "$indent<$qualName>$(Esc-Xml $value)</$qualName>"
|
||||
$fragXml = "$indent<$qualName>$(Esc-XmlText $value)</$qualName>"
|
||||
$nodes = Import-Fragment $xmlDoc $fragXml
|
||||
foreach ($node in $nodes) {
|
||||
Insert-BeforeElement $parent $node $null $indent
|
||||
@@ -1913,7 +1919,7 @@ function Set-OrCreateChildElementWithAttr($parent, [string]$localName, [string]$
|
||||
$prefix = $parent.GetPrefixOfNamespace($nsUri)
|
||||
$qualName = if ($prefix) { "${prefix}:$localName" } else { $localName }
|
||||
$typeAttr = if ($xsiType) { " xsi:type=`"$xsiType`"" } else { "" }
|
||||
$fragXml = "$indent<$qualName$typeAttr>$(Esc-Xml $value)</$qualName>"
|
||||
$fragXml = "$indent<$qualName$typeAttr>$(Esc-XmlText $value)</$qualName>"
|
||||
$nodes = Import-Fragment $xmlDoc $fragXml
|
||||
foreach ($node in $nodes) {
|
||||
Insert-BeforeElement $parent $node $null $indent
|
||||
@@ -2586,7 +2592,7 @@ switch ($Operation) {
|
||||
}
|
||||
}
|
||||
}
|
||||
$fragXml = "$childIndent<$key>$(Esc-Xml $value)</$key>"
|
||||
$fragXml = "$childIndent<$key>$(Esc-XmlText $value)</$key>"
|
||||
$nodes = Import-Fragment $xmlDoc $fragXml
|
||||
foreach ($node in $nodes) {
|
||||
Insert-BeforeElement $paramEl $node $refNode $childIndent
|
||||
@@ -3247,7 +3253,7 @@ switch ($Operation) {
|
||||
foreach ($field in $t.groupBy) {
|
||||
$lines = @()
|
||||
$lines += "$itemIndent<dcsset:item xsi:type=`"dcsset:GroupItemField`">"
|
||||
$lines += "$itemIndent`t<dcsset:field>$(Esc-Xml $field)</dcsset:field>"
|
||||
$lines += "$itemIndent`t<dcsset:field>$(Esc-XmlText $field)</dcsset:field>"
|
||||
$lines += "$itemIndent`t<dcsset:groupType>Items</dcsset:groupType>"
|
||||
$lines += "$itemIndent`t<dcsset:periodAdditionType>None</dcsset:periodAdditionType>"
|
||||
$lines += "$itemIndent`t<dcsset:periodAdditionBegin xsi:type=`"xs:dateTime`">0001-01-01T00:00:00</dcsset:periodAdditionBegin>"
|
||||
@@ -3563,18 +3569,18 @@ switch ($Operation) {
|
||||
$valLines = @()
|
||||
if ($parsed.value -is [hashtable] -and $parsed.value.variant) {
|
||||
$valLines += "$itemIndent<dcscor:value xsi:type=`"v8:StandardPeriod`">"
|
||||
$valLines += "$itemIndent`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml $parsed.value.variant)</v8:variant>"
|
||||
$valLines += "$itemIndent`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-XmlText $parsed.value.variant)</v8:variant>"
|
||||
$valLines += "$itemIndent`t<v8:startDate>0001-01-01T00:00:00</v8:startDate>"
|
||||
$valLines += "$itemIndent`t<v8:endDate>0001-01-01T00:00:00</v8:endDate>"
|
||||
$valLines += "$itemIndent</dcscor:value>"
|
||||
} elseif (Test-EmptyValue $parsed.value) {
|
||||
$valLines += "$itemIndent<dcscor:value xsi:nil=`"true`"/>"
|
||||
} elseif ("$($parsed.value)" -match '^\d{4}-\d{2}-\d{2}T') {
|
||||
$valLines += "$itemIndent<dcscor:value xsi:type=`"xs:dateTime`">$(Esc-Xml "$($parsed.value)")</dcscor:value>"
|
||||
$valLines += "$itemIndent<dcscor:value xsi:type=`"xs:dateTime`">$(Esc-XmlText "$($parsed.value)")</dcscor:value>"
|
||||
} elseif ("$($parsed.value)" -eq "true" -or "$($parsed.value)" -eq "false") {
|
||||
$valLines += "$itemIndent<dcscor:value xsi:type=`"xs:boolean`">$(Esc-Xml "$($parsed.value)")</dcscor:value>"
|
||||
$valLines += "$itemIndent<dcscor:value xsi:type=`"xs:boolean`">$(Esc-XmlText "$($parsed.value)")</dcscor:value>"
|
||||
} else {
|
||||
$valLines += "$itemIndent<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml "$($parsed.value)")</dcscor:value>"
|
||||
$valLines += "$itemIndent<dcscor:value xsi:type=`"xs:string`">$(Esc-XmlText "$($parsed.value)")</dcscor:value>"
|
||||
}
|
||||
$valXml = $valLines -join "`n"
|
||||
$valNodes = Import-Fragment $xmlDoc $valXml
|
||||
@@ -3748,7 +3754,7 @@ switch ($Operation) {
|
||||
}
|
||||
}
|
||||
foreach ($k in $kv.Keys) {
|
||||
$lines += "$fieldIndent`t<dcscom:$k>$(Esc-Xml $kv[$k])</dcscom:$k>"
|
||||
$lines += "$fieldIndent`t<dcscom:$k>$(Esc-XmlText $kv[$k])</dcscom:$k>"
|
||||
}
|
||||
foreach ($raw in $preservedRoleChildren) {
|
||||
$lines += "$fieldIndent`t" + $raw
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# skd-edit v1.34 — Atomic 1C DCS editor (Python port) (+resolve_type_str: срезание префикса cfg:/d5p1:)
|
||||
# skd-edit v1.35 — Atomic 1C DCS editor (Python port) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import json
|
||||
@@ -81,6 +81,11 @@ def local_name(node):
|
||||
# ── helpers ──────────────────────────────────────────────────
|
||||
|
||||
def esc_xml(s):
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
def esc_xml_text(s):
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
|
||||
|
||||
@@ -932,7 +937,7 @@ def build_available_value_fragment(item, declared_type, indent):
|
||||
lines.append(f'{indent}\t<presentation xsi:type="v8:LocalStringType">')
|
||||
lines.append(f"{indent}\t\t<v8:item>")
|
||||
lines.append(f"{indent}\t\t\t<v8:lang>ru</v8:lang>")
|
||||
lines.append(f"{indent}\t\t\t<v8:content>{esc_xml(item['presentation'])}</v8:content>")
|
||||
lines.append(f"{indent}\t\t\t<v8:content>{esc_xml_text(item['presentation'])}</v8:content>")
|
||||
lines.append(f"{indent}\t\t</v8:item>")
|
||||
lines.append(f"{indent}\t</presentation>")
|
||||
lines.append(f"{indent}</availableValue>")
|
||||
@@ -1005,14 +1010,14 @@ def build_value_type_xml(type_str, indent):
|
||||
return "\n".join(lines)
|
||||
|
||||
if re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef)\.', type_str):
|
||||
lines.append(f'{indent}<v8:Type xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d5p1:{esc_xml(type_str)}</v8:Type>')
|
||||
lines.append(f'{indent}<v8:Type xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d5p1:{esc_xml_text(type_str)}</v8:Type>')
|
||||
return "\n".join(lines)
|
||||
|
||||
if "." in type_str:
|
||||
lines.append(f'{indent}<v8:Type xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d5p1:{esc_xml(type_str)}</v8:Type>')
|
||||
lines.append(f'{indent}<v8:Type xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d5p1:{esc_xml_text(type_str)}</v8:Type>')
|
||||
return "\n".join(lines)
|
||||
|
||||
lines.append(f"{indent}<v8:Type>{esc_xml(type_str)}</v8:Type>")
|
||||
lines.append(f"{indent}<v8:Type>{esc_xml_text(type_str)}</v8:Type>")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
@@ -1067,7 +1072,7 @@ def build_mltext_xml(tag, text, indent):
|
||||
f'{indent}<{tag} xsi:type="v8:LocalStringType">',
|
||||
f"{indent}\t<v8:item>",
|
||||
f"{indent}\t\t<v8:lang>ru</v8:lang>",
|
||||
f"{indent}\t\t<v8:content>{esc_xml(text)}</v8:content>",
|
||||
f"{indent}\t\t<v8:content>{esc_xml_text(text)}</v8:content>",
|
||||
f"{indent}\t</v8:item>",
|
||||
f"{indent}</{tag}>",
|
||||
]
|
||||
@@ -1077,7 +1082,7 @@ def build_mltext_xml(tag, text, indent):
|
||||
def patch_mltext_ru(raw_outer_xml, new_ru_text, indent):
|
||||
"""Patch the ru <v8:content> within an existing multi-lang title OuterXml,
|
||||
preserving en/uk/etc. siblings. Mirrors PS Patch-MLTextRu."""
|
||||
escaped = esc_xml(new_ru_text)
|
||||
escaped = esc_xml_text(new_ru_text)
|
||||
ru_item_pat = r"(<v8:item>\s*<v8:lang>ru</v8:lang>\s*<v8:content>)[^<]*(</v8:content>\s*</v8:item>)"
|
||||
if re.search(ru_item_pat, raw_outer_xml):
|
||||
return re.sub(ru_item_pat, lambda m: m.group(1) + escaped + m.group(2), raw_outer_xml)
|
||||
@@ -1117,8 +1122,8 @@ def build_restriction_xml(restrict, indent):
|
||||
def build_field_fragment(parsed, indent):
|
||||
i = indent
|
||||
lines = [f'{i}<field xsi:type="DataSetFieldField">']
|
||||
lines.append(f"{i}\t<dataPath>{esc_xml(parsed['dataPath'])}</dataPath>")
|
||||
lines.append(f"{i}\t<field>{esc_xml(parsed['field'])}</field>")
|
||||
lines.append(f"{i}\t<dataPath>{esc_xml_text(parsed['dataPath'])}</dataPath>")
|
||||
lines.append(f"{i}\t<field>{esc_xml_text(parsed['field'])}</field>")
|
||||
|
||||
# Title: prefer raw multi-lang OuterXml (preserves en/uk/etc.). When shorthand
|
||||
# provides a new ru text different from existing, patch the ru content. Otherwise
|
||||
@@ -1159,8 +1164,8 @@ def build_total_fragment(parsed, indent):
|
||||
i = indent
|
||||
lines = [
|
||||
f"{i}<totalField>",
|
||||
f"{i}\t<dataPath>{esc_xml(parsed['dataPath'])}</dataPath>",
|
||||
f"{i}\t<expression>{esc_xml(parsed['expression'])}</expression>",
|
||||
f"{i}\t<dataPath>{esc_xml_text(parsed['dataPath'])}</dataPath>",
|
||||
f"{i}\t<expression>{esc_xml_text(parsed['expression'])}</expression>",
|
||||
f"{i}</totalField>",
|
||||
]
|
||||
return "\n".join(lines)
|
||||
@@ -1170,8 +1175,8 @@ def build_calc_field_fragment(parsed, indent):
|
||||
i = indent
|
||||
lines = [
|
||||
f"{i}<calculatedField>",
|
||||
f"{i}\t<dataPath>{esc_xml(parsed['dataPath'])}</dataPath>",
|
||||
f"{i}\t<expression>{esc_xml(parsed['expression'])}</expression>",
|
||||
f"{i}\t<dataPath>{esc_xml_text(parsed['dataPath'])}</dataPath>",
|
||||
f"{i}\t<expression>{esc_xml_text(parsed['expression'])}</expression>",
|
||||
]
|
||||
if parsed.get("title"):
|
||||
lines.append(build_mltext_xml("title", parsed["title"], f"{i}\t"))
|
||||
@@ -1193,7 +1198,7 @@ def build_param_value_xml(type_str, value, indent, tag_name="value", tag_ns=""):
|
||||
|
||||
if type_str == "StandardPeriod":
|
||||
lines.append(f'{indent}<{open_tag} xsi:type="v8:StandardPeriod">')
|
||||
lines.append(f'{indent}\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml(val_str)}</v8:variant>')
|
||||
lines.append(f'{indent}\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml_text(val_str)}</v8:variant>')
|
||||
lines.append(f"{indent}\t<v8:startDate>0001-01-01T00:00:00</v8:startDate>")
|
||||
lines.append(f"{indent}\t<v8:endDate>0001-01-01T00:00:00</v8:endDate>")
|
||||
lines.append(f"{indent}</{open_tag}>")
|
||||
@@ -1222,7 +1227,7 @@ def build_param_value_xml(type_str, value, indent, tag_name="value", tag_ns=""):
|
||||
else:
|
||||
xsi = "xs:string"
|
||||
|
||||
lines.append(f'{indent}<{open_tag} xsi:type="{xsi}">{esc_xml(val_str)}</{open_tag}>')
|
||||
lines.append(f'{indent}<{open_tag} xsi:type="{xsi}">{esc_xml_text(val_str)}</{open_tag}>')
|
||||
return lines
|
||||
|
||||
|
||||
@@ -1230,7 +1235,7 @@ def build_param_fragment(parsed, indent):
|
||||
i = indent
|
||||
fragments = []
|
||||
|
||||
lines = [f"{i}<parameter>", f"{i}\t<name>{esc_xml(parsed['name'])}</name>"]
|
||||
lines = [f"{i}<parameter>", f"{i}\t<name>{esc_xml_text(parsed['name'])}</name>"]
|
||||
|
||||
if parsed.get("title"):
|
||||
lines.append(build_mltext_xml("title", parsed["title"], f"{i}\t"))
|
||||
@@ -1277,7 +1282,7 @@ def build_param_fragment(parsed, indent):
|
||||
# Canonical БСП pattern: title + valueType + value + useRestriction + expression
|
||||
# NB: expr автодат собираем в переменную (не в f-string): бэкслеш в \uXXXX
|
||||
# внутри {} f-строки — SyntaxError на python < 3.12 (PEP 701). Совместимость с 3.9.
|
||||
expr_start = esc_xml('&' + param_name + '.\u0414\u0430\u0442\u0430\u041d\u0430\u0447\u0430\u043b\u0430')
|
||||
expr_start = esc_xml_text('&' + param_name + '.\u0414\u0430\u0442\u0430\u041d\u0430\u0447\u0430\u043b\u0430')
|
||||
b_lines = [
|
||||
f"{i}<parameter>",
|
||||
f"{i}\t<name>\u0414\u0430\u0442\u0430\u041d\u0430\u0447\u0430\u043b\u0430</name>",
|
||||
@@ -1292,7 +1297,7 @@ def build_param_fragment(parsed, indent):
|
||||
]
|
||||
fragments.append("\n".join(b_lines))
|
||||
|
||||
expr_end = esc_xml('&' + param_name + '.\u0414\u0430\u0442\u0430\u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f')
|
||||
expr_end = esc_xml_text('&' + param_name + '.\u0414\u0430\u0442\u0430\u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f')
|
||||
e_lines = [
|
||||
f"{i}<parameter>",
|
||||
f"{i}\t<name>\u0414\u0430\u0442\u0430\u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f</name>",
|
||||
@@ -1317,19 +1322,19 @@ def build_filter_item_fragment(parsed, indent):
|
||||
if parsed.get("use") is False:
|
||||
lines.append(f"{i}\t<dcsset:use>false</dcsset:use>")
|
||||
|
||||
lines.append(f'{i}\t<dcsset:left xsi:type="dcscor:Field">{esc_xml(parsed["field"])}</dcsset:left>')
|
||||
lines.append(f"{i}\t<dcsset:comparisonType>{esc_xml(parsed['op'])}</dcsset:comparisonType>")
|
||||
lines.append(f'{i}\t<dcsset:left xsi:type="dcscor:Field">{esc_xml_text(parsed["field"])}</dcsset:left>')
|
||||
lines.append(f"{i}\t<dcsset:comparisonType>{esc_xml_text(parsed['op'])}</dcsset:comparisonType>")
|
||||
|
||||
if parsed.get("value") is not None:
|
||||
vt = parsed.get("valueType", "xs:string")
|
||||
lines.append(f'{i}\t<dcsset:right xsi:type="{vt}">{esc_xml(str(parsed["value"]))}</dcsset:right>')
|
||||
lines.append(f'{i}\t<dcsset:right xsi:type="{vt}">{esc_xml_text(str(parsed["value"]))}</dcsset:right>')
|
||||
|
||||
if parsed.get("viewMode"):
|
||||
lines.append(f"{i}\t<dcsset:viewMode>{esc_xml(parsed['viewMode'])}</dcsset:viewMode>")
|
||||
lines.append(f"{i}\t<dcsset:viewMode>{esc_xml_text(parsed['viewMode'])}</dcsset:viewMode>")
|
||||
|
||||
if parsed.get("userSettingID"):
|
||||
uid = new_uuid() if parsed["userSettingID"] == "auto" else parsed["userSettingID"]
|
||||
lines.append(f"{i}\t<dcsset:userSettingID>{esc_xml(uid)}</dcsset:userSettingID>")
|
||||
lines.append(f"{i}\t<dcsset:userSettingID>{esc_xml_text(uid)}</dcsset:userSettingID>")
|
||||
|
||||
lines.append(f"{i}</dcsset:item>")
|
||||
return "\n".join(lines)
|
||||
@@ -1354,19 +1359,19 @@ def build_selection_item_fragment(field_name, indent):
|
||||
lines.append(f"{i}\t<dcsset:lwsTitle>")
|
||||
lines.append(f"{i}\t\t<v8:item>")
|
||||
lines.append(f"{i}\t\t\t<v8:lang>ru</v8:lang>")
|
||||
lines.append(f"{i}\t\t\t<v8:content>{esc_xml(title)}</v8:content>")
|
||||
lines.append(f"{i}\t\t\t<v8:content>{esc_xml_text(title)}</v8:content>")
|
||||
lines.append(f"{i}\t\t</v8:item>")
|
||||
lines.append(f"{i}\t</dcsset:lwsTitle>")
|
||||
for item in items:
|
||||
lines.append(f'{i}\t<dcsset:item xsi:type="dcsset:SelectedItemField">')
|
||||
lines.append(f"{i}\t\t<dcsset:field>{esc_xml(item)}</dcsset:field>")
|
||||
lines.append(f"{i}\t\t<dcsset:field>{esc_xml_text(item)}</dcsset:field>")
|
||||
lines.append(f"{i}\t</dcsset:item>")
|
||||
lines.append(f"{i}\t<dcsset:placement>Auto</dcsset:placement>")
|
||||
lines.append(f"{i}</dcsset:item>")
|
||||
return "\n".join(lines)
|
||||
lines = [
|
||||
f'{i}<dcsset:item xsi:type="dcsset:SelectedItemField">',
|
||||
f"{i}\t<dcsset:field>{esc_xml(field_name)}</dcsset:field>",
|
||||
f"{i}\t<dcsset:field>{esc_xml_text(field_name)}</dcsset:field>",
|
||||
f"{i}</dcsset:item>",
|
||||
]
|
||||
return "\n".join(lines)
|
||||
@@ -1379,31 +1384,31 @@ def build_data_param_fragment(parsed, indent):
|
||||
if parsed.get("use") is False:
|
||||
lines.append(f"{i}\t<dcscor:use>false</dcscor:use>")
|
||||
|
||||
lines.append(f"{i}\t<dcscor:parameter>{esc_xml(parsed['parameter'])}</dcscor:parameter>")
|
||||
lines.append(f"{i}\t<dcscor:parameter>{esc_xml_text(parsed['parameter'])}</dcscor:parameter>")
|
||||
|
||||
if parsed.get("value") is not None:
|
||||
val = parsed["value"]
|
||||
if isinstance(val, dict) and val.get("variant"):
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="v8:StandardPeriod">')
|
||||
lines.append(f'{i}\t\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml(val["variant"])}</v8:variant>')
|
||||
lines.append(f'{i}\t\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml_text(val["variant"])}</v8:variant>')
|
||||
lines.append(f"{i}\t\t<v8:startDate>0001-01-01T00:00:00</v8:startDate>")
|
||||
lines.append(f"{i}\t\t<v8:endDate>0001-01-01T00:00:00</v8:endDate>")
|
||||
lines.append(f"{i}\t</dcscor:value>")
|
||||
elif is_empty_value(val):
|
||||
lines.append(f'{i}\t<dcscor:value xsi:nil="true"/>')
|
||||
elif re.match(r'^\d{4}-\d{2}-\d{2}T', str(val)):
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="xs:dateTime">{esc_xml(str(val))}</dcscor:value>')
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="xs:dateTime">{esc_xml_text(str(val))}</dcscor:value>')
|
||||
elif str(val) in ("true", "false"):
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="xs:boolean">{esc_xml(str(val))}</dcscor:value>')
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="xs:boolean">{esc_xml_text(str(val))}</dcscor:value>')
|
||||
else:
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="xs:string">{esc_xml(str(val))}</dcscor:value>')
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="xs:string">{esc_xml_text(str(val))}</dcscor:value>')
|
||||
|
||||
if parsed.get("viewMode"):
|
||||
lines.append(f"{i}\t<dcsset:viewMode>{esc_xml(parsed['viewMode'])}</dcsset:viewMode>")
|
||||
lines.append(f"{i}\t<dcsset:viewMode>{esc_xml_text(parsed['viewMode'])}</dcsset:viewMode>")
|
||||
|
||||
if parsed.get("userSettingID"):
|
||||
uid = new_uuid() if parsed["userSettingID"] == "auto" else parsed["userSettingID"]
|
||||
lines.append(f"{i}\t<dcsset:userSettingID>{esc_xml(uid)}</dcsset:userSettingID>")
|
||||
lines.append(f"{i}\t<dcsset:userSettingID>{esc_xml_text(uid)}</dcsset:userSettingID>")
|
||||
|
||||
lines.append(f"{i}</dcscor:item>")
|
||||
return "\n".join(lines)
|
||||
@@ -1415,7 +1420,7 @@ def build_order_item_fragment(parsed, indent):
|
||||
return f'{i}<dcsset:item xsi:type="dcsset:OrderItemAuto"/>'
|
||||
lines = [
|
||||
f'{i}<dcsset:item xsi:type="dcsset:OrderItemField">',
|
||||
f"{i}\t<dcsset:field>{esc_xml(parsed['field'])}</dcsset:field>",
|
||||
f"{i}\t<dcsset:field>{esc_xml_text(parsed['field'])}</dcsset:field>",
|
||||
f"{i}\t<dcsset:orderType>{parsed['direction']}</dcsset:orderType>",
|
||||
f"{i}</dcsset:item>",
|
||||
]
|
||||
@@ -1426,13 +1431,13 @@ def build_data_set_link_fragment(parsed, indent):
|
||||
i = indent
|
||||
lines = [
|
||||
f"{i}<dataSetLink>",
|
||||
f"{i}\t<sourceDataSet>{esc_xml(parsed['source'])}</sourceDataSet>",
|
||||
f"{i}\t<destinationDataSet>{esc_xml(parsed['dest'])}</destinationDataSet>",
|
||||
f"{i}\t<sourceExpression>{esc_xml(parsed['sourceExpr'])}</sourceExpression>",
|
||||
f"{i}\t<destinationExpression>{esc_xml(parsed['destExpr'])}</destinationExpression>",
|
||||
f"{i}\t<sourceDataSet>{esc_xml_text(parsed['source'])}</sourceDataSet>",
|
||||
f"{i}\t<destinationDataSet>{esc_xml_text(parsed['dest'])}</destinationDataSet>",
|
||||
f"{i}\t<sourceExpression>{esc_xml_text(parsed['sourceExpr'])}</sourceExpression>",
|
||||
f"{i}\t<destinationExpression>{esc_xml_text(parsed['destExpr'])}</destinationExpression>",
|
||||
]
|
||||
if parsed.get("parameter"):
|
||||
lines.append(f"{i}\t<parameter>{esc_xml(parsed['parameter'])}</parameter>")
|
||||
lines.append(f"{i}\t<parameter>{esc_xml_text(parsed['parameter'])}</parameter>")
|
||||
lines.append(f"{i}</dataSetLink>")
|
||||
return "\n".join(lines)
|
||||
|
||||
@@ -1441,9 +1446,9 @@ def build_data_set_query_fragment(parsed, indent):
|
||||
i = indent
|
||||
lines = [
|
||||
f'{i}<dataSet xsi:type="DataSetQuery">',
|
||||
f"{i}\t<name>{esc_xml(parsed['name'])}</name>",
|
||||
f"{i}\t<dataSource>{esc_xml(parsed['dataSource'])}</dataSource>",
|
||||
f"{i}\t<query>{esc_xml(parsed['query'])}</query>",
|
||||
f"{i}\t<name>{esc_xml_text(parsed['name'])}</name>",
|
||||
f"{i}\t<dataSource>{esc_xml_text(parsed['dataSource'])}</dataSource>",
|
||||
f"{i}\t<query>{esc_xml_text(parsed['query'])}</query>",
|
||||
f"{i}</dataSet>",
|
||||
]
|
||||
return "\n".join(lines)
|
||||
@@ -1453,7 +1458,7 @@ def build_variant_fragment(parsed, indent):
|
||||
i = indent
|
||||
lines = [
|
||||
f"{i}<settingsVariant>",
|
||||
f"{i}\t<dcsset:name>{esc_xml(parsed['name'])}</dcsset:name>",
|
||||
f"{i}\t<dcsset:name>{esc_xml_text(parsed['name'])}</dcsset:name>",
|
||||
build_mltext_xml("dcsset:presentation", parsed["presentation"], f"{i}\t"),
|
||||
f'{i}\t<dcsset:settings xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows">',
|
||||
f"{i}\t\t<dcsset:selection>",
|
||||
@@ -1476,11 +1481,11 @@ def build_variant_fragment(parsed, indent):
|
||||
|
||||
def _emit_filter_comparison(lines, f, indent):
|
||||
lines.append(f'{indent}<dcsset:item xsi:type="dcsset:FilterItemComparison">')
|
||||
lines.append(f'{indent}\t<dcsset:left xsi:type="dcscor:Field">{esc_xml(f["field"])}</dcsset:left>')
|
||||
lines.append(f"{indent}\t<dcsset:comparisonType>{esc_xml(f['op'])}</dcsset:comparisonType>")
|
||||
lines.append(f'{indent}\t<dcsset:left xsi:type="dcscor:Field">{esc_xml_text(f["field"])}</dcsset:left>')
|
||||
lines.append(f"{indent}\t<dcsset:comparisonType>{esc_xml_text(f['op'])}</dcsset:comparisonType>")
|
||||
if f.get("value") is not None:
|
||||
vt = f.get("valueType", "xs:string")
|
||||
lines.append(f'{indent}\t<dcsset:right xsi:type="{vt}">{esc_xml(str(f["value"]))}</dcsset:right>')
|
||||
lines.append(f'{indent}\t<dcsset:right xsi:type="{vt}">{esc_xml_text(str(f["value"]))}</dcsset:right>')
|
||||
lines.append(f"{indent}</dcsset:item>")
|
||||
|
||||
|
||||
@@ -1492,7 +1497,7 @@ def build_conditional_appearance_item_fragment(parsed, indent):
|
||||
lines.append(f"{i}\t<dcsset:selection>")
|
||||
for fld in parsed["fields"]:
|
||||
lines.append(f"{i}\t\t<dcsset:item>")
|
||||
lines.append(f"{i}\t\t\t<dcsset:field>{esc_xml(fld)}</dcsset:field>")
|
||||
lines.append(f"{i}\t\t\t<dcsset:field>{esc_xml_text(fld)}</dcsset:field>")
|
||||
lines.append(f"{i}\t\t</dcsset:item>")
|
||||
lines.append(f"{i}\t</dcsset:selection>")
|
||||
else:
|
||||
@@ -1518,21 +1523,21 @@ def build_conditional_appearance_item_fragment(parsed, indent):
|
||||
lines.append(f"{i}\t<dcsset:appearance>")
|
||||
val = parsed["value"]
|
||||
lines.append(f'{i}\t\t<dcscor:item xsi:type="dcsset:SettingsParameterValue">')
|
||||
lines.append(f"{i}\t\t\t<dcscor:parameter>{esc_xml(parsed['param'])}</dcscor:parameter>")
|
||||
lines.append(f"{i}\t\t\t<dcscor:parameter>{esc_xml_text(parsed['param'])}</dcscor:parameter>")
|
||||
|
||||
if re.match(r'^(web|style|win):', val):
|
||||
lines.append(f'{i}\t\t\t<dcscor:value xsi:type="v8ui:Color">{esc_xml(val)}</dcscor:value>')
|
||||
lines.append(f'{i}\t\t\t<dcscor:value xsi:type="v8ui:Color">{esc_xml_text(val)}</dcscor:value>')
|
||||
elif val in ("true", "false"):
|
||||
lines.append(f'{i}\t\t\t<dcscor:value xsi:type="xs:boolean">{esc_xml(val)}</dcscor:value>')
|
||||
lines.append(f'{i}\t\t\t<dcscor:value xsi:type="xs:boolean">{esc_xml_text(val)}</dcscor:value>')
|
||||
elif parsed["param"] in ("Формат", "Текст", "Заголовок"):
|
||||
lines.append(f'{i}\t\t\t<dcscor:value xsi:type="v8:LocalStringType">')
|
||||
lines.append(f"{i}\t\t\t\t<v8:item>")
|
||||
lines.append(f"{i}\t\t\t\t\t<v8:lang>ru</v8:lang>")
|
||||
lines.append(f"{i}\t\t\t\t\t<v8:content>{esc_xml(val)}</v8:content>")
|
||||
lines.append(f"{i}\t\t\t\t\t<v8:content>{esc_xml_text(val)}</v8:content>")
|
||||
lines.append(f"{i}\t\t\t\t</v8:item>")
|
||||
lines.append(f"{i}\t\t\t</dcscor:value>")
|
||||
else:
|
||||
lines.append(f'{i}\t\t\t<dcscor:value xsi:type="xs:string">{esc_xml(val)}</dcscor:value>')
|
||||
lines.append(f'{i}\t\t\t<dcscor:value xsi:type="xs:string">{esc_xml_text(val)}</dcscor:value>')
|
||||
|
||||
lines.append(f"{i}\t\t</dcscor:item>")
|
||||
lines.append(f"{i}\t</dcsset:appearance>")
|
||||
@@ -1546,7 +1551,7 @@ def build_structure_item_fragment(item, indent):
|
||||
lines = [f'{i}<dcsset:item xsi:type="dcsset:StructureItemGroup">']
|
||||
|
||||
if item.get("name"):
|
||||
lines.append(f"{i}\t<dcsset:name>{esc_xml(item['name'])}</dcsset:name>")
|
||||
lines.append(f"{i}\t<dcsset:name>{esc_xml_text(item['name'])}</dcsset:name>")
|
||||
|
||||
group_by = item.get("groupBy", [])
|
||||
if not group_by:
|
||||
@@ -1555,7 +1560,7 @@ def build_structure_item_fragment(item, indent):
|
||||
lines.append(f"{i}\t<dcsset:groupItems>")
|
||||
for field in group_by:
|
||||
lines.append(f'{i}\t\t<dcsset:item xsi:type="dcsset:GroupItemField">')
|
||||
lines.append(f"{i}\t\t\t<dcsset:field>{esc_xml(field)}</dcsset:field>")
|
||||
lines.append(f"{i}\t\t\t<dcsset:field>{esc_xml_text(field)}</dcsset:field>")
|
||||
lines.append(f"{i}\t\t\t<dcsset:groupType>Items</dcsset:groupType>")
|
||||
lines.append(f"{i}\t\t\t<dcsset:periodAdditionType>None</dcsset:periodAdditionType>")
|
||||
lines.append(f'{i}\t\t\t<dcsset:periodAdditionBegin xsi:type="xs:dateTime">0001-01-01T00:00:00</dcsset:periodAdditionBegin>')
|
||||
@@ -1585,17 +1590,17 @@ def build_output_param_fragment(parsed, indent):
|
||||
ptype = output_param_types.get(key, "xs:string")
|
||||
|
||||
lines = [f'{i}<dcscor:item xsi:type="dcsset:SettingsParameterValue">']
|
||||
lines.append(f"{i}\t<dcscor:parameter>{esc_xml(key)}</dcscor:parameter>")
|
||||
lines.append(f"{i}\t<dcscor:parameter>{esc_xml_text(key)}</dcscor:parameter>")
|
||||
|
||||
if ptype == "mltext":
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="v8:LocalStringType">')
|
||||
lines.append(f"{i}\t\t<v8:item>")
|
||||
lines.append(f"{i}\t\t\t<v8:lang>ru</v8:lang>")
|
||||
lines.append(f"{i}\t\t\t<v8:content>{esc_xml(val)}</v8:content>")
|
||||
lines.append(f"{i}\t\t\t<v8:content>{esc_xml_text(val)}</v8:content>")
|
||||
lines.append(f"{i}\t\t</v8:item>")
|
||||
lines.append(f"{i}\t</dcscor:value>")
|
||||
else:
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="{ptype}">{esc_xml(val)}</dcscor:value>')
|
||||
lines.append(f'{i}\t<dcscor:value xsi:type="{ptype}">{esc_xml_text(val)}</dcscor:value>')
|
||||
|
||||
lines.append(f"{i}</dcscor:item>")
|
||||
return "\n".join(lines)
|
||||
@@ -1732,7 +1737,7 @@ def set_or_create_child_element(parent, ln, ns_uri, value, indent):
|
||||
prefix = p
|
||||
break
|
||||
qual_name = f"{prefix}:{ln}" if prefix else ln
|
||||
frag_xml = f"{indent}<{qual_name}>{esc_xml(value)}</{qual_name}>"
|
||||
frag_xml = f"{indent}<{qual_name}>{esc_xml_text(value)}</{qual_name}>"
|
||||
nodes = import_fragment(xml_doc, frag_xml)
|
||||
for node in nodes:
|
||||
insert_before_element(parent, node, None, indent)
|
||||
@@ -1756,7 +1761,7 @@ def set_or_create_child_element_with_attr(parent, ln, ns_uri, value, xsi_type, i
|
||||
break
|
||||
qual_name = f"{prefix}:{ln}" if prefix else ln
|
||||
type_attr = f' xsi:type="{xsi_type}"' if xsi_type else ""
|
||||
frag_xml = f"{indent}<{qual_name}{type_attr}>{esc_xml(value)}</{qual_name}>"
|
||||
frag_xml = f"{indent}<{qual_name}{type_attr}>{esc_xml_text(value)}</{qual_name}>"
|
||||
nodes = import_fragment(xml_doc, frag_xml)
|
||||
for node in nodes:
|
||||
insert_before_element(parent, node, None, indent)
|
||||
@@ -2292,7 +2297,7 @@ elif operation == "modify-parameter":
|
||||
ref_node = None
|
||||
if key == "denyIncompleteValues":
|
||||
ref_node = next((ch for ch in param_el if isinstance(ch.tag, str) and local_name(ch) == "use"), None)
|
||||
frag_xml = f"{child_indent}<{key}>{esc_xml(value)}</{key}>"
|
||||
frag_xml = f"{child_indent}<{key}>{esc_xml_text(value)}</{key}>"
|
||||
nodes = import_fragment(xml_doc, frag_xml)
|
||||
for node in nodes:
|
||||
insert_before_element(param_el, node, ref_node, child_indent)
|
||||
@@ -2780,7 +2785,7 @@ elif operation == "modify-structure":
|
||||
for field in t["groupBy"]:
|
||||
lines = [
|
||||
f'{item_indent}<dcsset:item xsi:type="dcsset:GroupItemField">',
|
||||
f'{item_indent}\t<dcsset:field>{esc_xml(field)}</dcsset:field>',
|
||||
f'{item_indent}\t<dcsset:field>{esc_xml_text(field)}</dcsset:field>',
|
||||
f'{item_indent}\t<dcsset:groupType>Items</dcsset:groupType>',
|
||||
f'{item_indent}\t<dcsset:periodAdditionType>None</dcsset:periodAdditionType>',
|
||||
f'{item_indent}\t<dcsset:periodAdditionBegin xsi:type="xs:dateTime">0001-01-01T00:00:00</dcsset:periodAdditionBegin>',
|
||||
@@ -3039,18 +3044,18 @@ elif operation == "modify-dataParameter":
|
||||
pv = parsed["value"]
|
||||
if isinstance(pv, dict) and pv.get("variant"):
|
||||
val_lines.append(f'{item_indent}<dcscor:value xsi:type="v8:StandardPeriod">')
|
||||
val_lines.append(f'{item_indent}\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml(pv["variant"])}</v8:variant>')
|
||||
val_lines.append(f'{item_indent}\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml_text(pv["variant"])}</v8:variant>')
|
||||
val_lines.append(f"{item_indent}\t<v8:startDate>0001-01-01T00:00:00</v8:startDate>")
|
||||
val_lines.append(f"{item_indent}\t<v8:endDate>0001-01-01T00:00:00</v8:endDate>")
|
||||
val_lines.append(f"{item_indent}</dcscor:value>")
|
||||
elif is_empty_value(pv):
|
||||
val_lines.append(f'{item_indent}<dcscor:value xsi:nil="true"/>')
|
||||
elif re.match(r'^\d{4}-\d{2}-\d{2}T', str(pv)):
|
||||
val_lines.append(f'{item_indent}<dcscor:value xsi:type="xs:dateTime">{esc_xml(str(pv))}</dcscor:value>')
|
||||
val_lines.append(f'{item_indent}<dcscor:value xsi:type="xs:dateTime">{esc_xml_text(str(pv))}</dcscor:value>')
|
||||
elif str(pv) in ("true", "false"):
|
||||
val_lines.append(f'{item_indent}<dcscor:value xsi:type="xs:boolean">{esc_xml(str(pv))}</dcscor:value>')
|
||||
val_lines.append(f'{item_indent}<dcscor:value xsi:type="xs:boolean">{esc_xml_text(str(pv))}</dcscor:value>')
|
||||
else:
|
||||
val_lines.append(f'{item_indent}<dcscor:value xsi:type="xs:string">{esc_xml(str(pv))}</dcscor:value>')
|
||||
val_lines.append(f'{item_indent}<dcscor:value xsi:type="xs:string">{esc_xml_text(str(pv))}</dcscor:value>')
|
||||
|
||||
val_xml = "\n".join(val_lines)
|
||||
val_nodes = import_fragment(xml_doc, val_xml)
|
||||
@@ -3192,7 +3197,7 @@ elif operation == "set-field-role":
|
||||
else:
|
||||
lines.append(f"{field_indent}\t<dcscom:{flag}>true</dcscom:{flag}>")
|
||||
for k, v in kv:
|
||||
lines.append(f"{field_indent}\t<dcscom:{k}>{esc_xml(v)}</dcscom:{k}>")
|
||||
lines.append(f"{field_indent}\t<dcscom:{k}>{esc_xml_text(v)}</dcscom:{k}>")
|
||||
for raw in preserved_role_children:
|
||||
lines.append(f"{field_indent}\t" + raw)
|
||||
lines.append(f"{field_indent}</role>")
|
||||
|
||||
Reference in New Issue
Block a user