mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-10 05:23:21 +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 @@
|
||||
# cf-init v1.8 — Create empty 1C configuration scaffold
|
||||
# cf-init v1.9 — Create empty 1C configuration scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -16,6 +16,12 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Esc-XmlText {
|
||||
param([string]$s)
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>')
|
||||
}
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# --- Resolve output dir ---
|
||||
@@ -74,14 +80,14 @@ foreach ($mf in $mobileFuncs) {
|
||||
# --- Synonym XML ---
|
||||
$synonymXml = ""
|
||||
if ($Synonym) {
|
||||
$synonymXml = "`r`n`t`t`t`t<v8:item>`r`n`t`t`t`t`t<v8:lang>ru</v8:lang>`r`n`t`t`t`t`t<v8:content>$([System.Security.SecurityElement]::Escape($Synonym))</v8:content>`r`n`t`t`t`t</v8:item>`r`n`t`t`t"
|
||||
$synonymXml = "`r`n`t`t`t`t<v8:item>`r`n`t`t`t`t`t<v8:lang>ru</v8:lang>`r`n`t`t`t`t`t<v8:content>$(Esc-XmlText ($Synonym))</v8:content>`r`n`t`t`t`t</v8:item>`r`n`t`t`t"
|
||||
}
|
||||
|
||||
# --- Optional properties ---
|
||||
# Элемент целиком, а не значение внутри пары: при пустом значении Конфигуратор
|
||||
# пишет <Vendor/>, а не <Vendor></Vendor>.
|
||||
$vendorEl = if ($Vendor) { "<Vendor>$([System.Security.SecurityElement]::Escape($Vendor))</Vendor>" } else { "<Vendor/>" }
|
||||
$versionEl = if ($Version) { "<Version>$([System.Security.SecurityElement]::Escape($Version))</Version>" } else { "<Version/>" }
|
||||
$vendorEl = if ($Vendor) { "<Vendor>$(Esc-XmlText ($Vendor))</Vendor>" } else { "<Vendor/>" }
|
||||
$versionEl = if ($Version) { "<Version>$(Esc-XmlText ($Version))</Version>" } else { "<Version/>" }
|
||||
|
||||
# --- Свойства и пространство имён формата 2.21 (платформа 8.5) ---
|
||||
# Значения и ПОЗИЦИИ сняты с выгрузки 8.5.1 (debug/fmt221/dump_v851): те же исходники,
|
||||
@@ -143,7 +149,7 @@ $cfgXml = @"
|
||||
</xr:ContainedObject>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>$([System.Security.SecurityElement]::Escape($Name))</Name>
|
||||
<Name>$(Esc-XmlText ($Name))</Name>
|
||||
<Synonym>$synonymXml</Synonym>
|
||||
<Comment/>
|
||||
<NamePrefix/>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
# cf-init v1.8 — Create empty 1C configuration scaffold
|
||||
# cf-init v1.9 — Create empty 1C configuration scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""Generates minimal XML source files for a 1C configuration."""
|
||||
import sys, os, argparse, re, uuid
|
||||
|
||||
def esc_xml(s):
|
||||
return s.replace('&','&').replace('<','<').replace('>','>').replace('"','"')
|
||||
def esc_xml_text(s):
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
|
||||
def new_uuid():
|
||||
return str(uuid.uuid4())
|
||||
@@ -96,12 +97,12 @@ def main():
|
||||
# --- Synonym XML ---
|
||||
synonym_xml = ""
|
||||
if synonym:
|
||||
synonym_xml = f"\r\n\t\t\t\t<v8:item>\r\n\t\t\t\t\t<v8:lang>ru</v8:lang>\r\n\t\t\t\t\t<v8:content>{esc_xml(synonym)}</v8:content>\r\n\t\t\t\t</v8:item>\r\n\t\t\t"
|
||||
synonym_xml = f"\r\n\t\t\t\t<v8:item>\r\n\t\t\t\t\t<v8:lang>ru</v8:lang>\r\n\t\t\t\t\t<v8:content>{esc_xml_text(synonym)}</v8:content>\r\n\t\t\t\t</v8:item>\r\n\t\t\t"
|
||||
|
||||
# Элемент целиком, а не значение внутри пары: при пустом значении Конфигуратор
|
||||
# пишет <Vendor/>, а не <Vendor></Vendor>.
|
||||
vendor_el = f"<Vendor>{esc_xml(vendor)}</Vendor>" if vendor else "<Vendor/>"
|
||||
version_el = f"<Version>{esc_xml(version)}</Version>" if version else "<Version/>"
|
||||
vendor_el = f"<Vendor>{esc_xml_text(vendor)}</Vendor>" if vendor else "<Vendor/>"
|
||||
version_el = f"<Version>{esc_xml_text(version)}</Version>" if version else "<Version/>"
|
||||
|
||||
class_ids = [
|
||||
"9cd510cd-abfc-11d4-9434-004095e12fc7",
|
||||
@@ -148,7 +149,7 @@ def main():
|
||||
\t\t<InternalInfo>
|
||||
{contained_objects}\t\t</InternalInfo>
|
||||
\t\t<Properties>
|
||||
\t\t\t<Name>{esc_xml(name)}</Name>
|
||||
\t\t\t<Name>{esc_xml_text(name)}</Name>
|
||||
\t\t\t<Synonym>{synonym_xml}</Synonym>
|
||||
\t\t\t<Comment/>
|
||||
\t\t\t<NamePrefix/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# cfe-init v1.7 — Create 1C configuration extension scaffold (CFE)
|
||||
# cfe-init v1.8 — Create 1C configuration extension scaffold (CFE) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -16,6 +16,12 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Esc-XmlText {
|
||||
param([string]$s)
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>')
|
||||
}
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# --- Default NamePrefix ---
|
||||
@@ -121,14 +127,14 @@ $co7 = [guid]::NewGuid().ToString()
|
||||
# --- Synonym XML ---
|
||||
$synonymXml = ""
|
||||
if ($Synonym) {
|
||||
$synonymXml = "`r`n`t`t`t`t<v8:item>`r`n`t`t`t`t`t<v8:lang>ru</v8:lang>`r`n`t`t`t`t`t<v8:content>$([System.Security.SecurityElement]::Escape($Synonym))</v8:content>`r`n`t`t`t`t</v8:item>`r`n`t`t`t"
|
||||
$synonymXml = "`r`n`t`t`t`t<v8:item>`r`n`t`t`t`t`t<v8:lang>ru</v8:lang>`r`n`t`t`t`t`t<v8:content>$(Esc-XmlText ($Synonym))</v8:content>`r`n`t`t`t`t</v8:item>`r`n`t`t`t"
|
||||
}
|
||||
|
||||
# --- Optional properties ---
|
||||
# Элемент целиком, а не значение внутри пары: при пустом значении Конфигуратор
|
||||
# пишет <Vendor/>, а не <Vendor></Vendor>.
|
||||
$vendorEl = if ($Vendor) { "<Vendor>$([System.Security.SecurityElement]::Escape($Vendor))</Vendor>" } else { "<Vendor/>" }
|
||||
$versionEl = if ($Version) { "<Version>$([System.Security.SecurityElement]::Escape($Version))</Version>" } else { "<Version/>" }
|
||||
$vendorEl = if ($Vendor) { "<Vendor>$(Esc-XmlText ($Vendor))</Vendor>" } else { "<Vendor/>" }
|
||||
$versionEl = if ($Version) { "<Version>$(Esc-XmlText ($Version))</Version>" } else { "<Version/>" }
|
||||
|
||||
# --- Role name ---
|
||||
$roleName = "${NamePrefix}ОсновнаяРоль"
|
||||
@@ -206,12 +212,12 @@ $cfgXml = @"
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<ObjectBelonging>Adopted</ObjectBelonging>
|
||||
<Name>$([System.Security.SecurityElement]::Escape($Name))</Name>
|
||||
<Name>$(Esc-XmlText ($Name))</Name>
|
||||
<Synonym>$synonymXml</Synonym>
|
||||
<Comment/>
|
||||
<ConfigurationExtensionPurpose>$Purpose</ConfigurationExtensionPurpose>
|
||||
<KeepMappingToExtendedConfigurationObjectsByIDs>true</KeepMappingToExtendedConfigurationObjectsByIDs>
|
||||
<NamePrefix>$([System.Security.SecurityElement]::Escape($NamePrefix))</NamePrefix>
|
||||
<NamePrefix>$(Esc-XmlText ($NamePrefix))</NamePrefix>
|
||||
<ConfigurationExtensionCompatibilityMode>$CompatibilityMode</ConfigurationExtensionCompatibilityMode>
|
||||
<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
||||
<UsePurposes>
|
||||
@@ -257,7 +263,7 @@ $roleXml = @"
|
||||
<MetaDataObject $xmlnsDecl version="$formatVersion">
|
||||
<Role uuid="$uuidRole">
|
||||
<Properties>
|
||||
<Name>$([System.Security.SecurityElement]::Escape($roleName))</Name>
|
||||
<Name>$(Esc-XmlText ($roleName))</Name>
|
||||
<Synonym/>
|
||||
<Comment/>
|
||||
</Properties>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
# cfe-init v1.7 — Create 1C configuration extension scaffold (CFE)
|
||||
# cfe-init v1.8 — Create 1C configuration extension scaffold (CFE) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""Generates minimal XML source files for a 1C configuration extension."""
|
||||
import sys, os, re, argparse, uuid
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
def esc_xml(s):
|
||||
return s.replace('&','&').replace('<','<').replace('>','>').replace('"','"')
|
||||
def esc_xml_text(s):
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
|
||||
def new_uuid():
|
||||
return str(uuid.uuid4())
|
||||
@@ -142,12 +143,12 @@ def main():
|
||||
# --- Synonym XML ---
|
||||
synonym_xml = ""
|
||||
if synonym:
|
||||
synonym_xml = f"\r\n\t\t\t\t<v8:item>\r\n\t\t\t\t\t<v8:lang>ru</v8:lang>\r\n\t\t\t\t\t<v8:content>{esc_xml(synonym)}</v8:content>\r\n\t\t\t\t</v8:item>\r\n\t\t\t"
|
||||
synonym_xml = f"\r\n\t\t\t\t<v8:item>\r\n\t\t\t\t\t<v8:lang>ru</v8:lang>\r\n\t\t\t\t\t<v8:content>{esc_xml_text(synonym)}</v8:content>\r\n\t\t\t\t</v8:item>\r\n\t\t\t"
|
||||
|
||||
# Элемент целиком, а не значение внутри пары: при пустом значении Конфигуратор
|
||||
# пишет <Vendor/>, а не <Vendor></Vendor>.
|
||||
vendor_el = f"<Vendor>{esc_xml(vendor)}</Vendor>" if vendor else "<Vendor/>"
|
||||
version_el = f"<Version>{esc_xml(version)}</Version>" if version else "<Version/>"
|
||||
vendor_el = f"<Vendor>{esc_xml_text(vendor)}</Vendor>" if vendor else "<Vendor/>"
|
||||
version_el = f"<Version>{esc_xml_text(version)}</Version>" if version else "<Version/>"
|
||||
|
||||
# --- Role name ---
|
||||
role_name = f"{name_prefix}ОсновнаяРоль"
|
||||
@@ -224,12 +225,12 @@ def main():
|
||||
{contained_objects}\t\t</InternalInfo>
|
||||
\t\t<Properties>
|
||||
\t\t\t<ObjectBelonging>Adopted</ObjectBelonging>
|
||||
\t\t\t<Name>{esc_xml(name)}</Name>
|
||||
\t\t\t<Name>{esc_xml_text(name)}</Name>
|
||||
\t\t\t<Synonym>{synonym_xml}</Synonym>
|
||||
\t\t\t<Comment/>
|
||||
\t\t\t<ConfigurationExtensionPurpose>{purpose}</ConfigurationExtensionPurpose>
|
||||
\t\t\t<KeepMappingToExtendedConfigurationObjectsByIDs>true</KeepMappingToExtendedConfigurationObjectsByIDs>
|
||||
\t\t\t<NamePrefix>{esc_xml(name_prefix)}</NamePrefix>
|
||||
\t\t\t<NamePrefix>{esc_xml_text(name_prefix)}</NamePrefix>
|
||||
\t\t\t<ConfigurationExtensionCompatibilityMode>{compat}</ConfigurationExtensionCompatibilityMode>
|
||||
\t\t\t<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
||||
\t\t\t<UsePurposes>
|
||||
@@ -271,7 +272,7 @@ def main():
|
||||
<MetaDataObject {xmlns_decl} version="{format_version}">
|
||||
\t<Role uuid="{uuid_role}">
|
||||
\t\t<Properties>
|
||||
\t\t\t<Name>{esc_xml(role_name)}</Name>
|
||||
\t\t\t<Name>{esc_xml_text(role_name)}</Name>
|
||||
\t\t\t<Synonym/>
|
||||
\t\t\t<Comment/>
|
||||
\t\t</Properties>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# epf-init v1.4 — Init 1C external data processor scaffold
|
||||
# epf-init v1.5 — Init 1C external data processor scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -16,6 +16,12 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Esc-XmlText {
|
||||
param([string]$s)
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>')
|
||||
}
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
@@ -47,11 +53,11 @@ $xml = @"
|
||||
</xr:GeneratedType>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>$Name</Name>
|
||||
<Name>$(Esc-XmlText $Name)</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>$Synonym</v8:content>
|
||||
<v8:content>$(Esc-XmlText $Synonym)</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
# epf-init v1.4 — Init 1C external data processor scaffold
|
||||
# epf-init v1.5 — Init 1C external data processor scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""Generates minimal XML source files for a 1C external data processor."""
|
||||
import sys, os, re, argparse, uuid
|
||||
|
||||
def esc_xml(s):
|
||||
return s.replace('&','&').replace('<','<').replace('>','>').replace('"','"')
|
||||
def esc_xml_text(s):
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
|
||||
def new_uuid():
|
||||
return str(uuid.uuid4())
|
||||
@@ -95,11 +96,11 @@ def main():
|
||||
\t\t\t</xr:GeneratedType>
|
||||
\t\t</InternalInfo>
|
||||
\t\t<Properties>
|
||||
\t\t\t<Name>{esc_xml(name)}</Name>
|
||||
\t\t\t<Name>{esc_xml_text(name)}</Name>
|
||||
\t\t\t<Synonym>
|
||||
\t\t\t\t<v8:item>
|
||||
\t\t\t\t\t<v8:lang>ru</v8:lang>
|
||||
\t\t\t\t\t<v8:content>{esc_xml(synonym)}</v8:content>
|
||||
\t\t\t\t\t<v8:content>{esc_xml_text(synonym)}</v8:content>
|
||||
\t\t\t\t</v8:item>
|
||||
\t\t\t</Synonym>
|
||||
\t\t\t<Comment/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# erf-init v1.4 — Init 1C external report scaffold
|
||||
# erf-init v1.5 — Init 1C external report scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -18,6 +18,12 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Esc-XmlText {
|
||||
param([string]$s)
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>')
|
||||
}
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
@@ -75,11 +81,11 @@ $xml = @"
|
||||
</xr:GeneratedType>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>$Name</Name>
|
||||
<Name>$(Esc-XmlText $Name)</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>$Synonym</v8:content>
|
||||
<v8:content>$(Esc-XmlText $Synonym)</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
# erf-init v1.4 — Init 1C external report scaffold
|
||||
# erf-init v1.5 — Init 1C external report scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""Generates minimal XML source files for a 1C external report."""
|
||||
import sys, os, re, argparse, uuid
|
||||
|
||||
def esc_xml(s):
|
||||
return s.replace('&','&').replace('<','<').replace('>','>').replace('"','"')
|
||||
def esc_xml_text(s):
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
|
||||
def new_uuid():
|
||||
return str(uuid.uuid4())
|
||||
@@ -107,11 +108,11 @@ def main():
|
||||
\t\t\t</xr:GeneratedType>
|
||||
\t\t</InternalInfo>
|
||||
\t\t<Properties>
|
||||
\t\t\t<Name>{esc_xml(name)}</Name>
|
||||
\t\t\t<Name>{esc_xml_text(name)}</Name>
|
||||
\t\t\t<Synonym>
|
||||
\t\t\t\t<v8:item>
|
||||
\t\t\t\t\t<v8:lang>ru</v8:lang>
|
||||
\t\t\t\t\t<v8:content>{esc_xml(synonym)}</v8:content>
|
||||
\t\t\t\t\t<v8:content>{esc_xml_text(synonym)}</v8:content>
|
||||
\t\t\t\t</v8:item>
|
||||
\t\t\t</Synonym>
|
||||
\t\t\t<Comment/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# form-compile v1.187 — Compile 1C managed form from JSON or object metadata (+resolve_type_str: срезание префикса cfg:/d5p1:)
|
||||
# form-compile v1.188 — Compile 1C managed form from JSON or object metadata (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[string]$JsonPath,
|
||||
@@ -1705,6 +1705,12 @@ function X {
|
||||
}
|
||||
|
||||
function Esc-Xml {
|
||||
param([string]$s)
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>').Replace('"','"')
|
||||
}
|
||||
|
||||
function Esc-XmlText {
|
||||
# Экранирование ТЕКСТА элемента (<v8:content>, <Value>): только & < > .
|
||||
# Кавычки/апострофы в тексте экранировать НЕ нужно (1С их не экранирует — пишет литерально);
|
||||
# " ломал бы раундтрип. Кавычки спецсимвольны лишь в значениях атрибутов.
|
||||
@@ -1719,14 +1725,14 @@ function Emit-MLItems {
|
||||
param($val, [string]$indent)
|
||||
if ($val -is [System.Collections.IDictionary]) {
|
||||
foreach ($k in $val.Keys) {
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>$k</v8:lang>"; X "$indent`t<v8:content>$(Esc-Xml "$($val[$k])")</v8:content>"; X "$indent</v8:item>"
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>$k</v8:lang>"; X "$indent`t<v8:content>$(Esc-XmlText "$($val[$k])")</v8:content>"; X "$indent</v8:item>"
|
||||
}
|
||||
} elseif ($val -is [System.Management.Automation.PSCustomObject]) {
|
||||
foreach ($p in $val.PSObject.Properties) {
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>$($p.Name)</v8:lang>"; X "$indent`t<v8:content>$(Esc-Xml "$($p.Value)")</v8:content>"; X "$indent</v8:item>"
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>$($p.Name)</v8:lang>"; X "$indent`t<v8:content>$(Esc-XmlText "$($p.Value)")</v8:content>"; X "$indent</v8:item>"
|
||||
}
|
||||
} else {
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>ru</v8:lang>"; X "$indent`t<v8:content>$(Esc-Xml "$val")</v8:content>"; X "$indent</v8:item>"
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>ru</v8:lang>"; X "$indent`t<v8:content>$(Esc-XmlText "$val")</v8:content>"; X "$indent</v8:item>"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1745,7 +1751,7 @@ function Emit-USPresentation {
|
||||
param($val, [string]$tag, [string]$indent)
|
||||
if ($null -eq $val) { return }
|
||||
if ($val -is [string]) {
|
||||
X "$indent<$tag xsi:type=`"xs:string`">$(Esc-Xml $val)</$tag>"
|
||||
X "$indent<$tag xsi:type=`"xs:string`">$(Esc-XmlText $val)</$tag>"
|
||||
} else {
|
||||
Emit-MLText -tag $tag -text $val -indent $indent -xsiType "v8:LocalStringType"
|
||||
}
|
||||
@@ -1874,10 +1880,10 @@ function Emit-FilterItem {
|
||||
}
|
||||
}
|
||||
if ($item.presentation) { Emit-USPresentation -val $item.presentation -tag "dcsset:presentation" -indent "$indent`t" }
|
||||
if ($item.viewMode) { X "$indent`t<dcsset:viewMode>$(Esc-Xml "$($item.viewMode)")</dcsset:viewMode>" }
|
||||
if ($item.viewMode) { X "$indent`t<dcsset:viewMode>$(Esc-XmlText "$($item.viewMode)")</dcsset:viewMode>" }
|
||||
if ($item.userSettingID) {
|
||||
$guid = if ("$($item.userSettingID)" -eq "auto") { New-Guid-String } else { "$($item.userSettingID)" }
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-Xml $guid)</dcsset:userSettingID>"
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-XmlText $guid)</dcsset:userSettingID>"
|
||||
}
|
||||
if ($item.userSettingPresentation) { Emit-USPresentation -val $item.userSettingPresentation -tag "dcsset:userSettingPresentation" -indent "$indent`t" }
|
||||
X "$indent</dcsset:item>"
|
||||
@@ -1885,10 +1891,10 @@ function Emit-FilterItem {
|
||||
}
|
||||
X "$indent<dcsset:item xsi:type=`"dcsset:FilterItemComparison`">"
|
||||
if ($item.use -eq $false) { X "$indent`t<dcsset:use>false</dcsset:use>" }
|
||||
X "$indent`t<dcsset:left xsi:type=`"dcscor:Field`">$(Esc-Xml "$($item.field)")</dcsset:left>"
|
||||
X "$indent`t<dcsset:left xsi:type=`"dcscor:Field`">$(Esc-XmlText "$($item.field)")</dcsset:left>"
|
||||
$compType = $script:comparisonTypes["$($item.op)"]
|
||||
if (-not $compType) { $compType = "$($item.op)" }
|
||||
X "$indent`t<dcsset:comparisonType>$(Esc-Xml $compType)</dcsset:comparisonType>"
|
||||
X "$indent`t<dcsset:comparisonType>$(Esc-XmlText $compType)</dcsset:comparisonType>"
|
||||
$valIsArray = ($item.value -is [array]) -or ($item.value -is [System.Collections.IList] -and $item.value -isnot [string])
|
||||
if ($valIsArray) {
|
||||
if (@($item.value).Count -eq 0) {
|
||||
@@ -1907,7 +1913,7 @@ function Emit-FilterItem {
|
||||
elseif ("$v" -match '^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена|Catalog|Enum|Document|ChartOfAccounts|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.') { $vt = 'dcscor:DesignTimeValue' }
|
||||
else { $vt = 'xs:string' }
|
||||
}
|
||||
$vStr = if ($v -is [bool]) { "$v".ToLower() } else { Esc-Xml "$v" }
|
||||
$vStr = if ($v -is [bool]) { "$v".ToLower() } else { Esc-XmlText "$v" }
|
||||
$nsAttr = Get-ValueTypeNsAttr -valueType $vt -value "$v"
|
||||
X "$indent`t<dcsset:right$nsAttr xsi:type=`"$vt`">$vStr</dcsset:right>"
|
||||
}
|
||||
@@ -1933,8 +1939,8 @@ function Emit-FilterItem {
|
||||
$variant = "$sv"; $hasDate = $false; $dateV = $null
|
||||
}
|
||||
X "$indent`t<dcsset:right xsi:type=`"v8:$sdType`">"
|
||||
X "$indent`t`t<v8:variant xsi:type=`"v8:${sdType}Variant`">$(Esc-Xml $variant)</v8:variant>"
|
||||
if ($hasDate) { X "$indent`t`t<v8:date>$(Esc-Xml $dateV)</v8:date>" }
|
||||
X "$indent`t`t<v8:variant xsi:type=`"v8:${sdType}Variant`">$(Esc-XmlText $variant)</v8:variant>"
|
||||
if ($hasDate) { X "$indent`t`t<v8:date>$(Esc-XmlText $dateV)</v8:date>" }
|
||||
X "$indent`t</dcsset:right>"
|
||||
} elseif ("$($item.value)" -eq '_') {
|
||||
# "_" — маркер пустого значения: платформа эмитит пустой self-closing <dcsset:right>
|
||||
@@ -1952,15 +1958,15 @@ function Emit-FilterItem {
|
||||
elseif ("$v" -match '^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена|Catalog|Enum|Document|ChartOfAccounts|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.') { $vt = "dcscor:DesignTimeValue" }
|
||||
else { $vt = "xs:string" }
|
||||
}
|
||||
$vStr = if ($item.value -is [bool]) { "$($item.value)".ToLower() } else { Esc-Xml "$($item.value)" }
|
||||
$vStr = if ($item.value -is [bool]) { "$($item.value)".ToLower() } else { Esc-XmlText "$($item.value)" }
|
||||
$nsAttr = Get-ValueTypeNsAttr -valueType $vt -value "$($item.value)"
|
||||
X "$indent`t<dcsset:right$nsAttr xsi:type=`"$vt`">$vStr</dcsset:right>"
|
||||
}
|
||||
if ($item.presentation) { Emit-USPresentation -val $item.presentation -tag "dcsset:presentation" -indent "$indent`t" }
|
||||
if ($item.viewMode) { X "$indent`t<dcsset:viewMode>$(Esc-Xml "$($item.viewMode)")</dcsset:viewMode>" }
|
||||
if ($item.viewMode) { X "$indent`t<dcsset:viewMode>$(Esc-XmlText "$($item.viewMode)")</dcsset:viewMode>" }
|
||||
if ($item.userSettingID) {
|
||||
$uid = if ("$($item.userSettingID)" -eq "auto") { New-Guid-String } else { "$($item.userSettingID)" }
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-XmlText $uid)</dcsset:userSettingID>"
|
||||
}
|
||||
if ($item.userSettingPresentation) { Emit-USPresentation -val $item.userSettingPresentation -tag "dcsset:userSettingPresentation" -indent "$indent`t" }
|
||||
X "$indent</dcsset:item>"
|
||||
@@ -1984,10 +1990,10 @@ function Emit-Filter {
|
||||
Emit-FilterItem -item ([pscustomobject]$obj) -indent "$indent`t"
|
||||
} else { Emit-FilterItem -item $item -indent "$indent`t" }
|
||||
}
|
||||
if ($null -ne $blockViewMode) { X "$indent`t<dcsset:viewMode>$(Esc-Xml "$blockViewMode")</dcsset:viewMode>" }
|
||||
if ($null -ne $blockViewMode) { X "$indent`t<dcsset:viewMode>$(Esc-XmlText "$blockViewMode")</dcsset:viewMode>" }
|
||||
if ($null -ne $blockUserSettingID) {
|
||||
$uid = if ("$blockUserSettingID" -eq 'auto') { New-Guid-String } else { "$blockUserSettingID" }
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-XmlText $uid)</dcsset:userSettingID>"
|
||||
}
|
||||
if ($null -ne $blockUserSettingPresentation) { Emit-USPresentation -val $blockUserSettingPresentation -tag "dcsset:userSettingPresentation" -indent "$indent`t" }
|
||||
X "$indent</dcsset:filter>"
|
||||
@@ -2009,7 +2015,7 @@ function Emit-Order {
|
||||
if ($parts.Count -gt 1 -and $parts[1] -match '^(?i)(desc|убыв)') { $dir = "Desc" }
|
||||
elseif ($parts.Count -gt 1 -and $parts[1] -match '^(?i)(asc|возр)') { $dir = "Asc" }
|
||||
X "$indent`t<dcsset:item xsi:type=`"dcsset:OrderItemField`">"
|
||||
X "$indent`t`t<dcsset:field>$(Esc-Xml $field)</dcsset:field>"
|
||||
X "$indent`t`t<dcsset:field>$(Esc-XmlText $field)</dcsset:field>"
|
||||
X "$indent`t`t<dcsset:orderType>$dir</dcsset:orderType>"
|
||||
X "$indent`t</dcsset:item>"
|
||||
}
|
||||
@@ -2019,16 +2025,16 @@ function Emit-Order {
|
||||
if ($dir -match '^(?i)(desc|убыв)') { $dir = "Desc" } elseif ($dir -match '^(?i)(asc|возр)') { $dir = "Asc" }
|
||||
X "$indent`t<dcsset:item xsi:type=`"dcsset:OrderItemField`">"
|
||||
if ($item.use -eq $false) { X "$indent`t`t<dcsset:use>false</dcsset:use>" }
|
||||
X "$indent`t`t<dcsset:field>$(Esc-Xml "$($item.field)")</dcsset:field>"
|
||||
X "$indent`t`t<dcsset:field>$(Esc-XmlText "$($item.field)")</dcsset:field>"
|
||||
X "$indent`t`t<dcsset:orderType>$dir</dcsset:orderType>"
|
||||
if ($item.viewMode) { X "$indent`t`t<dcsset:viewMode>$(Esc-Xml "$($item.viewMode)")</dcsset:viewMode>" }
|
||||
if ($item.viewMode) { X "$indent`t`t<dcsset:viewMode>$(Esc-XmlText "$($item.viewMode)")</dcsset:viewMode>" }
|
||||
X "$indent`t</dcsset:item>"
|
||||
}
|
||||
}
|
||||
if ($null -ne $blockViewMode) { X "$indent`t<dcsset:viewMode>$(Esc-Xml "$blockViewMode")</dcsset:viewMode>" }
|
||||
if ($null -ne $blockViewMode) { X "$indent`t<dcsset:viewMode>$(Esc-XmlText "$blockViewMode")</dcsset:viewMode>" }
|
||||
if ($null -ne $blockUserSettingID) {
|
||||
$uid = if ("$blockUserSettingID" -eq 'auto') { New-Guid-String } else { "$blockUserSettingID" }
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-XmlText $uid)</dcsset:userSettingID>"
|
||||
}
|
||||
if ($null -ne $blockUserSettingPresentation) { Emit-USPresentation -val $blockUserSettingPresentation -tag "dcsset:userSettingPresentation" -indent "$indent`t" }
|
||||
X "$indent</dcsset:order>"
|
||||
@@ -2060,7 +2066,7 @@ function Emit-AppearanceValue {
|
||||
if (_HasKey $val 'items') { $nestedItems = (_Get $val 'items') }
|
||||
}
|
||||
if ($useWrapper) { X "$indent`t<dcscor:use>false</dcscor:use>" }
|
||||
X "$indent`t<dcscor:parameter>$(Esc-Xml $key)</dcscor:parameter>"
|
||||
X "$indent`t<dcscor:parameter>$(Esc-XmlText $key)</dcscor:parameter>"
|
||||
$isFontDict = $false
|
||||
if ($innerVal -is [PSCustomObject]) {
|
||||
$tProp = $innerVal.PSObject.Properties['@type']
|
||||
@@ -2076,7 +2082,7 @@ function Emit-AppearanceValue {
|
||||
$lg = if (_HasKey $innerVal 'gap') { if ((_Get $innerVal 'gap')) { 'true' } else { 'false' } } else { 'false' }
|
||||
$ls = if (_HasKey $innerVal 'style') { "$(_Get $innerVal 'style')" } else { 'None' }
|
||||
X "$indent`t<dcscor:value xsi:type=`"v8ui:Line`" width=`"$lw`" gap=`"$lg`">"
|
||||
X "$indent`t`t<v8ui:style xsi:type=`"v8ui:SpreadsheetDocumentCellLineType`">$(Esc-Xml $ls)</v8ui:style>"
|
||||
X "$indent`t`t<v8ui:style xsi:type=`"v8ui:SpreadsheetDocumentCellLineType`">$(Esc-XmlText $ls)</v8ui:style>"
|
||||
X "$indent`t</dcscor:value>"
|
||||
} elseif ($isFontDict) {
|
||||
$attrParts = @()
|
||||
@@ -2089,7 +2095,7 @@ function Emit-AppearanceValue {
|
||||
X "$indent`t<dcscor:value xsi:type=`"v8ui:Font`" $($attrParts -join ' ')/>"
|
||||
} elseif ($isDict -and (_HasKey $innerVal 'field')) {
|
||||
# Ссылка на поле (dcscor:Field) — значение параметра оформления = поле компоновки
|
||||
X "$indent`t<dcscor:value xsi:type=`"dcscor:Field`">$(Esc-Xml "$(_Get $innerVal 'field')")</dcscor:value>"
|
||||
X "$indent`t<dcscor:value xsi:type=`"dcscor:Field`">$(Esc-XmlText "$(_Get $innerVal 'field')")</dcscor:value>"
|
||||
} elseif ($isDict) {
|
||||
# Локализуемый текст параметра оформления: платформа объявляет xsi:type на dcscor:value
|
||||
Emit-MLText -tag "dcscor:value" -text $innerVal -indent "$indent`t" -xsiType "v8:LocalStringType"
|
||||
@@ -2104,19 +2110,19 @@ function Emit-AppearanceValue {
|
||||
'ТипМакета' = 'dcsset:DataCompositionGroupTemplateType'
|
||||
}
|
||||
$keyType = $keyTypeMap[$key]
|
||||
if ($keyType) { X "$indent`t<dcscor:value xsi:type=`"$keyType`">$(Esc-Xml $actualVal)</dcscor:value>" }
|
||||
elseif ($actualVal -match '^(style|web|win):') { X "$indent`t<dcscor:value xsi:type=`"v8ui:Color`">$(Esc-Xml $actualVal)</dcscor:value>" }
|
||||
if ($keyType) { X "$indent`t<dcscor:value xsi:type=`"$keyType`">$(Esc-XmlText $actualVal)</dcscor:value>" }
|
||||
elseif ($actualVal -match '^(style|web|win):') { X "$indent`t<dcscor:value xsi:type=`"v8ui:Color`">$(Esc-XmlText $actualVal)</dcscor:value>" }
|
||||
elseif ($actualVal -eq "true" -or $actualVal -eq "false") { X "$indent`t<dcscor:value xsi:type=`"xs:boolean`">$actualVal</dcscor:value>" }
|
||||
elseif ($key -eq "Текст" -or $key -eq "Заголовок" -or $key -eq "Формат") {
|
||||
# Текст/Заголовок/Формат: голая строка = плоский xs:string (так платформа хранит
|
||||
# нелокализованный литерал). Локализуемый текст → объект {ru,en} (ветка isDict выше).
|
||||
# Пустая строка → самозакрывающийся тег (как у платформы).
|
||||
if ($actualVal -eq '') { X "$indent`t<dcscor:value xsi:type=`"xs:string`"/>" }
|
||||
else { X "$indent`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml $actualVal)</dcscor:value>" }
|
||||
else { X "$indent`t<dcscor:value xsi:type=`"xs:string`">$(Esc-XmlText $actualVal)</dcscor:value>" }
|
||||
}
|
||||
elseif ($actualVal -match '^-?\d+(\.\d+)?$') { X "$indent`t<dcscor:value xsi:type=`"xs:decimal`">$actualVal</dcscor:value>" }
|
||||
elseif ($key -eq 'ЦветТекста' -or $key -eq 'ЦветФона' -or $key -eq 'ЦветГраницы') { X "$indent`t<dcscor:value xsi:type=`"v8ui:Color`">$(Esc-Xml $actualVal)</dcscor:value>" }
|
||||
else { X "$indent`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml $actualVal)</dcscor:value>" }
|
||||
elseif ($key -eq 'ЦветТекста' -or $key -eq 'ЦветФона' -or $key -eq 'ЦветГраницы') { X "$indent`t<dcscor:value xsi:type=`"v8ui:Color`">$(Esc-XmlText $actualVal)</dcscor:value>" }
|
||||
else { X "$indent`t<dcscor:value xsi:type=`"xs:string`">$(Esc-XmlText $actualVal)</dcscor:value>" }
|
||||
}
|
||||
if ($nestedItems) {
|
||||
$niProps = if ($nestedItems -is [PSCustomObject]) { $nestedItems.PSObject.Properties } else { $null }
|
||||
@@ -2139,7 +2145,7 @@ function Emit-ConditionalAppearance {
|
||||
X "$indent`t`t<dcsset:selection>"
|
||||
foreach ($sel in $ca.selection) {
|
||||
X "$indent`t`t`t<dcsset:item>"
|
||||
X "$indent`t`t`t`t<dcsset:field>$(Esc-Xml "$sel")</dcsset:field>"
|
||||
X "$indent`t`t`t`t<dcsset:field>$(Esc-XmlText "$sel")</dcsset:field>"
|
||||
X "$indent`t`t`t</dcsset:item>"
|
||||
}
|
||||
X "$indent`t`t</dcsset:selection>"
|
||||
@@ -2158,12 +2164,12 @@ function Emit-ConditionalAppearance {
|
||||
Emit-MLItems -val $ca.presentation -indent "$indent`t`t`t"
|
||||
X "$indent`t`t</dcsset:presentation>"
|
||||
}
|
||||
else { X "$indent`t`t<dcsset:presentation xsi:type=`"xs:string`">$(Esc-Xml "$($ca.presentation)")</dcsset:presentation>" }
|
||||
else { X "$indent`t`t<dcsset:presentation xsi:type=`"xs:string`">$(Esc-XmlText "$($ca.presentation)")</dcsset:presentation>" }
|
||||
}
|
||||
if ($ca.viewMode) { X "$indent`t`t<dcsset:viewMode>$(Esc-Xml "$($ca.viewMode)")</dcsset:viewMode>" }
|
||||
if ($ca.viewMode) { X "$indent`t`t<dcsset:viewMode>$(Esc-XmlText "$($ca.viewMode)")</dcsset:viewMode>" }
|
||||
if ($ca.userSettingID) {
|
||||
$uid = if ("$($ca.userSettingID)" -eq "auto") { New-Guid-String } else { "$($ca.userSettingID)" }
|
||||
X "$indent`t`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
|
||||
X "$indent`t`t<dcsset:userSettingID>$(Esc-XmlText $uid)</dcsset:userSettingID>"
|
||||
}
|
||||
if ($ca.userSettingPresentation) { Emit-USPresentation -val $ca.userSettingPresentation -tag "dcsset:userSettingPresentation" -indent "$indent`t`t" }
|
||||
if ($ca.useInDontUse -and $ca.useInDontUse.Count -gt 0) {
|
||||
@@ -2179,10 +2185,10 @@ function Emit-ConditionalAppearance {
|
||||
}
|
||||
X "$indent`t</dcsset:item>"
|
||||
}
|
||||
if ($null -ne $blockViewMode) { X "$indent`t<dcsset:viewMode>$(Esc-Xml "$blockViewMode")</dcsset:viewMode>" }
|
||||
if ($null -ne $blockViewMode) { X "$indent`t<dcsset:viewMode>$(Esc-XmlText "$blockViewMode")</dcsset:viewMode>" }
|
||||
if ($null -ne $blockUserSettingID) {
|
||||
$uid = if ("$blockUserSettingID" -eq 'auto') { New-Guid-String } else { "$blockUserSettingID" }
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
|
||||
X "$indent`t<dcsset:userSettingID>$(Esc-XmlText $uid)</dcsset:userSettingID>"
|
||||
}
|
||||
if ($null -ne $blockUserSettingPresentation) { Emit-USPresentation -val $blockUserSettingPresentation -tag "dcsset:userSettingPresentation" -indent "$indent`t" }
|
||||
X "$indent</$wrapTag>"
|
||||
@@ -2221,14 +2227,14 @@ function Emit-GroupItemField {
|
||||
$pae = if ($level.periodAdditionEnd) { "$($level.periodAdditionEnd)" } else { '0001-01-01T00:00:00' }
|
||||
}
|
||||
X "$indent<dcsset:item xsi:type=`"dcsset:GroupItemField`">"
|
||||
X "$indent`t<dcsset:field>$(Esc-Xml $field)</dcsset:field>"
|
||||
X "$indent`t<dcsset:groupType>$(Esc-Xml $gt)</dcsset:groupType>"
|
||||
X "$indent`t<dcsset:periodAdditionType>$(Esc-Xml $pat)</dcsset:periodAdditionType>"
|
||||
X "$indent`t<dcsset:field>$(Esc-XmlText $field)</dcsset:field>"
|
||||
X "$indent`t<dcsset:groupType>$(Esc-XmlText $gt)</dcsset:groupType>"
|
||||
X "$indent`t<dcsset:periodAdditionType>$(Esc-XmlText $pat)</dcsset:periodAdditionType>"
|
||||
# Авто-детект: ISO-дата → xs:dateTime, иначе путь → dcscor:Field.
|
||||
$pabT = if ($pab -match '^\d{4}-\d{2}-\d{2}T') { 'xs:dateTime' } else { 'dcscor:Field' }
|
||||
$paeT = if ($pae -match '^\d{4}-\d{2}-\d{2}T') { 'xs:dateTime' } else { 'dcscor:Field' }
|
||||
X "$indent`t<dcsset:periodAdditionBegin xsi:type=`"$pabT`">$(Esc-Xml $pab)</dcsset:periodAdditionBegin>"
|
||||
X "$indent`t<dcsset:periodAdditionEnd xsi:type=`"$paeT`">$(Esc-Xml $pae)</dcsset:periodAdditionEnd>"
|
||||
X "$indent`t<dcsset:periodAdditionBegin xsi:type=`"$pabT`">$(Esc-XmlText $pab)</dcsset:periodAdditionBegin>"
|
||||
X "$indent`t<dcsset:periodAdditionEnd xsi:type=`"$paeT`">$(Esc-XmlText $pae)</dcsset:periodAdditionEnd>"
|
||||
X "$indent</dcsset:item>"
|
||||
}
|
||||
|
||||
@@ -2297,22 +2303,22 @@ function Emit-CalcFields {
|
||||
}
|
||||
$ci = "$indent`t"
|
||||
X "$indent<CalculatedField>"
|
||||
X "$ci<dcssch:dataPath>$(Esc-Xml $dataPath)</dcssch:dataPath>"
|
||||
X "$ci<dcssch:expression>$(Esc-Xml $expression)</dcssch:expression>"
|
||||
X "$ci<dcssch:dataPath>$(Esc-XmlText $dataPath)</dcssch:dataPath>"
|
||||
X "$ci<dcssch:expression>$(Esc-XmlText $expression)</dcssch:expression>"
|
||||
if ($title) { Emit-MLText -tag 'dcssch:title' -text $title -indent $ci -xsiType 'v8:LocalStringType' }
|
||||
if ($restrict.Count -gt 0) {
|
||||
X "$ci<dcssch:useRestriction>"
|
||||
foreach ($r in @('field','condition','group','order')) { if ($restrict -contains $r) { X "$ci`t<dcssch:$r>true</dcssch:$r>" } }
|
||||
X "$ci</dcssch:useRestriction>"
|
||||
}
|
||||
if ($pres) { X "$ci<dcssch:presentationExpression>$(Esc-Xml "$pres")</dcssch:presentationExpression>" }
|
||||
if ($pres) { X "$ci<dcssch:presentationExpression>$(Esc-XmlText "$pres")</dcssch:presentationExpression>" }
|
||||
if ($orderExpr) {
|
||||
$oeList = if ($orderExpr -is [System.Collections.IList]) { $orderExpr } else { @($orderExpr) }
|
||||
foreach ($oe in $oeList) {
|
||||
if ($oe -is [string]) { $exprV = $oe; $oType = 'Asc'; $auto = 'false' }
|
||||
else { $exprV = "$($oe.expression)"; $oType = if ($oe.orderType) { "$($oe.orderType)" } else { 'Asc' }; $auto = if ($oe.autoOrder) { 'true' } else { 'false' } }
|
||||
X "$ci<dcssch:orderExpression>"
|
||||
X "$ci`t<expression xmlns=`"$($script:dcsCommonNs)`">$(Esc-Xml $exprV)</expression>"
|
||||
X "$ci`t<expression xmlns=`"$($script:dcsCommonNs)`">$(Esc-XmlText $exprV)</expression>"
|
||||
X "$ci`t<orderType xmlns=`"$($script:dcsCommonNs)`">$oType</orderType>"
|
||||
X "$ci`t<autoOrder xmlns=`"$($script:dcsCommonNs)`">$auto</autoOrder>"
|
||||
X "$ci</dcssch:orderExpression>"
|
||||
@@ -3259,7 +3265,7 @@ function Emit-CommonElementProps {
|
||||
if ($null -ne $el.($p[0])) { X "$indent<$($p[1])>$(if ($el.($p[0])){'true'}else{'false'})</$($p[1])>" }
|
||||
}
|
||||
# Динамический заголовок колонки-группы из данных (HeaderDataPath) — перед HeaderHorizontalAlign (порядок XSD)
|
||||
if ($el.headerDataPath) { X "$indent<HeaderDataPath>$(Esc-Xml "$($el.headerDataPath)")</HeaderDataPath>" }
|
||||
if ($el.headerDataPath) { X "$indent<HeaderDataPath>$(Esc-XmlText "$($el.headerDataPath)")</HeaderDataPath>" }
|
||||
if ($el.footerHorizontalAlign) { X "$indent<FooterHorizontalAlign>$($el.footerHorizontalAlign)</FooterHorizontalAlign>" }
|
||||
if ($el.headerHorizontalAlign) { X "$indent<HeaderHorizontalAlign>$($el.headerHorizontalAlign)</HeaderHorizontalAlign>" }
|
||||
# Формат заголовка колонки-группы (ML-текст) — после HeaderHorizontalAlign (порядок XSD)
|
||||
@@ -3279,8 +3285,8 @@ function Emit-PictureRef {
|
||||
if (-not $src) { return }
|
||||
$srcStr = "$src"
|
||||
X "$indent<$picTag>"
|
||||
if ($srcStr -match '^abs:(.*)$') { X "$indent`t<xr:Abs>$(Esc-Xml $matches[1])</xr:Abs>" }
|
||||
else { X "$indent`t<xr:Ref>$(Esc-Xml $srcStr)</xr:Ref>" }
|
||||
if ($srcStr -match '^abs:(.*)$') { X "$indent`t<xr:Abs>$(Esc-XmlText $matches[1])</xr:Abs>" }
|
||||
else { X "$indent`t<xr:Ref>$(Esc-XmlText $srcStr)</xr:Ref>" }
|
||||
X "$indent`t<xr:LoadTransparent>$(if ($lt) { 'true' } else { 'false' })</xr:LoadTransparent>"
|
||||
if ($tpx) { X "$indent`t<xr:TransparentPixel x=`"$($tpx.x)`" y=`"$($tpx.y)`"/>" }
|
||||
X "$indent</$picTag>"
|
||||
@@ -3309,8 +3315,8 @@ function Emit-CommandPicture {
|
||||
if ($null -eq $lt -and $null -ne $elemLt) { $lt = [bool]$elemLt }
|
||||
$srcStr = "$src"
|
||||
X "$indent<Picture>"
|
||||
if ($srcStr -match '^abs:(.*)$') { X "$indent`t<xr:Abs>$(Esc-Xml $matches[1])</xr:Abs>" }
|
||||
else { X "$indent`t<xr:Ref>$(Esc-Xml $srcStr)</xr:Ref>" }
|
||||
if ($srcStr -match '^abs:(.*)$') { X "$indent`t<xr:Abs>$(Esc-XmlText $matches[1])</xr:Abs>" }
|
||||
else { X "$indent`t<xr:Ref>$(Esc-XmlText $srcStr)</xr:Ref>" }
|
||||
X "$indent`t<xr:LoadTransparent>$(if ($lt -eq $false) { 'false' } else { 'true' })</xr:LoadTransparent>"
|
||||
if ($tpx) { X "$indent`t<xr:TransparentPixel x=`"$($tpx.x)`" y=`"$($tpx.y)`"/>" }
|
||||
X "$indent</Picture>"
|
||||
@@ -3472,7 +3478,7 @@ function Emit-GenericScalars {
|
||||
X "$indent<$($s.Tag)>$(if ($p.Value){'true'}else{'false'})</$($s.Tag)>"
|
||||
} else {
|
||||
$v = "$($p.Value)"; if ($v -eq '') { continue }
|
||||
X "$indent<$($s.Tag)>$(Esc-Xml $v)</$($s.Tag)>"
|
||||
X "$indent<$($s.Tag)>$(Esc-XmlText $v)</$($s.Tag)>"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3519,7 +3525,7 @@ function Emit-BorderTag {
|
||||
$width = if ($val.PSObject.Properties['width'] -and $null -ne $val.width) { $val.width } else { 1 }
|
||||
$style = if ($val.PSObject.Properties['style']) { "$($val.style)" } else { $null }
|
||||
X "$indent<Border width=`"$width`">"
|
||||
if ($style) { X "$indent`t<v8ui:style xsi:type=`"v8ui:ControlBorderType`">$(Esc-Xml $style)</v8ui:style>" }
|
||||
if ($style) { X "$indent`t<v8ui:style xsi:type=`"v8ui:ControlBorderType`">$(Esc-XmlText $style)</v8ui:style>" }
|
||||
X "$indent</Border>"
|
||||
}
|
||||
|
||||
@@ -3546,13 +3552,13 @@ function PL-Bool {
|
||||
}
|
||||
function Emit-PlannerColor {
|
||||
param([string]$tag, $o, [string]$key, [string]$ind)
|
||||
X "$ind<pl:$tag>$(Esc-Xml "$(PL-Get $o $key 'auto')")</pl:$tag>"
|
||||
X "$ind<pl:$tag>$(Esc-XmlText "$(PL-Get $o $key 'auto')")</pl:$tag>"
|
||||
}
|
||||
# <pl:text>/<pl:tooltip>… — пустое → самозакрывающийся тег (как в выгрузке платформы).
|
||||
function Emit-PlannerText {
|
||||
param([string]$tag, $v, [string]$ind)
|
||||
if ([string]::IsNullOrEmpty("$v")) { X "$ind<pl:$tag/>" }
|
||||
else { X "$ind<pl:$tag>$(Esc-Xml "$v")</pl:$tag>" }
|
||||
else { X "$ind<pl:$tag>$(Esc-XmlText "$v")</pl:$tag>" }
|
||||
}
|
||||
# Признак ссылочного значения (объект разреза/элемент-ссылка) → xsi:type="xr:DesignTimeRef";
|
||||
# иначе xs:string. Покрывает англ. (Enum.X.EnumValue.Y) и рус. (Справочник.X) метатипы.
|
||||
@@ -3567,7 +3573,7 @@ function Emit-PlannerValue {
|
||||
param($v, [string]$ind)
|
||||
if ($null -eq $v -or "$v" -eq '') { X "$ind<pl:value xsi:nil=`"true`"/>"; return }
|
||||
$t = if (Test-PlannerRef "$v") { 'xr:DesignTimeRef' } else { 'xs:string' }
|
||||
X "$ind<pl:value xsi:type=`"$t`">$(Esc-Xml "$v")</pl:value>"
|
||||
X "$ind<pl:value xsi:type=`"$t`">$(Esc-XmlText "$v")</pl:value>"
|
||||
}
|
||||
function Emit-PlannerFont {
|
||||
param($o, [string]$ind)
|
||||
@@ -3581,14 +3587,14 @@ function Emit-PlannerBorder {
|
||||
$bw = if ($b) { PL-Get $b 'width' 1 } else { 1 }
|
||||
$bs = if ($b) { PL-Get $b 'style' 'Single' } else { 'Single' }
|
||||
X "$ind<pl:border width=`"$bw`">"
|
||||
X "$ind`t<v8ui:style xsi:type=`"v8ui:ControlBorderType`">$(Esc-Xml "$bs")</v8ui:style>"
|
||||
X "$ind`t<v8ui:style xsi:type=`"v8ui:ControlBorderType`">$(Esc-XmlText "$bs")</v8ui:style>"
|
||||
X "$ind</pl:border>"
|
||||
}
|
||||
function Emit-PlannerLevel {
|
||||
param($lv, [string]$cns, [string]$ind)
|
||||
$li = "$ind`t"
|
||||
X "$ind<level xmlns=`"$cns`">"
|
||||
X "$li<measure>$(Esc-Xml "$(PL-Get $lv 'measure' 'Hour')")</measure>"
|
||||
X "$li<measure>$(Esc-XmlText "$(PL-Get $lv 'measure' 'Hour')")</measure>"
|
||||
X "$li<interval>$(PL-Get $lv 'interval' 1)</interval>"
|
||||
X "$li<show>$(PL-Bool (PL-Get $lv 'show' $true))</show>"
|
||||
$line = PL-Get $lv 'line' $null
|
||||
@@ -3596,10 +3602,10 @@ function Emit-PlannerLevel {
|
||||
$lg = if ($line) { PL-Get $line 'gap' $false } else { $false }
|
||||
$lst = if ($line) { PL-Get $line 'style' 'Solid' } else { 'Solid' }
|
||||
X "$li<line width=`"$lw`" gap=`"$(PL-Bool $lg)`">"
|
||||
X "$li`t<v8ui:style xsi:type=`"v8ui:ChartLineType`">$(Esc-Xml "$lst")</v8ui:style>"
|
||||
X "$li`t<v8ui:style xsi:type=`"v8ui:ChartLineType`">$(Esc-XmlText "$lst")</v8ui:style>"
|
||||
X "$li</line>"
|
||||
X "$li<scaleColor>$(Esc-Xml "$(PL-Get $lv 'scaleColor' 'auto')")</scaleColor>"
|
||||
X "$li<dayFormatRule>$(Esc-Xml "$(PL-Get $lv 'dayFormatRule' 'MonthDayWeekDay')")</dayFormatRule>"
|
||||
X "$li<scaleColor>$(Esc-XmlText "$(PL-Get $lv 'scaleColor' 'auto')")</scaleColor>"
|
||||
X "$li<dayFormatRule>$(Esc-XmlText "$(PL-Get $lv 'dayFormatRule' 'MonthDayWeekDay')")</dayFormatRule>"
|
||||
$fmt = PL-Get $lv 'format' $null
|
||||
if ($null -eq $fmt) { $fmt = [ordered]@{ '#' = 'DF="HH:mm"'; 'ru' = 'DF="HH:mm"' } }
|
||||
X "$li<format>"
|
||||
@@ -3610,8 +3616,8 @@ function Emit-PlannerLevel {
|
||||
X "$li<labels>"
|
||||
X "$li`t<ticks>$ticks</ticks>"
|
||||
X "$li</labels>"
|
||||
X "$li<backColor>$(Esc-Xml "$(PL-Get $lv 'backColor' 'auto')")</backColor>"
|
||||
X "$li<textColor>$(Esc-Xml "$(PL-Get $lv 'textColor' 'auto')")</textColor>"
|
||||
X "$li<backColor>$(Esc-XmlText "$(PL-Get $lv 'backColor' 'auto')")</backColor>"
|
||||
X "$li<textColor>$(Esc-XmlText "$(PL-Get $lv 'textColor' 'auto')")</textColor>"
|
||||
X "$li<showPereodicalLabels>$(PL-Bool (PL-Get $lv 'showPereodicalLabels' $true))</showPereodicalLabels>"
|
||||
X "$ind</level>"
|
||||
}
|
||||
@@ -3620,14 +3626,14 @@ function Emit-PlannerTimeScale {
|
||||
$cns = $script:CHART_NS
|
||||
$ci = "$ind`t"
|
||||
X "$ind<pl:timeScale>"
|
||||
X "$ci<placement xmlns=`"$cns`">$(Esc-Xml "$(if ($ts) { PL-Get $ts 'placement' 'Left' } else { 'Left' })")</placement>"
|
||||
X "$ci<placement xmlns=`"$cns`">$(Esc-XmlText "$(if ($ts) { PL-Get $ts 'placement' 'Left' } else { 'Left' })")</placement>"
|
||||
$levels = if ($ts) { @(PL-Get $ts 'levels' @()) } else { @() }
|
||||
if (@($levels).Count -eq 0) { $levels = @($null) } # один уровень-дефолт
|
||||
foreach ($lv in $levels) { Emit-PlannerLevel $lv $cns $ci }
|
||||
$transp = if ($ts) { PL-Get $ts 'transparent' $false } else { $false }
|
||||
X "$ci<transparent xmlns=`"$cns`">$(PL-Bool $transp)</transparent>"
|
||||
X "$ci<backColor xmlns=`"$cns`">$(Esc-Xml "$(if ($ts) { PL-Get $ts 'backColor' 'auto' } else { 'auto' })")</backColor>"
|
||||
X "$ci<textColor xmlns=`"$cns`">$(Esc-Xml "$(if ($ts) { PL-Get $ts 'textColor' 'auto' } else { 'auto' })")</textColor>"
|
||||
X "$ci<backColor xmlns=`"$cns`">$(Esc-XmlText "$(if ($ts) { PL-Get $ts 'backColor' 'auto' } else { 'auto' })")</backColor>"
|
||||
X "$ci<textColor xmlns=`"$cns`">$(Esc-XmlText "$(if ($ts) { PL-Get $ts 'textColor' 'auto' } else { 'auto' })")</textColor>"
|
||||
X "$ci<currentLevel xmlns=`"$cns`">$(if ($ts) { PL-Get $ts 'currentLevel' 0 } else { 0 })</currentLevel>"
|
||||
X "$ind</pl:timeScale>"
|
||||
}
|
||||
@@ -3652,7 +3658,7 @@ function Emit-PlannerItem {
|
||||
X "$ii<pl:id>$id</pl:id>"
|
||||
X "$ii<pl:textFormatted>$(PL-Bool (PL-Get $it 'textFormatted' $false))</pl:textFormatted>"
|
||||
Emit-PlannerBorder $it $ii 'border'
|
||||
X "$ii<pl:editMode>$(Esc-Xml "$(PL-Get $it 'editMode' 'EnableEdit')")</pl:editMode>"
|
||||
X "$ii<pl:editMode>$(Esc-XmlText "$(PL-Get $it 'editMode' 'EnableEdit')")</pl:editMode>"
|
||||
X "$ind</pl:item>"
|
||||
}
|
||||
# Элемент измерения (<pl:item> внутри <pl:dimension>) — рекурсивен: может нести вложенные
|
||||
@@ -3707,7 +3713,7 @@ function Emit-PlannerSettings {
|
||||
$wfmt = PL-Get $pl 'timeScaleWrapHeadersFormat' $null
|
||||
if ($null -eq $wfmt) { $wfmt = [ordered]@{ '#' = 'DLF="DD"'; 'ru' = 'DLF="DD"' } }
|
||||
Emit-MLText -tag 'pl:timeScaleWrapHeadersFormat' -text $wfmt -indent $si
|
||||
X "$si<pl:periodicVariantUnit>$(Esc-Xml "$(PL-Get $pl 'periodicVariantUnit' 'Day')")</pl:periodicVariantUnit>"
|
||||
X "$si<pl:periodicVariantUnit>$(Esc-XmlText "$(PL-Get $pl 'periodicVariantUnit' 'Day')")</pl:periodicVariantUnit>"
|
||||
X "$si<pl:periodicVariantRepetition>$(PL-Get $pl 'periodicVariantRepetition' 1)</pl:periodicVariantRepetition>"
|
||||
X "$si<pl:timeScaleWrapBeginIndent>$(PL-Get $pl 'timeScaleWrapBeginIndent' 0)</pl:timeScaleWrapBeginIndent>"
|
||||
X "$si<pl:timeScaleWrapEndIndent>$(PL-Get $pl 'timeScaleWrapEndIndent' 0)</pl:timeScaleWrapEndIndent>"
|
||||
@@ -3720,16 +3726,16 @@ function Emit-PlannerSettings {
|
||||
X "$si</pl:period>"
|
||||
}
|
||||
X "$si<pl:displayCurrentDate>$(PL-Bool (PL-Get $pl 'displayCurrentDate' $true))</pl:displayCurrentDate>"
|
||||
X "$si<pl:itemsTimeRepresentation>$(Esc-Xml "$(PL-Get $pl 'itemsTimeRepresentation' 'BeginTime')")</pl:itemsTimeRepresentation>"
|
||||
X "$si<pl:itemsBehaviorWhenSpaceInsufficient>$(Esc-Xml "$(PL-Get $pl 'itemsBehaviorWhenSpaceInsufficient' 'CollapseItems')")</pl:itemsBehaviorWhenSpaceInsufficient>"
|
||||
X "$si<pl:itemsTimeRepresentation>$(Esc-XmlText "$(PL-Get $pl 'itemsTimeRepresentation' 'BeginTime')")</pl:itemsTimeRepresentation>"
|
||||
X "$si<pl:itemsBehaviorWhenSpaceInsufficient>$(Esc-XmlText "$(PL-Get $pl 'itemsBehaviorWhenSpaceInsufficient' 'CollapseItems')")</pl:itemsBehaviorWhenSpaceInsufficient>"
|
||||
X "$si<pl:autoMinColumnWidth>$(PL-Bool (PL-Get $pl 'autoMinColumnWidth' $true))</pl:autoMinColumnWidth>"
|
||||
X "$si<pl:autoMinRowHeight>$(PL-Bool (PL-Get $pl 'autoMinRowHeight' $true))</pl:autoMinRowHeight>"
|
||||
X "$si<pl:minColumnWidth>$(PL-Get $pl 'minColumnWidth' 0)</pl:minColumnWidth>"
|
||||
X "$si<pl:minRowHeight>$(PL-Get $pl 'minRowHeight' 0)</pl:minRowHeight>"
|
||||
X "$si<pl:fixDimensionsHeader>$(Esc-Xml "$(PL-Get $pl 'fixDimensionsHeader' 'auto')")</pl:fixDimensionsHeader>"
|
||||
X "$si<pl:fixTimeScaleHeader>$(Esc-Xml "$(PL-Get $pl 'fixTimeScaleHeader' 'auto')")</pl:fixTimeScaleHeader>"
|
||||
X "$si<pl:fixDimensionsHeader>$(Esc-XmlText "$(PL-Get $pl 'fixDimensionsHeader' 'auto')")</pl:fixDimensionsHeader>"
|
||||
X "$si<pl:fixTimeScaleHeader>$(Esc-XmlText "$(PL-Get $pl 'fixTimeScaleHeader' 'auto')")</pl:fixTimeScaleHeader>"
|
||||
Emit-PlannerBorder $pl $si 'border'
|
||||
X "$si<pl:newItemsTextType>$(Esc-Xml "$(PL-Get $pl 'newItemsTextType' 'String')")</pl:newItemsTextType>"
|
||||
X "$si<pl:newItemsTextType>$(Esc-XmlText "$(PL-Get $pl 'newItemsTextType' 'String')")</pl:newItemsTextType>"
|
||||
X "$ind</Settings>"
|
||||
}
|
||||
|
||||
@@ -3762,13 +3768,13 @@ function Emit-ChartNode {
|
||||
if ($keys -contains 'gap') {
|
||||
$w = Get-Prop $val 'width'; $g = Get-Prop $val 'gap'; $st = Get-Prop $val 'style'
|
||||
X "$ind<d4p1:$name width=`"$w`" gap=`"$(PL-Bool $g)`">"
|
||||
X "$ind`t<v8ui:style xsi:type=`"v8ui:ChartLineType`">$(Esc-Xml "$st")</v8ui:style>"
|
||||
X "$ind`t<v8ui:style xsi:type=`"v8ui:ChartLineType`">$(Esc-XmlText "$st")</v8ui:style>"
|
||||
X "$ind</d4p1:$name>"; return
|
||||
}
|
||||
if (($keys -contains 'style') -and ($keys -contains 'width')) {
|
||||
$w = Get-Prop $val 'width'; $st = Get-Prop $val 'style'
|
||||
X "$ind<d4p1:$name width=`"$w`">"
|
||||
X "$ind`t<v8ui:style xsi:type=`"v8ui:ControlBorderType`">$(Esc-Xml "$st")</v8ui:style>"
|
||||
X "$ind`t<v8ui:style xsi:type=`"v8ui:ControlBorderType`">$(Esc-XmlText "$st")</v8ui:style>"
|
||||
X "$ind</d4p1:$name>"; return
|
||||
}
|
||||
$isFont = $false; foreach ($fk in $script:CHART_FONT_KEYS) { if ($keys -contains $fk) { $isFont = $true; break } }
|
||||
@@ -3784,7 +3790,7 @@ function Emit-ChartNode {
|
||||
}
|
||||
if ($null -eq $val -or "$val" -eq '') { X "$ind<d4p1:$name/>"; return }
|
||||
if ($val -is [bool]) { X "$ind<d4p1:$name>$(PL-Bool $val)</d4p1:$name>"; return }
|
||||
X "$ind<d4p1:$name>$(Esc-Xml "$val")</d4p1:$name>"
|
||||
X "$ind<d4p1:$name>$(Esc-XmlText "$val")</d4p1:$name>"
|
||||
}
|
||||
function Emit-ChartSettings {
|
||||
param($chart, [string]$ind, [string]$ctype = 'd4p1:Chart')
|
||||
@@ -3806,7 +3812,7 @@ function Emit-Appearance {
|
||||
if ($null -eq $val -or ($val -is [string] -and $val -eq '')) { continue }
|
||||
$spec = $script:appearanceSpec[$key]
|
||||
switch ($spec.kind) {
|
||||
'color' { X "$indent<$($spec.tag)>$(Esc-Xml "$val")</$($spec.tag)>" }
|
||||
'color' { X "$indent<$($spec.tag)>$(Esc-XmlText "$val")</$($spec.tag)>" }
|
||||
'font' { Emit-FontTag -tag $spec.tag -val $val -indent $indent }
|
||||
'border' { Emit-BorderTag -val $val -indent $indent }
|
||||
}
|
||||
@@ -4091,13 +4097,13 @@ function Emit-Input {
|
||||
@('choiceForm','ChoiceForm'), @('choiceHistoryOnInput','ChoiceHistoryOnInput'),
|
||||
@('choiceFoldersAndItems','ChoiceFoldersAndItems'), @('footerDataPath','FooterDataPath')
|
||||
)) {
|
||||
if ($el.($p[0])) { X "$inner<$($p[1])>$(Esc-Xml "$($el.($p[0]))")</$($p[1])>" }
|
||||
if ($el.($p[0])) { X "$inner<$($p[1])>$(Esc-XmlText "$($el.($p[0]))")</$($p[1])>" }
|
||||
}
|
||||
# MinValue/MaxValue — типизированное. JSON-число → xs:decimal, строка → xs:string (тип сохранён декомпилятором).
|
||||
foreach ($p in @(@('minValue','MinValue'), @('maxValue','MaxValue'))) {
|
||||
if ($null -ne $el.($p[0])) {
|
||||
$mvt = if ($el.($p[0]) -is [string]) { 'xs:string' } else { 'xs:decimal' }
|
||||
X "$inner<$($p[1]) xsi:type=`"$mvt`">$(Esc-Xml "$($el.($p[0]))")</$($p[1])>"
|
||||
X "$inner<$($p[1]) xsi:type=`"$mvt`">$(Esc-XmlText "$($el.($p[0]))")</$($p[1])>"
|
||||
}
|
||||
}
|
||||
if ($el.choiceButtonRepresentation) { X "$inner<ChoiceButtonRepresentation>$($el.choiceButtonRepresentation)</ChoiceButtonRepresentation>" }
|
||||
@@ -4160,7 +4166,7 @@ function Emit-Check {
|
||||
|
||||
if ($null -ne $el.warningOnEdit) { Emit-MLText -tag "WarningOnEdit" -text $el.warningOnEdit -indent $inner }
|
||||
# FooterDataPath / FooterText — общие cell-свойства колонки (как у input/labelField)
|
||||
if ($el.footerDataPath) { X "$inner<FooterDataPath>$(Esc-Xml "$($el.footerDataPath)")</FooterDataPath>" }
|
||||
if ($el.footerDataPath) { X "$inner<FooterDataPath>$(Esc-XmlText "$($el.footerDataPath)")</FooterDataPath>" }
|
||||
if ($null -ne $el.footerText) { Emit-MLText -tag "FooterText" -text $el.footerText -indent $inner }
|
||||
|
||||
# Формат / формат редактирования (LocalStringType — строка или {ru,en})
|
||||
@@ -4317,7 +4323,7 @@ function Emit-ChoicePresentation {
|
||||
foreach ($pair in $pairs) {
|
||||
X "$indent`t<v8:item>"
|
||||
X "$indent`t`t<v8:lang>$($pair[0])</v8:lang>"
|
||||
X "$indent`t`t<v8:content>$(Esc-Xml $pair[1])</v8:content>"
|
||||
X "$indent`t`t<v8:content>$(Esc-XmlText $pair[1])</v8:content>"
|
||||
X "$indent`t</v8:item>"
|
||||
}
|
||||
X "$indent</Presentation>"
|
||||
@@ -4327,7 +4333,7 @@ function Emit-ChoicePresentation {
|
||||
function Get-ChoiceValueTag {
|
||||
param($norm)
|
||||
if ([string]::IsNullOrEmpty($norm.Text)) { return "<Value xsi:type=`"$($norm.XsiType)`"/>" }
|
||||
return "<Value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</Value>"
|
||||
return "<Value xsi:type=`"$($norm.XsiType)`">$(Esc-XmlText $norm.Text)</Value>"
|
||||
}
|
||||
|
||||
# Emit <ChoiceList> (список выбора) — у RadioButtonField и InputField.
|
||||
@@ -4540,8 +4546,8 @@ function Emit-ChoiceParameterLinks {
|
||||
}
|
||||
}
|
||||
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:Name>$(Esc-XmlText "$name")</xr:Name>"
|
||||
X "$indent`t`t<xr:DataPath xsi:type=`"xs:string`">$(Esc-XmlText "$dp")</xr:DataPath>"
|
||||
X "$indent`t`t<xr:ValueChange>$vc</xr:ValueChange>"
|
||||
X "$indent`t</xr:Link>"
|
||||
}
|
||||
@@ -4558,7 +4564,7 @@ function Emit-TypeLink {
|
||||
$li = Get-ElProp $tl @('linkItem','элементСвязи')
|
||||
if ($null -eq $li) { $li = 0 }
|
||||
X "$indent<TypeLink>"
|
||||
X "$indent`t<xr:DataPath>$(Esc-Xml "$dp")</xr:DataPath>"
|
||||
X "$indent`t<xr:DataPath>$(Esc-XmlText "$dp")</xr:DataPath>"
|
||||
X "$indent`t<xr:LinkItem>$li</xr:LinkItem>"
|
||||
X "$indent</TypeLink>"
|
||||
}
|
||||
@@ -4665,7 +4671,7 @@ function Emit-LabelField {
|
||||
if ($el.titleLocation) { X "$inner<TitleLocation>$(Map-TitleLoc "$($el.titleLocation)")</TitleLocation>" }
|
||||
if ($el.editMode) { X "$inner<EditMode>$($el.editMode)</EditMode>" }
|
||||
# FooterDataPath — путь данных подвала колонки (общий cell-prop, как у input); после EditMode
|
||||
if ($el.footerDataPath) { X "$inner<FooterDataPath>$(Esc-Xml "$($el.footerDataPath)")</FooterDataPath>" }
|
||||
if ($el.footerDataPath) { X "$inner<FooterDataPath>$(Esc-XmlText "$($el.footerDataPath)")</FooterDataPath>" }
|
||||
# PasswordMode на LabelField — платформа эмитит явный false (редко); факт. значение
|
||||
if ($null -ne $el.passwordMode) { X "$inner<PasswordMode>$(if ($el.passwordMode){'true'}else{'false'})</PasswordMode>" }
|
||||
Emit-ColumnPics -el $el -indent $inner
|
||||
@@ -4988,7 +4994,7 @@ function Emit-Button {
|
||||
if (($btnParam -is [System.Management.Automation.PSCustomObject] -or $btnParam -is [hashtable]) -and $btnParam.type) {
|
||||
Emit-Type -typeStr "$($btnParam.type)" -indent $inner -tag "Parameter" -tagAttrs ' xsi:type="v8:TypeDescription"'
|
||||
} else {
|
||||
X "$inner<Parameter xsi:type=`"xr:MDObjectRef`">$(Esc-Xml "$btnParam")</Parameter>"
|
||||
X "$inner<Parameter xsi:type=`"xr:MDObjectRef`">$(Esc-XmlText "$btnParam")</Parameter>"
|
||||
}
|
||||
}
|
||||
# DataPath — привязка команды кнопки к контексту (Объект.Ref, Items.X.CurrentData.Поле)
|
||||
@@ -5043,8 +5049,8 @@ function Emit-PictureDecoration {
|
||||
$srcStr = "$($el.src)"
|
||||
$lt = if ($el.loadTransparent -eq $true) { "true" } else { "false" }
|
||||
X "$inner<Picture>"
|
||||
if ($srcStr -match '^abs:(.*)$') { X "$inner`t<xr:Abs>$(Esc-Xml $matches[1])</xr:Abs>" }
|
||||
else { X "$inner`t<xr:Ref>$(Esc-Xml $srcStr)</xr:Ref>" }
|
||||
if ($srcStr -match '^abs:(.*)$') { X "$inner`t<xr:Abs>$(Esc-XmlText $matches[1])</xr:Abs>" }
|
||||
else { X "$inner`t<xr:Ref>$(Esc-XmlText $srcStr)</xr:Ref>" }
|
||||
X "$inner`t<xr:LoadTransparent>$lt</xr:LoadTransparent>"
|
||||
if ($el.transparentPixel) { X "$inner`t<xr:TransparentPixel x=`"$($el.transparentPixel.x)`" y=`"$($el.transparentPixel.y)`"/>" }
|
||||
X "$inner</Picture>"
|
||||
@@ -5088,7 +5094,7 @@ function Emit-PictureField {
|
||||
if ($null -ne $el.enableDrag) { X "$inner<EnableDrag>$(if ($el.enableDrag){'true'}else{'false'})</EnableDrag>" }
|
||||
|
||||
# FooterDataPath / FooterText — общие cell-свойства колонки (как у input/labelField)
|
||||
if ($el.footerDataPath) { X "$inner<FooterDataPath>$(Esc-Xml "$($el.footerDataPath)")</FooterDataPath>" }
|
||||
if ($el.footerDataPath) { X "$inner<FooterDataPath>$(Esc-XmlText "$($el.footerDataPath)")</FooterDataPath>" }
|
||||
if ($null -ne $el.footerText) { Emit-MLText -tag "FooterText" -text $el.footerText -indent $inner }
|
||||
|
||||
# ValuesPicture — picture (collection) used to render the field's value.
|
||||
@@ -5444,18 +5450,18 @@ function Emit-DLValue {
|
||||
return
|
||||
}
|
||||
$valStr = if ($val -is [bool]) { if ($val) { 'true' } else { 'false' } } else { "$val" }
|
||||
if ($type -match '^(date|dateTime|time)') { X "$indent<dcssch:value xsi:type=`"xs:dateTime`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
elseif ($type -eq "boolean") { X "$indent<dcssch:value xsi:type=`"xs:boolean`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
elseif ($type -eq 'v8:Type') { $nsAttr = Get-ValueTypeNsAttr -valueType 'v8:Type' -value $valStr; X "$indent<dcssch:value$nsAttr xsi:type=`"v8:Type`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
elseif ($type -match '^ent:') { X "$indent<dcssch:value xsi:type=`"$type`">$(Esc-Xml $valStr)</dcssch:value>" } # системное перечисление (ent:X) — value несёт тот же xsi:type
|
||||
elseif ($type -match '^decimal') { X "$indent<dcssch:value xsi:type=`"xs:decimal`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
elseif ($type -match '^string') { X "$indent<dcssch:value xsi:type=`"xs:string`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
elseif ($type -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|BusinessProcessRef|TaskRef|ExchangePlanRef)\.') { X "$indent<dcssch:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
if ($type -match '^(date|dateTime|time)') { X "$indent<dcssch:value xsi:type=`"xs:dateTime`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
elseif ($type -eq "boolean") { X "$indent<dcssch:value xsi:type=`"xs:boolean`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
elseif ($type -eq 'v8:Type') { $nsAttr = Get-ValueTypeNsAttr -valueType 'v8:Type' -value $valStr; X "$indent<dcssch:value$nsAttr xsi:type=`"v8:Type`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
elseif ($type -match '^ent:') { X "$indent<dcssch:value xsi:type=`"$type`">$(Esc-XmlText $valStr)</dcssch:value>" } # системное перечисление (ent:X) — value несёт тот же xsi:type
|
||||
elseif ($type -match '^decimal') { X "$indent<dcssch:value xsi:type=`"xs:decimal`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
elseif ($type -match '^string') { X "$indent<dcssch:value xsi:type=`"xs:string`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
elseif ($type -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|BusinessProcessRef|TaskRef|ExchangePlanRef)\.') { X "$indent<dcssch:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
else {
|
||||
if ($valStr -match '^\d{4}-\d{2}-\d{2}T') { X "$indent<dcssch:value xsi:type=`"xs:dateTime`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
elseif ($valStr -eq "true" -or $valStr -eq "false") { X "$indent<dcssch:value xsi:type=`"xs:boolean`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
elseif ($valStr -match '^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.' -or $valStr -match '^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.') { X "$indent<dcssch:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
else { X "$indent<dcssch:value xsi:type=`"xs:string`">$(Esc-Xml $valStr)</dcssch:value>" }
|
||||
if ($valStr -match '^\d{4}-\d{2}-\d{2}T') { X "$indent<dcssch:value xsi:type=`"xs:dateTime`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
elseif ($valStr -eq "true" -or $valStr -eq "false") { X "$indent<dcssch:value xsi:type=`"xs:boolean`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
elseif ($valStr -match '^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.' -or $valStr -match '^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.') { X "$indent<dcssch:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
else { X "$indent<dcssch:value xsi:type=`"xs:string`">$(Esc-XmlText $valStr)</dcssch:value>" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5489,7 +5495,7 @@ function Emit-DLInputParameters {
|
||||
foreach ($item in $items) {
|
||||
X "$indent`t<dcscor:item>"
|
||||
if ((Has-DLProp $item 'use') -and $null -ne $item.use -and -not $item.use) { X "$indent`t`t<dcscor:use>false</dcscor:use>" }
|
||||
X "$indent`t`t<dcscor:parameter>$(Esc-Xml "$($item.parameter)")</dcscor:parameter>"
|
||||
X "$indent`t`t<dcscor:parameter>$(Esc-XmlText "$($item.parameter)")</dcscor:parameter>"
|
||||
if (Has-DLProp $item 'choiceParameters') {
|
||||
$cpItems = if ($null -ne $item.choiceParameters) { @($item.choiceParameters) } else { @() }
|
||||
if ($cpItems.Count -eq 0) { X "$indent`t`t<dcscor:value xsi:type=`"dcscor:ChoiceParameters`"/>" }
|
||||
@@ -5497,11 +5503,11 @@ function Emit-DLInputParameters {
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"dcscor:ChoiceParameters`">"
|
||||
foreach ($cpItem in $cpItems) {
|
||||
X "$indent`t`t`t<dcscor:item>"
|
||||
X "$indent`t`t`t`t<dcscor:choiceParameter>$(Esc-Xml "$($cpItem.name)")</dcscor:choiceParameter>"
|
||||
X "$indent`t`t`t`t<dcscor:choiceParameter>$(Esc-XmlText "$($cpItem.name)")</dcscor:choiceParameter>"
|
||||
foreach ($v in @($cpItem.values)) {
|
||||
if ($v -is [bool]) { X "$indent`t`t`t`t<dcscor:value xsi:type=`"xs:boolean`">$(if ($v) { 'true' } else { 'false' })</dcscor:value>" }
|
||||
elseif ($v -is [int] -or $v -is [long] -or $v -is [double] -or $v -is [decimal]) { X "$indent`t`t`t`t<dcscor:value xsi:type=`"xs:decimal`">$v</dcscor:value>" }
|
||||
else { X "$indent`t`t`t`t<dcscor:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-Xml "$v")</dcscor:value>" }
|
||||
else { X "$indent`t`t`t`t<dcscor:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-XmlText "$v")</dcscor:value>" }
|
||||
}
|
||||
X "$indent`t`t`t</dcscor:item>"
|
||||
}
|
||||
@@ -5514,8 +5520,8 @@ function Emit-DLInputParameters {
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"dcscor:ChoiceParameterLinks`">"
|
||||
foreach ($cplItem in $cplItems) {
|
||||
X "$indent`t`t`t<dcscor:item>"
|
||||
X "$indent`t`t`t`t<dcscor:choiceParameter>$(Esc-Xml "$($cplItem.name)")</dcscor:choiceParameter>"
|
||||
X "$indent`t`t`t`t<dcscor:value>$(Esc-Xml "$($cplItem.value)")</dcscor:value>"
|
||||
X "$indent`t`t`t`t<dcscor:choiceParameter>$(Esc-XmlText "$($cplItem.name)")</dcscor:choiceParameter>"
|
||||
X "$indent`t`t`t`t<dcscor:value>$(Esc-XmlText "$($cplItem.value)")</dcscor:value>"
|
||||
$mode = if ($cplItem.mode) { "$($cplItem.mode)" } else { 'Auto' }
|
||||
X "$indent`t`t`t`t<dcscor:mode xmlns:d8p1=`"http://v8.1c.ru/8.1/data/enterprise`" xsi:type=`"d8p1:LinkedValueChangeMode`">$mode</dcscor:mode>"
|
||||
X "$indent`t`t`t</dcscor:item>"
|
||||
@@ -5526,15 +5532,15 @@ function Emit-DLInputParameters {
|
||||
# Связь по типу (dcscor:TypeLink) — field + linkItem (структурное значение параметра).
|
||||
$tl = $item.typeLink
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"dcscor:TypeLink`">"
|
||||
$tlf = Get-Prop $tl 'field'; if ($null -ne $tlf) { X "$indent`t`t`t<dcscor:field>$(Esc-Xml "$tlf")</dcscor:field>" }
|
||||
$tli = Get-Prop $tl 'linkItem'; if ($null -ne $tli) { X "$indent`t`t`t<dcscor:linkItem>$(Esc-Xml "$tli")</dcscor:linkItem>" }
|
||||
$tlf = Get-Prop $tl 'field'; if ($null -ne $tlf) { X "$indent`t`t`t<dcscor:field>$(Esc-XmlText "$tlf")</dcscor:field>" }
|
||||
$tli = Get-Prop $tl 'linkItem'; if ($null -ne $tli) { X "$indent`t`t`t<dcscor:linkItem>$(Esc-XmlText "$tli")</dcscor:linkItem>" }
|
||||
X "$indent`t`t</dcscor:value>"
|
||||
} elseif (Has-DLProp $item 'value') {
|
||||
$val = $item.value
|
||||
if ($val -is [bool]) { X "$indent`t`t<dcscor:value xsi:type=`"xs:boolean`">$(if ($val) { 'true' } else { 'false' })</dcscor:value>" }
|
||||
elseif ($val -is [int] -or $val -is [long] -or $val -is [double] -or $val -is [decimal]) { X "$indent`t`t<dcscor:value xsi:type=`"xs:decimal`">$val</dcscor:value>" }
|
||||
elseif ($val -is [hashtable] -or $val -is [System.Collections.IDictionary] -or $val -is [PSCustomObject]) { Emit-DLMLText -tag "dcscor:value" -text $val -indent "$indent`t`t" }
|
||||
else { X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml "$val")</dcscor:value>" }
|
||||
else { X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-XmlText "$val")</dcscor:value>" }
|
||||
}
|
||||
X "$indent`t</dcscor:item>"
|
||||
}
|
||||
@@ -5609,16 +5615,16 @@ function Emit-DataParameters {
|
||||
}
|
||||
X "$indent`t<dcscor:item xsi:type=`"dcsset:SettingsParameterValue`">"
|
||||
if ($dp.use -eq $false) { X "$indent`t`t<dcscor:use>false</dcscor:use>" }
|
||||
X "$indent`t`t<dcscor:parameter>$(Esc-Xml "$($dp.parameter)")</dcscor:parameter>"
|
||||
X "$indent`t`t<dcscor:parameter>$(Esc-XmlText "$($dp.parameter)")</dcscor:parameter>"
|
||||
$dpValIsArr = ($dp.value -is [array]) -or ($dp.value -is [System.Collections.IList] -and $dp.value -isnot [string])
|
||||
if ($dpValIsArr) {
|
||||
# Список значений параметра (valueListAllowed) — отдельный <dcscor:value> на каждое.
|
||||
$avtype = "$($dp.valueType)"
|
||||
foreach ($v in @($dp.value)) {
|
||||
$vStr = if ($v -is [bool]) { "$v".ToLower() } else { "$v" }
|
||||
if ($avtype -match '^[a-zA-Z]+:') { X "$indent`t`t<dcscor:value xsi:type=`"$avtype`">$(Esc-Xml $vStr)</dcscor:value>" }
|
||||
elseif ("$vStr" -match '^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.' -or "$vStr" -match '^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.') { X "$indent`t`t<dcscor:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-Xml $vStr)</dcscor:value>" }
|
||||
else { X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml $vStr)</dcscor:value>" }
|
||||
if ($avtype -match '^[a-zA-Z]+:') { X "$indent`t`t<dcscor:value xsi:type=`"$avtype`">$(Esc-XmlText $vStr)</dcscor:value>" }
|
||||
elseif ("$vStr" -match '^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.' -or "$vStr" -match '^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.') { X "$indent`t`t<dcscor:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-XmlText $vStr)</dcscor:value>" }
|
||||
else { X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-XmlText $vStr)</dcscor:value>" }
|
||||
}
|
||||
} elseif ($dp.nilValue -eq $true) {
|
||||
X "$indent`t`t<dcscor:value xsi:nil=`"true`"/>"
|
||||
@@ -5641,41 +5647,41 @@ function Emit-DataParameters {
|
||||
if ($dp.value -is [PSCustomObject] -and $dp.value.PSObject.Properties['date']) { $_d = "$($dp.value.date)" }
|
||||
elseif (($dp.value -is [System.Collections.IDictionary]) -and $dp.value.Contains('date')) { $_d = "$($dp.value['date'])" }
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"v8:StandardBeginningDate`">"
|
||||
X "$indent`t`t`t<v8:variant xsi:type=`"v8:StandardBeginningDateVariant`">$(Esc-Xml $_variantStr)</v8:variant>"
|
||||
if ($_variantStr -eq 'Custom') { if (-not $_d) { $_d = '0001-01-01T00:00:00' }; X "$indent`t`t`t<v8:date>$(Esc-Xml $_d)</v8:date>" }
|
||||
X "$indent`t`t`t<v8:variant xsi:type=`"v8:StandardBeginningDateVariant`">$(Esc-XmlText $_variantStr)</v8:variant>"
|
||||
if ($_variantStr -eq 'Custom') { if (-not $_d) { $_d = '0001-01-01T00:00:00' }; X "$indent`t`t`t<v8:date>$(Esc-XmlText $_d)</v8:date>" }
|
||||
X "$indent`t`t</dcscor:value>"
|
||||
} else {
|
||||
$_sd = $null; $_ed = $null
|
||||
if ($dp.value -is [PSCustomObject]) { if ($dp.value.PSObject.Properties['startDate']) { $_sd = "$($dp.value.startDate)" }; if ($dp.value.PSObject.Properties['endDate']) { $_ed = "$($dp.value.endDate)" } }
|
||||
else { if ($dp.value.Contains('startDate')) { $_sd = "$($dp.value['startDate'])" }; if ($dp.value.Contains('endDate')) { $_ed = "$($dp.value['endDate'])" } }
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"v8:StandardPeriod`">"
|
||||
X "$indent`t`t`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml $_variantStr)</v8:variant>"
|
||||
if ($_variantStr -eq 'Custom') { if (-not $_sd) { $_sd = '0001-01-01T00:00:00' }; if (-not $_ed) { $_ed = '0001-01-01T00:00:00' }; X "$indent`t`t`t<v8:startDate>$(Esc-Xml $_sd)</v8:startDate>"; X "$indent`t`t`t<v8:endDate>$(Esc-Xml $_ed)</v8:endDate>" }
|
||||
X "$indent`t`t`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-XmlText $_variantStr)</v8:variant>"
|
||||
if ($_variantStr -eq 'Custom') { if (-not $_sd) { $_sd = '0001-01-01T00:00:00' }; if (-not $_ed) { $_ed = '0001-01-01T00:00:00' }; X "$indent`t`t`t<v8:startDate>$(Esc-XmlText $_sd)</v8:startDate>"; X "$indent`t`t`t<v8:endDate>$(Esc-XmlText $_ed)</v8:endDate>" }
|
||||
X "$indent`t`t</dcscor:value>"
|
||||
}
|
||||
} elseif ($vtype -match '^[a-zA-Z]+:') {
|
||||
$vStr = if ($dp.value -is [bool]) { "$($dp.value)".ToLower() } else { "$($dp.value)" }
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"$vtype`">$(Esc-Xml $vStr)</dcscor:value>"
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"$vtype`">$(Esc-XmlText $vStr)</dcscor:value>"
|
||||
} elseif ($vtype -eq 'boolean' -or $dp.value -is [bool]) {
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:boolean`">$(Esc-Xml ("$($dp.value)".ToLower()))</dcscor:value>"
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:boolean`">$(Esc-XmlText ("$($dp.value)".ToLower()))</dcscor:value>"
|
||||
} elseif ($vtype -match '^date' -or "$($dp.value)" -match '^\d{4}-\d{2}-\d{2}T') {
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:dateTime`">$(Esc-Xml "$($dp.value)")</dcscor:value>"
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:dateTime`">$(Esc-XmlText "$($dp.value)")</dcscor:value>"
|
||||
} elseif ($vtype -match '^decimal') {
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:decimal`">$(Esc-Xml "$($dp.value)")</dcscor:value>"
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:decimal`">$(Esc-XmlText "$($dp.value)")</dcscor:value>"
|
||||
} elseif ($vtype -match '^string') {
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml "$($dp.value)")</dcscor:value>"
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-XmlText "$($dp.value)")</dcscor:value>"
|
||||
} elseif ("$($dp.value)" -match '^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.' -or "$($dp.value)" -match '^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.') {
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-Xml "$($dp.value)")</dcscor:value>"
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-XmlText "$($dp.value)")</dcscor:value>"
|
||||
} else {
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml "$($dp.value)")</dcscor:value>"
|
||||
X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-XmlText "$($dp.value)")</dcscor:value>"
|
||||
}
|
||||
}
|
||||
if ($dp.viewMode) { X "$indent`t`t<dcsset:viewMode>$(Esc-Xml "$($dp.viewMode)")</dcsset:viewMode>" }
|
||||
if ($dp.userSettingID) { $uid = if ("$($dp.userSettingID)" -eq "auto") { New-Guid-String } else { "$($dp.userSettingID)" }; X "$indent`t`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>" }
|
||||
if ($dp.viewMode) { X "$indent`t`t<dcsset:viewMode>$(Esc-XmlText "$($dp.viewMode)")</dcsset:viewMode>" }
|
||||
if ($dp.userSettingID) { $uid = if ("$($dp.userSettingID)" -eq "auto") { New-Guid-String } else { "$($dp.userSettingID)" }; X "$indent`t`t<dcsset:userSettingID>$(Esc-XmlText $uid)</dcsset:userSettingID>" }
|
||||
if ($dp.userSettingPresentation) { Emit-USPresentation -val $dp.userSettingPresentation -tag "dcsset:userSettingPresentation" -indent "$indent`t`t" }
|
||||
X "$indent`t</dcscor:item>"
|
||||
}
|
||||
if ($null -ne $blockViewMode) { X "$indent`t<dcsset:viewMode>$(Esc-Xml "$blockViewMode")</dcsset:viewMode>" }
|
||||
if ($null -ne $blockViewMode) { X "$indent`t<dcsset:viewMode>$(Esc-XmlText "$blockViewMode")</dcsset:viewMode>" }
|
||||
X "$indent</dcsset:dataParameters>"
|
||||
}
|
||||
|
||||
@@ -5683,7 +5689,7 @@ function Emit-DLParameter {
|
||||
param($p, $parsed, [string]$indent)
|
||||
X "$indent<Parameter>"
|
||||
$ci = "$indent`t"
|
||||
X "$ci<dcssch:name>$(Esc-Xml $parsed.name)</dcssch:name>"
|
||||
X "$ci<dcssch:name>$(Esc-XmlText $parsed.name)</dcssch:name>"
|
||||
# Title: явный override (shorthand [..] / объект title/presentation) или авто из имени.
|
||||
$title = $null
|
||||
if ($parsed.title) { $title = $parsed.title }
|
||||
@@ -5717,7 +5723,7 @@ function Emit-DLParameter {
|
||||
# expression
|
||||
$expr = $null
|
||||
if ($p -isnot [string] -and (Has-DLProp $p 'expression') -and $p.expression) { $expr = "$($p.expression)" }
|
||||
if ($expr) { X "$ci<dcssch:expression>$(Esc-Xml $expr)</dcssch:expression>" }
|
||||
if ($expr) { X "$ci<dcssch:expression>$(Esc-XmlText $expr)</dcssch:expression>" }
|
||||
# availableValues
|
||||
if ($p -isnot [string] -and (Has-DLProp $p 'availableValues') -and $p.availableValues) {
|
||||
foreach ($av in @($p.availableValues)) { Emit-DLAvailableValue -av $av -type $parsed.type -indent $ci }
|
||||
@@ -5736,7 +5742,7 @@ function Emit-DLParameter {
|
||||
# use
|
||||
$useVal = $null
|
||||
if ($p -isnot [string] -and (Has-DLProp $p 'use') -and $p.use) { $useVal = "$($p.use)" }
|
||||
if ($useVal) { X "$ci<dcssch:use>$(Esc-Xml $useVal)</dcssch:use>" }
|
||||
if ($useVal) { X "$ci<dcssch:use>$(Esc-XmlText $useVal)</dcssch:use>" }
|
||||
X "$indent</Parameter>"
|
||||
}
|
||||
|
||||
@@ -5856,7 +5862,7 @@ function Emit-Attributes {
|
||||
}
|
||||
if ($saveFields.Count -gt 0) {
|
||||
X "$inner<Save>"
|
||||
foreach ($f in $saveFields) { X "$inner`t<Field>$(Esc-Xml $f)</Field>" }
|
||||
foreach ($f in $saveFields) { X "$inner`t<Field>$(Esc-XmlText $f)</Field>" }
|
||||
X "$inner</Save>"
|
||||
}
|
||||
}
|
||||
@@ -5957,7 +5963,7 @@ function Emit-Attributes {
|
||||
X "$si<DynamicDataRead>$ddr</DynamicDataRead>"
|
||||
if ($hasQuery) {
|
||||
$qtext = Resolve-QueryValue "$($st.query)" $script:queryBaseDir
|
||||
X "$si<QueryText>$(Esc-Xml $qtext)</QueryText>"
|
||||
X "$si<QueryText>$(Esc-XmlText $qtext)</QueryText>"
|
||||
}
|
||||
# Явные поля набора (редко): override title/dataPath
|
||||
if ($st.fields) {
|
||||
@@ -5972,8 +5978,8 @@ function Emit-Attributes {
|
||||
if ($null -ne (Get-Prop $fld 'dataPath')) { $dp = "$($fld.dataPath)" }
|
||||
elseif ($isFolder) { $dp = "" }
|
||||
else { $dp = "$($fld.field)" }
|
||||
if ($dp -eq "") { X "$si`t<dcssch:dataPath/>" } else { X "$si`t<dcssch:dataPath>$(Esc-Xml "$dp")</dcssch:dataPath>" }
|
||||
if (-not $isFolder) { X "$si`t<dcssch:field>$(Esc-Xml "$($fld.field)")</dcssch:field>" }
|
||||
if ($dp -eq "") { X "$si`t<dcssch:dataPath/>" } else { X "$si`t<dcssch:dataPath>$(Esc-XmlText "$dp")</dcssch:dataPath>" }
|
||||
if (-not $isFolder) { X "$si`t<dcssch:field>$(Esc-XmlText "$($fld.field)")</dcssch:field>" }
|
||||
if ($fld.title) {
|
||||
X "$si`t<dcssch:title xsi:type=`"v8:LocalStringType`">"
|
||||
Emit-MLItems -val $fld.title -indent "$si`t`t"
|
||||
@@ -5983,7 +5989,7 @@ function Emit-Attributes {
|
||||
Emit-RestrictBlock 'useRestriction' $fld.useRestriction "$si`t"
|
||||
Emit-RestrictBlock 'attributeUseRestriction' $fld.attributeUseRestriction "$si`t"
|
||||
# presentationExpression поля — перед valueType (порядок исходника)
|
||||
if ($fld.presentationExpression) { X "$si`t<dcssch:presentationExpression>$(Esc-Xml "$($fld.presentationExpression)")</dcssch:presentationExpression>" }
|
||||
if ($fld.presentationExpression) { X "$si`t<dcssch:presentationExpression>$(Esc-XmlText "$($fld.presentationExpression)")</dcssch:presentationExpression>" }
|
||||
# valueType поля набора (тип значения; вычисляемые/кастомные поля)
|
||||
if ($fld.valueType) { Emit-DLValueType -typeStr "$($fld.valueType)" -indent "$si`t" }
|
||||
# appearance поля (формат/оформление) — после valueType (порядок исходника)
|
||||
@@ -6003,8 +6009,8 @@ function Emit-Attributes {
|
||||
Emit-DLParameters -params $st.parameters -indent $si
|
||||
# Ключ набора (query-based список без MainTable): KeyType (RowNumber/FieldValue/RowKey)
|
||||
# + KeyField* — после Parameter*, до MainTable. Захват/эмит факт. значений.
|
||||
if ($st.keyType) { X "$si<KeyType>$(Esc-Xml "$($st.keyType)")</KeyType>" }
|
||||
if ($st.keyFields) { foreach ($kf in @($st.keyFields)) { X "$si<KeyField>$(Esc-Xml "$kf")</KeyField>" } }
|
||||
if ($st.keyType) { X "$si<KeyType>$(Esc-XmlText "$($st.keyType)")</KeyType>" }
|
||||
if ($st.keyFields) { foreach ($kf in @($st.keyFields)) { X "$si<KeyField>$(Esc-XmlText "$kf")</KeyField>" } }
|
||||
if ($st.mainTable) { X "$si<MainTable>$(Normalize-MetaTypeRef "$($st.mainTable)")</MainTable>" }
|
||||
# GetInvisibleFieldPresentations — после MainTable (дефолт true; эмитим только при заданном ключе = отклонении false).
|
||||
if ($null -ne $st.getInvisibleFieldPresentations) { X "$si<GetInvisibleFieldPresentations>$(if ($st.getInvisibleFieldPresentations){'true'}else{'false'})</GetInvisibleFieldPresentations>" }
|
||||
@@ -6141,7 +6147,7 @@ function Emit-Commands {
|
||||
if (-not $cmdTable) { $cmdTable = $cmd.associatedTableElementId }
|
||||
if (-not $cmdTable) { $cmdTable = $cmd.используемаяТаблица }
|
||||
if ($cmdTable) {
|
||||
X "$inner<AssociatedTableElementId xsi:type=`"xs:string`">$(Esc-Xml "$cmdTable")</AssociatedTableElementId>"
|
||||
X "$inner<AssociatedTableElementId xsi:type=`"xs:string`">$(Esc-XmlText "$cmdTable")</AssociatedTableElementId>"
|
||||
}
|
||||
|
||||
if ($cmd.shortcut) {
|
||||
@@ -6233,10 +6239,10 @@ function Emit-CommandInterface {
|
||||
# group из дерева побеждает (если задан и непустой); явный group элемента — фолбэк
|
||||
if ($treeGroup) { $grp = $treeGroup }
|
||||
X "$inner`t<Item>"
|
||||
X "$inner`t`t<Command>$(Esc-Xml "$cmd")</Command>"
|
||||
X "$inner`t`t<Command>$(Esc-XmlText "$cmd")</Command>"
|
||||
X "$inner`t`t<Type>$type</Type>"
|
||||
if ($attr) { X "$inner`t`t<Attribute>$(Esc-Xml "$attr")</Attribute>" }
|
||||
if ($grp) { X "$inner`t`t<CommandGroup>$(Esc-Xml "$grp")</CommandGroup>" }
|
||||
if ($attr) { X "$inner`t`t<Attribute>$(Esc-XmlText "$attr")</Attribute>" }
|
||||
if ($grp) { X "$inner`t`t<CommandGroup>$(Esc-XmlText "$grp")</CommandGroup>" }
|
||||
if ($null -ne $idx) { X "$inner`t`t<Index>$idx</Index>" }
|
||||
if ($null -ne $dv) { X "$inner`t`t<DefaultVisible>$(if ($dv){'true'}else{'false'})</DefaultVisible>" }
|
||||
if ($null -ne $vis) { Emit-XrFlag -tag 'Visible' -val $vis -indent "$inner`t`t" }
|
||||
@@ -6573,7 +6579,7 @@ if ($null -ne $def.mobileCommandBarContent -and @($def.mobileCommandBarContent).
|
||||
X "`t`t`t<xr:CheckState>0</xr:CheckState>"
|
||||
# пустое значение → самозакрывающийся тег (зеркало платформы)
|
||||
if ([string]::IsNullOrEmpty("$nm")) { X "`t`t`t<xr:Value xsi:type=`"xs:string`"/>" }
|
||||
else { X "`t`t`t<xr:Value xsi:type=`"xs:string`">$(Esc-Xml "$nm")</xr:Value>" }
|
||||
else { X "`t`t`t<xr:Value xsi:type=`"xs:string`">$(Esc-XmlText "$nm")</xr:Value>" }
|
||||
X "`t`t</xr:Item>"
|
||||
}
|
||||
X "`t</MobileDeviceCommandBarContent>"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# form-compile v1.187 — Compile 1C managed form from JSON or object metadata (+resolve_type_str: срезание префикса cfg:/d5p1:)
|
||||
# form-compile v1.188 — Compile 1C managed form from JSON or object metadata (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import copy
|
||||
@@ -1431,6 +1431,11 @@ def generate_chart_of_accounts_choice_dsl(meta, preset_data):
|
||||
|
||||
|
||||
def esc_xml(s):
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
def esc_xml_text(s):
|
||||
# Экранирование ТЕКСТА элемента (<v8:content>, <Value>): только & < > .
|
||||
# Кавычки/апострофы в тексте 1С не экранирует (пишет литерально) — " ломал бы раундтрип.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
@@ -1469,12 +1474,12 @@ def emit_ml_items(lines, indent, val):
|
||||
for k, v in val.items():
|
||||
lines.append(f"{indent}<v8:item>")
|
||||
lines.append(f"{indent}\t<v8:lang>{k}</v8:lang>")
|
||||
lines.append(f"{indent}\t<v8:content>{esc_xml(str(v))}</v8:content>")
|
||||
lines.append(f"{indent}\t<v8:content>{esc_xml_text(str(v))}</v8:content>")
|
||||
lines.append(f"{indent}</v8:item>")
|
||||
else:
|
||||
lines.append(f"{indent}<v8:item>")
|
||||
lines.append(f"{indent}\t<v8:lang>ru</v8:lang>")
|
||||
lines.append(f"{indent}\t<v8:content>{esc_xml(str(val))}</v8:content>")
|
||||
lines.append(f"{indent}\t<v8:content>{esc_xml_text(str(val))}</v8:content>")
|
||||
lines.append(f"{indent}</v8:item>")
|
||||
|
||||
|
||||
@@ -1493,7 +1498,7 @@ def emit_us_presentation(lines, indent, tag, val):
|
||||
if val is None:
|
||||
return
|
||||
if isinstance(val, str):
|
||||
lines.append(f'{indent}<{tag} xsi:type="xs:string">{esc_xml(val)}</{tag}>')
|
||||
lines.append(f'{indent}<{tag} xsi:type="xs:string">{esc_xml_text(val)}</{tag}>')
|
||||
else:
|
||||
emit_mltext(lines, indent, tag, val, xsi_type='v8:LocalStringType')
|
||||
|
||||
@@ -1642,10 +1647,10 @@ def emit_filter_item(lines, item, indent):
|
||||
if item.get('presentation'):
|
||||
emit_us_presentation(lines, f'{indent}\t', 'dcsset:presentation', item['presentation'])
|
||||
if item.get('viewMode'):
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml(str(item["viewMode"]))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml_text(str(item["viewMode"]))}</dcsset:viewMode>')
|
||||
if item.get('userSettingID'):
|
||||
guid = new_uuid() if str(item['userSettingID']) == 'auto' else str(item['userSettingID'])
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml(guid)}</dcsset:userSettingID>')
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml_text(guid)}</dcsset:userSettingID>')
|
||||
if item.get('userSettingPresentation'):
|
||||
emit_us_presentation(lines, f'{indent}\t', 'dcsset:userSettingPresentation', item['userSettingPresentation'])
|
||||
lines.append(f'{indent}</dcsset:item>')
|
||||
@@ -1654,12 +1659,12 @@ def emit_filter_item(lines, item, indent):
|
||||
lines.append(f'{indent}<dcsset:item xsi:type="dcsset:FilterItemComparison">')
|
||||
if item.get('use') is False:
|
||||
lines.append(f'{indent}\t<dcsset:use>false</dcsset:use>')
|
||||
lines.append(f'{indent}\t<dcsset:left xsi:type="dcscor:Field">{esc_xml(str(item.get("field", "")))}</dcsset:left>')
|
||||
lines.append(f'{indent}\t<dcsset:left xsi:type="dcscor:Field">{esc_xml_text(str(item.get("field", "")))}</dcsset:left>')
|
||||
# Регистронезависимый лукап (зеркало PS): Like/LIKE/ПОДОБНО → канон; иначе — как есть
|
||||
comp_type = _COMPARISON_TYPES_CI.get(str(item.get('op')).lower())
|
||||
if not comp_type:
|
||||
comp_type = str(item.get('op'))
|
||||
lines.append(f'{indent}\t<dcsset:comparisonType>{esc_xml(comp_type)}</dcsset:comparisonType>')
|
||||
lines.append(f'{indent}\t<dcsset:comparisonType>{esc_xml_text(comp_type)}</dcsset:comparisonType>')
|
||||
val = item.get('value')
|
||||
if isinstance(val, list):
|
||||
if len(val) == 0:
|
||||
@@ -1670,7 +1675,7 @@ def emit_filter_item(lines, item, indent):
|
||||
else:
|
||||
for v in val:
|
||||
vt = _value_type_for(v, item.get('valueType'))
|
||||
v_str = str(v).lower() if isinstance(v, bool) else esc_xml(str(v))
|
||||
v_str = str(v).lower() if isinstance(v, bool) else esc_xml_text(str(v))
|
||||
ns_attr = _value_type_ns_attr(vt, v)
|
||||
lines.append(f'{indent}\t<dcsset:right{ns_attr} xsi:type="{vt}">{v_str}</dcsset:right>')
|
||||
elif val is not None and (
|
||||
@@ -1687,9 +1692,9 @@ def emit_filter_item(lines, item, indent):
|
||||
else:
|
||||
variant = str(val); date_v = None
|
||||
lines.append(f'{indent}\t<dcsset:right xsi:type="v8:{sd_type}">')
|
||||
lines.append(f'{indent}\t\t<v8:variant xsi:type="v8:{sd_type}Variant">{esc_xml(variant)}</v8:variant>')
|
||||
lines.append(f'{indent}\t\t<v8:variant xsi:type="v8:{sd_type}Variant">{esc_xml_text(variant)}</v8:variant>')
|
||||
if date_v is not None:
|
||||
lines.append(f'{indent}\t\t<v8:date>{esc_xml(str(date_v))}</v8:date>')
|
||||
lines.append(f'{indent}\t\t<v8:date>{esc_xml_text(str(date_v))}</v8:date>')
|
||||
lines.append(f'{indent}\t</dcsset:right>')
|
||||
elif str(val) == '_':
|
||||
# "_" — маркер пустого значения: платформа эмитит пустой self-closing <dcsset:right>
|
||||
@@ -1698,16 +1703,16 @@ def emit_filter_item(lines, item, indent):
|
||||
lines.append(f'{indent}\t<dcsset:right xsi:type="{vt}"/>')
|
||||
elif val is not None:
|
||||
vt = _value_type_for(val, item.get('valueType'))
|
||||
v_str = str(val).lower() if isinstance(val, bool) else esc_xml(str(val))
|
||||
v_str = str(val).lower() if isinstance(val, bool) else esc_xml_text(str(val))
|
||||
ns_attr = _value_type_ns_attr(vt, val)
|
||||
lines.append(f'{indent}\t<dcsset:right{ns_attr} xsi:type="{vt}">{v_str}</dcsset:right>')
|
||||
if item.get('presentation'):
|
||||
emit_us_presentation(lines, f'{indent}\t', 'dcsset:presentation', item['presentation'])
|
||||
if item.get('viewMode'):
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml(str(item["viewMode"]))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml_text(str(item["viewMode"]))}</dcsset:viewMode>')
|
||||
if item.get('userSettingID'):
|
||||
uid = new_uuid() if str(item['userSettingID']) == 'auto' else str(item['userSettingID'])
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml(uid)}</dcsset:userSettingID>')
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml_text(uid)}</dcsset:userSettingID>')
|
||||
if item.get('userSettingPresentation'):
|
||||
emit_us_presentation(lines, f'{indent}\t', 'dcsset:userSettingPresentation', item['userSettingPresentation'])
|
||||
lines.append(f'{indent}</dcsset:item>')
|
||||
@@ -1737,10 +1742,10 @@ def emit_filter(lines, items, indent, block_view_mode=None, block_user_setting_i
|
||||
else:
|
||||
emit_filter_item(lines, item, f'{indent}\t')
|
||||
if block_view_mode is not None:
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml(str(block_view_mode))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml_text(str(block_view_mode))}</dcsset:viewMode>')
|
||||
if block_user_setting_id is not None:
|
||||
uid = new_uuid() if str(block_user_setting_id) == 'auto' else str(block_user_setting_id)
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml(uid)}</dcsset:userSettingID>')
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml_text(uid)}</dcsset:userSettingID>')
|
||||
if block_user_setting_presentation is not None:
|
||||
emit_us_presentation(lines, f'{indent}\t', 'dcsset:userSettingPresentation', block_user_setting_presentation)
|
||||
lines.append(f'{indent}</dcsset:filter>')
|
||||
@@ -1766,7 +1771,7 @@ def emit_order(lines, items, indent, skip_auto=False, block_view_mode=None, bloc
|
||||
elif len(parts) > 1 and re.match(r'(?i)^(asc|возр)', parts[1]):
|
||||
direction = 'Asc'
|
||||
lines.append(f'{indent}\t<dcsset:item xsi:type="dcsset:OrderItemField">')
|
||||
lines.append(f'{indent}\t\t<dcsset:field>{esc_xml(field)}</dcsset:field>')
|
||||
lines.append(f'{indent}\t\t<dcsset:field>{esc_xml_text(field)}</dcsset:field>')
|
||||
lines.append(f'{indent}\t\t<dcsset:orderType>{direction}</dcsset:orderType>')
|
||||
lines.append(f'{indent}\t</dcsset:item>')
|
||||
else:
|
||||
@@ -1782,16 +1787,16 @@ def emit_order(lines, items, indent, skip_auto=False, block_view_mode=None, bloc
|
||||
lines.append(f'{indent}\t<dcsset:item xsi:type="dcsset:OrderItemField">')
|
||||
if item.get('use') is False:
|
||||
lines.append(f'{indent}\t\t<dcsset:use>false</dcsset:use>')
|
||||
lines.append(f'{indent}\t\t<dcsset:field>{esc_xml(str(item.get("field", "")))}</dcsset:field>')
|
||||
lines.append(f'{indent}\t\t<dcsset:field>{esc_xml_text(str(item.get("field", "")))}</dcsset:field>')
|
||||
lines.append(f'{indent}\t\t<dcsset:orderType>{direction}</dcsset:orderType>')
|
||||
if item.get('viewMode'):
|
||||
lines.append(f'{indent}\t\t<dcsset:viewMode>{esc_xml(str(item["viewMode"]))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t\t<dcsset:viewMode>{esc_xml_text(str(item["viewMode"]))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t</dcsset:item>')
|
||||
if block_view_mode is not None:
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml(str(block_view_mode))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml_text(str(block_view_mode))}</dcsset:viewMode>')
|
||||
if block_user_setting_id is not None:
|
||||
uid = new_uuid() if str(block_user_setting_id) == 'auto' else str(block_user_setting_id)
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml(uid)}</dcsset:userSettingID>')
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml_text(uid)}</dcsset:userSettingID>')
|
||||
if block_user_setting_presentation is not None:
|
||||
emit_us_presentation(lines, f'{indent}\t', 'dcsset:userSettingPresentation', block_user_setting_presentation)
|
||||
lines.append(f'{indent}</dcsset:order>')
|
||||
@@ -1823,7 +1828,7 @@ def emit_appearance_value(lines, key, val, indent):
|
||||
nested_items = _get(val, 'items')
|
||||
if use_wrapper:
|
||||
lines.append(f'{indent}\t<dcscor:use>false</dcscor:use>')
|
||||
lines.append(f'{indent}\t<dcscor:parameter>{esc_xml(key)}</dcscor:parameter>')
|
||||
lines.append(f'{indent}\t<dcscor:parameter>{esc_xml_text(key)}</dcscor:parameter>')
|
||||
|
||||
is_font_dict = isinstance(inner_val, dict) and inner_val.get('@type') is not None and str(inner_val.get('@type')) == 'Font'
|
||||
is_line_dict = _has_key(inner_val, '@type') and (str(_get(inner_val, '@type')) == 'Line')
|
||||
@@ -1833,7 +1838,7 @@ def emit_appearance_value(lines, key, val, indent):
|
||||
lg = ('true' if _get(inner_val, 'gap') else 'false') if _has_key(inner_val, 'gap') else 'false'
|
||||
ls = str(_get(inner_val, 'style')) if _has_key(inner_val, 'style') else 'None'
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="v8ui:Line" width="{lw}" gap="{lg}">')
|
||||
lines.append(f'{indent}\t\t<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">{esc_xml(ls)}</v8ui:style>')
|
||||
lines.append(f'{indent}\t\t<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">{esc_xml_text(ls)}</v8ui:style>')
|
||||
lines.append(f'{indent}\t</dcscor:value>')
|
||||
elif is_font_dict:
|
||||
attr_parts = []
|
||||
@@ -1845,7 +1850,7 @@ def emit_appearance_value(lines, key, val, indent):
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="v8ui:Font" {" ".join(attr_parts)}/>')
|
||||
elif is_dict and _has_key(inner_val, 'field'):
|
||||
# Ссылка на поле (dcscor:Field) — значение параметра оформления = поле компоновки
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="dcscor:Field">{esc_xml(str(_get(inner_val, "field")))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="dcscor:Field">{esc_xml_text(str(_get(inner_val, "field")))}</dcscor:value>')
|
||||
elif is_dict:
|
||||
# Локализуемый текст параметра оформления: платформа объявляет xsi:type на dcscor:value
|
||||
emit_mltext(lines, f'{indent}\t', 'dcscor:value', inner_val, xsi_type='v8:LocalStringType')
|
||||
@@ -1861,9 +1866,9 @@ def emit_appearance_value(lines, key, val, indent):
|
||||
}
|
||||
key_type = key_type_map.get(key)
|
||||
if key_type:
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="{key_type}">{esc_xml(actual_val)}</dcscor:value>')
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="{key_type}">{esc_xml_text(actual_val)}</dcscor:value>')
|
||||
elif re.match(r'^(style|web|win):', actual_val):
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="v8ui:Color">{esc_xml(actual_val)}</dcscor:value>')
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="v8ui:Color">{esc_xml_text(actual_val)}</dcscor:value>')
|
||||
elif actual_val == 'true' or actual_val == 'false':
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="xs:boolean">{actual_val}</dcscor:value>')
|
||||
elif key == 'Текст' or key == 'Заголовок' or key == 'Формат':
|
||||
@@ -1872,13 +1877,13 @@ def emit_appearance_value(lines, key, val, indent):
|
||||
if actual_val == '':
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="xs:string"/>')
|
||||
else:
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="xs:string">{esc_xml(actual_val)}</dcscor:value>')
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="xs:string">{esc_xml_text(actual_val)}</dcscor:value>')
|
||||
elif re.match(r'^-?\d+(\.\d+)?$', actual_val):
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="xs:decimal">{actual_val}</dcscor:value>')
|
||||
elif key == 'ЦветТекста' or key == 'ЦветФона' or key == 'ЦветГраницы':
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="v8ui:Color">{esc_xml(actual_val)}</dcscor:value>')
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="v8ui:Color">{esc_xml_text(actual_val)}</dcscor:value>')
|
||||
else:
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="xs:string">{esc_xml(actual_val)}</dcscor:value>')
|
||||
lines.append(f'{indent}\t<dcscor:value xsi:type="xs:string">{esc_xml_text(actual_val)}</dcscor:value>')
|
||||
if nested_items:
|
||||
if isinstance(nested_items, dict):
|
||||
for nk, nv in nested_items.items():
|
||||
@@ -1916,14 +1921,14 @@ def emit_group_item_field(lines, level, indent):
|
||||
pab = str(level.get('periodAdditionBegin') or '0001-01-01T00:00:00')
|
||||
pae = str(level.get('periodAdditionEnd') or '0001-01-01T00:00:00')
|
||||
lines.append(f'{indent}<dcsset:item xsi:type="dcsset:GroupItemField">')
|
||||
lines.append(f'{indent}\t<dcsset:field>{esc_xml(field)}</dcsset:field>')
|
||||
lines.append(f'{indent}\t<dcsset:groupType>{esc_xml(gt)}</dcsset:groupType>')
|
||||
lines.append(f'{indent}\t<dcsset:periodAdditionType>{esc_xml(pat)}</dcsset:periodAdditionType>')
|
||||
lines.append(f'{indent}\t<dcsset:field>{esc_xml_text(field)}</dcsset:field>')
|
||||
lines.append(f'{indent}\t<dcsset:groupType>{esc_xml_text(gt)}</dcsset:groupType>')
|
||||
lines.append(f'{indent}\t<dcsset:periodAdditionType>{esc_xml_text(pat)}</dcsset:periodAdditionType>')
|
||||
# Авто-детект: ISO-дата → xs:dateTime, иначе путь → dcscor:Field.
|
||||
pab_t = 'xs:dateTime' if re.match(r'^\d{4}-\d{2}-\d{2}T', pab) else 'dcscor:Field'
|
||||
pae_t = 'xs:dateTime' if re.match(r'^\d{4}-\d{2}-\d{2}T', pae) else 'dcscor:Field'
|
||||
lines.append(f'{indent}\t<dcsset:periodAdditionBegin xsi:type="{pab_t}">{esc_xml(pab)}</dcsset:periodAdditionBegin>')
|
||||
lines.append(f'{indent}\t<dcsset:periodAdditionEnd xsi:type="{pae_t}">{esc_xml(pae)}</dcsset:periodAdditionEnd>')
|
||||
lines.append(f'{indent}\t<dcsset:periodAdditionBegin xsi:type="{pab_t}">{esc_xml_text(pab)}</dcsset:periodAdditionBegin>')
|
||||
lines.append(f'{indent}\t<dcsset:periodAdditionEnd xsi:type="{pae_t}">{esc_xml_text(pae)}</dcsset:periodAdditionEnd>')
|
||||
lines.append(f'{indent}</dcsset:item>')
|
||||
|
||||
|
||||
@@ -1999,8 +2004,8 @@ def emit_calc_fields(lines, calc_fields, indent):
|
||||
order_expr = cf.get('orderExpression')
|
||||
ci = f'{indent}\t'
|
||||
lines.append(f'{indent}<CalculatedField>')
|
||||
lines.append(f'{ci}<dcssch:dataPath>{esc_xml(data_path)}</dcssch:dataPath>')
|
||||
lines.append(f'{ci}<dcssch:expression>{esc_xml(expression)}</dcssch:expression>')
|
||||
lines.append(f'{ci}<dcssch:dataPath>{esc_xml_text(data_path)}</dcssch:dataPath>')
|
||||
lines.append(f'{ci}<dcssch:expression>{esc_xml_text(expression)}</dcssch:expression>')
|
||||
if title:
|
||||
emit_mltext(lines, ci, 'dcssch:title', title, xsi_type='v8:LocalStringType')
|
||||
if restrict:
|
||||
@@ -2010,7 +2015,7 @@ def emit_calc_fields(lines, calc_fields, indent):
|
||||
lines.append(f'{ci}\t<dcssch:{r}>true</dcssch:{r}>')
|
||||
lines.append(f'{ci}</dcssch:useRestriction>')
|
||||
if pres_expr:
|
||||
lines.append(f'{ci}<dcssch:presentationExpression>{esc_xml(str(pres_expr))}</dcssch:presentationExpression>')
|
||||
lines.append(f'{ci}<dcssch:presentationExpression>{esc_xml_text(str(pres_expr))}</dcssch:presentationExpression>')
|
||||
if order_expr:
|
||||
for oe in (order_expr if isinstance(order_expr, list) else [order_expr]):
|
||||
if isinstance(oe, str):
|
||||
@@ -2020,7 +2025,7 @@ def emit_calc_fields(lines, calc_fields, indent):
|
||||
otype = str(oe.get('orderType', 'Asc'))
|
||||
auto = 'true' if oe.get('autoOrder') else 'false'
|
||||
lines.append(f'{ci}<dcssch:orderExpression>')
|
||||
lines.append(f'{ci}\t<expression xmlns="{_DCS_COMMON_NS}">{esc_xml(expr_v)}</expression>')
|
||||
lines.append(f'{ci}\t<expression xmlns="{_DCS_COMMON_NS}">{esc_xml_text(expr_v)}</expression>')
|
||||
lines.append(f'{ci}\t<orderType xmlns="{_DCS_COMMON_NS}">{otype}</orderType>')
|
||||
lines.append(f'{ci}\t<autoOrder xmlns="{_DCS_COMMON_NS}">{auto}</autoOrder>')
|
||||
lines.append(f'{ci}</dcssch:orderExpression>')
|
||||
@@ -2068,7 +2073,7 @@ def emit_conditional_appearance(lines, items, indent, block_view_mode=None, bloc
|
||||
lines.append(f'{indent}\t\t<dcsset:selection>')
|
||||
for sel in ca['selection']:
|
||||
lines.append(f'{indent}\t\t\t<dcsset:item>')
|
||||
lines.append(f'{indent}\t\t\t\t<dcsset:field>{esc_xml(str(sel))}</dcsset:field>')
|
||||
lines.append(f'{indent}\t\t\t\t<dcsset:field>{esc_xml_text(str(sel))}</dcsset:field>')
|
||||
lines.append(f'{indent}\t\t\t</dcsset:item>')
|
||||
lines.append(f'{indent}\t\t</dcsset:selection>')
|
||||
else:
|
||||
@@ -2089,12 +2094,12 @@ def emit_conditional_appearance(lines, items, indent, block_view_mode=None, bloc
|
||||
emit_ml_items(lines, f'{indent}\t\t\t', ca['presentation'])
|
||||
lines.append(f'{indent}\t\t</dcsset:presentation>')
|
||||
else:
|
||||
lines.append(f'{indent}\t\t<dcsset:presentation xsi:type="xs:string">{esc_xml(str(ca["presentation"]))}</dcsset:presentation>')
|
||||
lines.append(f'{indent}\t\t<dcsset:presentation xsi:type="xs:string">{esc_xml_text(str(ca["presentation"]))}</dcsset:presentation>')
|
||||
if ca.get('viewMode'):
|
||||
lines.append(f'{indent}\t\t<dcsset:viewMode>{esc_xml(str(ca["viewMode"]))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t\t<dcsset:viewMode>{esc_xml_text(str(ca["viewMode"]))}</dcsset:viewMode>')
|
||||
if ca.get('userSettingID'):
|
||||
uid = new_uuid() if str(ca['userSettingID']) == 'auto' else str(ca['userSettingID'])
|
||||
lines.append(f'{indent}\t\t<dcsset:userSettingID>{esc_xml(uid)}</dcsset:userSettingID>')
|
||||
lines.append(f'{indent}\t\t<dcsset:userSettingID>{esc_xml_text(uid)}</dcsset:userSettingID>')
|
||||
if ca.get('userSettingPresentation'):
|
||||
emit_us_presentation(lines, f'{indent}\t\t', 'dcsset:userSettingPresentation', ca['userSettingPresentation'])
|
||||
if ca.get('useInDontUse') and len(ca['useInDontUse']) > 0:
|
||||
@@ -2108,10 +2113,10 @@ def emit_conditional_appearance(lines, items, indent, block_view_mode=None, bloc
|
||||
lines.append(f'{indent}\t\t<dcsset:{tag}>DontUse</dcsset:{tag}>')
|
||||
lines.append(f'{indent}\t</dcsset:item>')
|
||||
if block_view_mode is not None:
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml(str(block_view_mode))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml_text(str(block_view_mode))}</dcsset:viewMode>')
|
||||
if block_user_setting_id is not None:
|
||||
uid = new_uuid() if str(block_user_setting_id) == 'auto' else str(block_user_setting_id)
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml(uid)}</dcsset:userSettingID>')
|
||||
lines.append(f'{indent}\t<dcsset:userSettingID>{esc_xml_text(uid)}</dcsset:userSettingID>')
|
||||
if block_user_setting_presentation is not None:
|
||||
emit_us_presentation(lines, f'{indent}\t', 'dcsset:userSettingPresentation', block_user_setting_presentation)
|
||||
lines.append(f'{indent}</{wrap_tag}>')
|
||||
@@ -2482,7 +2487,7 @@ def emit_choice_presentation(lines, pres, indent):
|
||||
for lang, content in pairs:
|
||||
lines.append(f"{indent}\t<v8:item>")
|
||||
lines.append(f"{indent}\t\t<v8:lang>{lang}</v8:lang>")
|
||||
lines.append(f"{indent}\t\t<v8:content>{esc_xml(content)}</v8:content>")
|
||||
lines.append(f"{indent}\t\t<v8:content>{esc_xml_text(content)}</v8:content>")
|
||||
lines.append(f"{indent}\t</v8:item>")
|
||||
lines.append(f"{indent}</Presentation>")
|
||||
|
||||
@@ -2491,7 +2496,7 @@ def choice_value_tag(norm):
|
||||
# <Value> для choiceList/choiceParameters: пустой текст → самозакрывающийся тег (зеркало платформы).
|
||||
if not norm["text"]:
|
||||
return f'<Value xsi:type="{norm["xsi_type"]}"/>'
|
||||
return f'<Value xsi:type="{norm["xsi_type"]}">{esc_xml(norm["text"])}</Value>'
|
||||
return f'<Value xsi:type="{norm["xsi_type"]}">{esc_xml_text(norm["text"])}</Value>'
|
||||
|
||||
|
||||
def emit_choice_list(lines, el, indent):
|
||||
@@ -2668,8 +2673,8 @@ def emit_choice_parameter_links(lines, el, indent):
|
||||
name_s = '' if name is None else str(name)
|
||||
dp_s = '' if dp is None else str(dp)
|
||||
lines.append(f'{indent}\t<xr:Link>')
|
||||
lines.append(f'{indent}\t\t<xr:Name>{esc_xml(name_s)}</xr:Name>')
|
||||
lines.append(f'{indent}\t\t<xr:DataPath xsi:type="xs:string">{esc_xml(dp_s)}</xr:DataPath>')
|
||||
lines.append(f'{indent}\t\t<xr:Name>{esc_xml_text(name_s)}</xr:Name>')
|
||||
lines.append(f'{indent}\t\t<xr:DataPath xsi:type="xs:string">{esc_xml_text(dp_s)}</xr:DataPath>')
|
||||
lines.append(f'{indent}\t\t<xr:ValueChange>{vc}</xr:ValueChange>')
|
||||
lines.append(f'{indent}\t</xr:Link>')
|
||||
lines.append(f'{indent}</ChoiceParameterLinks>')
|
||||
@@ -2688,7 +2693,7 @@ def emit_type_link(lines, el, indent):
|
||||
li = 0
|
||||
dp_s = '' if dp is None else str(dp)
|
||||
lines.append(f'{indent}<TypeLink>')
|
||||
lines.append(f'{indent}\t<xr:DataPath>{esc_xml(dp_s)}</xr:DataPath>')
|
||||
lines.append(f'{indent}\t<xr:DataPath>{esc_xml_text(dp_s)}</xr:DataPath>')
|
||||
lines.append(f'{indent}\t<xr:LinkItem>{li}</xr:LinkItem>')
|
||||
lines.append(f'{indent}</TypeLink>')
|
||||
|
||||
@@ -3011,7 +3016,7 @@ def emit_common_element_props(lines, el, indent):
|
||||
lines.append(f'{indent}<{tag}>{"true" if el[key] else "false"}</{tag}>')
|
||||
# Динамический заголовок колонки-группы из данных (HeaderDataPath) — перед HeaderHorizontalAlign (порядок XSD)
|
||||
if el.get('headerDataPath'):
|
||||
lines.append(f"{indent}<HeaderDataPath>{esc_xml(str(el['headerDataPath']))}</HeaderDataPath>")
|
||||
lines.append(f"{indent}<HeaderDataPath>{esc_xml_text(str(el['headerDataPath']))}</HeaderDataPath>")
|
||||
if el.get('footerHorizontalAlign'):
|
||||
lines.append(f"{indent}<FooterHorizontalAlign>{el['footerHorizontalAlign']}</FooterHorizontalAlign>")
|
||||
if el.get('headerHorizontalAlign'):
|
||||
@@ -3040,9 +3045,9 @@ def emit_picture_ref(lines, val, pic_tag, indent):
|
||||
src_str = str(src)
|
||||
lines.append(f"{indent}<{pic_tag}>")
|
||||
if src_str.startswith('abs:'):
|
||||
lines.append(f"{indent}\t<xr:Abs>{esc_xml(src_str[4:])}</xr:Abs>")
|
||||
lines.append(f"{indent}\t<xr:Abs>{esc_xml_text(src_str[4:])}</xr:Abs>")
|
||||
else:
|
||||
lines.append(f"{indent}\t<xr:Ref>{esc_xml(src_str)}</xr:Ref>")
|
||||
lines.append(f"{indent}\t<xr:Ref>{esc_xml_text(src_str)}</xr:Ref>")
|
||||
lines.append(f'{indent}\t<xr:LoadTransparent>{"true" if lt else "false"}</xr:LoadTransparent>')
|
||||
if tpx:
|
||||
lines.append(f'{indent}\t<xr:TransparentPixel x="{tpx.get("x")}" y="{tpx.get("y")}"/>')
|
||||
@@ -3080,9 +3085,9 @@ def emit_command_picture(lines, pic, elem_lt, indent):
|
||||
src_str = str(src)
|
||||
lines.append(f'{indent}<Picture>')
|
||||
if src_str.startswith('abs:'):
|
||||
lines.append(f'{indent}\t<xr:Abs>{esc_xml(src_str[4:])}</xr:Abs>')
|
||||
lines.append(f'{indent}\t<xr:Abs>{esc_xml_text(src_str[4:])}</xr:Abs>')
|
||||
else:
|
||||
lines.append(f'{indent}\t<xr:Ref>{esc_xml(src_str)}</xr:Ref>')
|
||||
lines.append(f'{indent}\t<xr:Ref>{esc_xml_text(src_str)}</xr:Ref>')
|
||||
lines.append(f'{indent}\t<xr:LoadTransparent>{"false" if lt is False else "true"}</xr:LoadTransparent>')
|
||||
if tpx:
|
||||
lines.append(f'{indent}\t<xr:TransparentPixel x="{tpx.get("x")}" y="{tpx.get("y")}"/>')
|
||||
@@ -3172,7 +3177,7 @@ def emit_border_tag(lines, val, indent):
|
||||
style = str(val['style']) if 'style' in val else None
|
||||
lines.append(f'{indent}<Border width="{width}">')
|
||||
if style:
|
||||
lines.append(f'{indent}\t<v8ui:style xsi:type="v8ui:ControlBorderType">{esc_xml(style)}</v8ui:style>')
|
||||
lines.append(f'{indent}\t<v8ui:style xsi:type="v8ui:ControlBorderType">{esc_xml_text(style)}</v8ui:style>')
|
||||
lines.append(f'{indent}</Border>')
|
||||
|
||||
|
||||
@@ -3199,14 +3204,14 @@ def _pl_bool(v):
|
||||
|
||||
|
||||
def emit_planner_color(lines, tag, o, key, ind):
|
||||
lines.append(f'{ind}<pl:{tag}>{esc_xml(str(_pl_get(o, key, "auto")))}</pl:{tag}>')
|
||||
lines.append(f'{ind}<pl:{tag}>{esc_xml_text(str(_pl_get(o, key, "auto")))}</pl:{tag}>')
|
||||
|
||||
|
||||
def emit_planner_text(lines, tag, v, ind):
|
||||
if v is None or str(v) == '':
|
||||
lines.append(f'{ind}<pl:{tag}/>')
|
||||
else:
|
||||
lines.append(f'{ind}<pl:{tag}>{esc_xml(str(v))}</pl:{tag}>')
|
||||
lines.append(f'{ind}<pl:{tag}>{esc_xml_text(str(v))}</pl:{tag}>')
|
||||
|
||||
|
||||
_PLANNER_REF_RE = re.compile(
|
||||
@@ -3224,7 +3229,7 @@ def emit_planner_value(lines, v, ind):
|
||||
lines.append(f'{ind}<pl:value xsi:nil="true"/>')
|
||||
return
|
||||
t = 'xr:DesignTimeRef' if test_planner_ref(v) else 'xs:string'
|
||||
lines.append(f'{ind}<pl:value xsi:type="{t}">{esc_xml(str(v))}</pl:value>')
|
||||
lines.append(f'{ind}<pl:value xsi:type="{t}">{esc_xml_text(str(v))}</pl:value>')
|
||||
|
||||
|
||||
def emit_planner_font(lines, o, ind):
|
||||
@@ -3240,14 +3245,14 @@ def emit_planner_border(lines, o, ind, key='border'):
|
||||
bw = _pl_get(b, 'width', 1) if b else 1
|
||||
bs = _pl_get(b, 'style', 'Single') if b else 'Single'
|
||||
lines.append(f'{ind}<pl:border width="{bw}">')
|
||||
lines.append(f'{ind}\t<v8ui:style xsi:type="v8ui:ControlBorderType">{esc_xml(str(bs))}</v8ui:style>')
|
||||
lines.append(f'{ind}\t<v8ui:style xsi:type="v8ui:ControlBorderType">{esc_xml_text(str(bs))}</v8ui:style>')
|
||||
lines.append(f'{ind}</pl:border>')
|
||||
|
||||
|
||||
def emit_planner_level(lines, lv, cns, ind):
|
||||
li = f'{ind}\t'
|
||||
lines.append(f'{ind}<level xmlns="{cns}">')
|
||||
lines.append(f'{li}<measure>{esc_xml(str(_pl_get(lv, "measure", "Hour")))}</measure>')
|
||||
lines.append(f'{li}<measure>{esc_xml_text(str(_pl_get(lv, "measure", "Hour")))}</measure>')
|
||||
lines.append(f'{li}<interval>{_pl_get(lv, "interval", 1)}</interval>')
|
||||
lines.append(f'{li}<show>{_pl_bool(_pl_get(lv, "show", True))}</show>')
|
||||
line = _pl_get(lv, 'line')
|
||||
@@ -3255,10 +3260,10 @@ def emit_planner_level(lines, lv, cns, ind):
|
||||
lg = _pl_get(line, 'gap', False) if line else False
|
||||
lst = _pl_get(line, 'style', 'Solid') if line else 'Solid'
|
||||
lines.append(f'{li}<line width="{lw}" gap="{_pl_bool(lg)}">')
|
||||
lines.append(f'{li}\t<v8ui:style xsi:type="v8ui:ChartLineType">{esc_xml(str(lst))}</v8ui:style>')
|
||||
lines.append(f'{li}\t<v8ui:style xsi:type="v8ui:ChartLineType">{esc_xml_text(str(lst))}</v8ui:style>')
|
||||
lines.append(f'{li}</line>')
|
||||
lines.append(f'{li}<scaleColor>{esc_xml(str(_pl_get(lv, "scaleColor", "auto")))}</scaleColor>')
|
||||
lines.append(f'{li}<dayFormatRule>{esc_xml(str(_pl_get(lv, "dayFormatRule", "MonthDayWeekDay")))}</dayFormatRule>')
|
||||
lines.append(f'{li}<scaleColor>{esc_xml_text(str(_pl_get(lv, "scaleColor", "auto")))}</scaleColor>')
|
||||
lines.append(f'{li}<dayFormatRule>{esc_xml_text(str(_pl_get(lv, "dayFormatRule", "MonthDayWeekDay")))}</dayFormatRule>')
|
||||
fmt = _pl_get(lv, 'format')
|
||||
if fmt is None:
|
||||
fmt = {'#': 'DF="HH:mm"', 'ru': 'DF="HH:mm"'}
|
||||
@@ -3270,8 +3275,8 @@ def emit_planner_level(lines, lv, cns, ind):
|
||||
lines.append(f'{li}<labels>')
|
||||
lines.append(f'{li}\t<ticks>{ticks}</ticks>')
|
||||
lines.append(f'{li}</labels>')
|
||||
lines.append(f'{li}<backColor>{esc_xml(str(_pl_get(lv, "backColor", "auto")))}</backColor>')
|
||||
lines.append(f'{li}<textColor>{esc_xml(str(_pl_get(lv, "textColor", "auto")))}</textColor>')
|
||||
lines.append(f'{li}<backColor>{esc_xml_text(str(_pl_get(lv, "backColor", "auto")))}</backColor>')
|
||||
lines.append(f'{li}<textColor>{esc_xml_text(str(_pl_get(lv, "textColor", "auto")))}</textColor>')
|
||||
lines.append(f'{li}<showPereodicalLabels>{_pl_bool(_pl_get(lv, "showPereodicalLabels", True))}</showPereodicalLabels>')
|
||||
lines.append(f'{ind}</level>')
|
||||
|
||||
@@ -3281,7 +3286,7 @@ def emit_planner_timescale(lines, ts, ind):
|
||||
ci = f'{ind}\t'
|
||||
lines.append(f'{ind}<pl:timeScale>')
|
||||
placement = _pl_get(ts, 'placement', 'Left') if ts else 'Left'
|
||||
lines.append(f'{ci}<placement xmlns="{cns}">{esc_xml(str(placement))}</placement>')
|
||||
lines.append(f'{ci}<placement xmlns="{cns}">{esc_xml_text(str(placement))}</placement>')
|
||||
levels = _pl_get(ts, 'levels', []) if ts else []
|
||||
if not levels:
|
||||
levels = [None]
|
||||
@@ -3292,8 +3297,8 @@ def emit_planner_timescale(lines, ts, ind):
|
||||
tbc = _pl_get(ts, 'backColor', 'auto') if ts else 'auto'
|
||||
ttc = _pl_get(ts, 'textColor', 'auto') if ts else 'auto'
|
||||
tcl = _pl_get(ts, 'currentLevel', 0) if ts else 0
|
||||
lines.append(f'{ci}<backColor xmlns="{cns}">{esc_xml(str(tbc))}</backColor>')
|
||||
lines.append(f'{ci}<textColor xmlns="{cns}">{esc_xml(str(ttc))}</textColor>')
|
||||
lines.append(f'{ci}<backColor xmlns="{cns}">{esc_xml_text(str(tbc))}</backColor>')
|
||||
lines.append(f'{ci}<textColor xmlns="{cns}">{esc_xml_text(str(ttc))}</textColor>')
|
||||
lines.append(f'{ci}<currentLevel xmlns="{cns}">{tcl}</currentLevel>')
|
||||
lines.append(f'{ind}</pl:timeScale>')
|
||||
|
||||
@@ -3320,7 +3325,7 @@ def emit_planner_item(lines, it, ind):
|
||||
lines.append(f'{ii}<pl:id>{iid}</pl:id>')
|
||||
lines.append(f'{ii}<pl:textFormatted>{_pl_bool(_pl_get(it, "textFormatted", False))}</pl:textFormatted>')
|
||||
emit_planner_border(lines, it, ii, 'border')
|
||||
lines.append(f'{ii}<pl:editMode>{esc_xml(str(_pl_get(it, "editMode", "EnableEdit")))}</pl:editMode>')
|
||||
lines.append(f'{ii}<pl:editMode>{esc_xml_text(str(_pl_get(it, "editMode", "EnableEdit")))}</pl:editMode>')
|
||||
lines.append(f'{ind}</pl:item>')
|
||||
|
||||
|
||||
@@ -3376,7 +3381,7 @@ def emit_planner_settings(lines, pl, ind):
|
||||
if wfmt is None:
|
||||
wfmt = {'#': 'DLF="DD"', 'ru': 'DLF="DD"'}
|
||||
emit_mltext(lines, si, 'pl:timeScaleWrapHeadersFormat', wfmt)
|
||||
lines.append(f'{si}<pl:periodicVariantUnit>{esc_xml(str(_pl_get(pl, "periodicVariantUnit", "Day")))}</pl:periodicVariantUnit>')
|
||||
lines.append(f'{si}<pl:periodicVariantUnit>{esc_xml_text(str(_pl_get(pl, "periodicVariantUnit", "Day")))}</pl:periodicVariantUnit>')
|
||||
lines.append(f'{si}<pl:periodicVariantRepetition>{_pl_get(pl, "periodicVariantRepetition", 1)}</pl:periodicVariantRepetition>')
|
||||
lines.append(f'{si}<pl:timeScaleWrapBeginIndent>{_pl_get(pl, "timeScaleWrapBeginIndent", 0)}</pl:timeScaleWrapBeginIndent>')
|
||||
lines.append(f'{si}<pl:timeScaleWrapEndIndent>{_pl_get(pl, "timeScaleWrapEndIndent", 0)}</pl:timeScaleWrapEndIndent>')
|
||||
@@ -3388,16 +3393,16 @@ def emit_planner_settings(lines, pl, ind):
|
||||
lines.append(f'{si}\t<pl:end>{_pl_get(period, "end", "0001-01-01T00:00:00")}</pl:end>')
|
||||
lines.append(f'{si}</pl:period>')
|
||||
lines.append(f'{si}<pl:displayCurrentDate>{_pl_bool(_pl_get(pl, "displayCurrentDate", True))}</pl:displayCurrentDate>')
|
||||
lines.append(f'{si}<pl:itemsTimeRepresentation>{esc_xml(str(_pl_get(pl, "itemsTimeRepresentation", "BeginTime")))}</pl:itemsTimeRepresentation>')
|
||||
lines.append(f'{si}<pl:itemsBehaviorWhenSpaceInsufficient>{esc_xml(str(_pl_get(pl, "itemsBehaviorWhenSpaceInsufficient", "CollapseItems")))}</pl:itemsBehaviorWhenSpaceInsufficient>')
|
||||
lines.append(f'{si}<pl:itemsTimeRepresentation>{esc_xml_text(str(_pl_get(pl, "itemsTimeRepresentation", "BeginTime")))}</pl:itemsTimeRepresentation>')
|
||||
lines.append(f'{si}<pl:itemsBehaviorWhenSpaceInsufficient>{esc_xml_text(str(_pl_get(pl, "itemsBehaviorWhenSpaceInsufficient", "CollapseItems")))}</pl:itemsBehaviorWhenSpaceInsufficient>')
|
||||
lines.append(f'{si}<pl:autoMinColumnWidth>{_pl_bool(_pl_get(pl, "autoMinColumnWidth", True))}</pl:autoMinColumnWidth>')
|
||||
lines.append(f'{si}<pl:autoMinRowHeight>{_pl_bool(_pl_get(pl, "autoMinRowHeight", True))}</pl:autoMinRowHeight>')
|
||||
lines.append(f'{si}<pl:minColumnWidth>{_pl_get(pl, "minColumnWidth", 0)}</pl:minColumnWidth>')
|
||||
lines.append(f'{si}<pl:minRowHeight>{_pl_get(pl, "minRowHeight", 0)}</pl:minRowHeight>')
|
||||
lines.append(f'{si}<pl:fixDimensionsHeader>{esc_xml(str(_pl_get(pl, "fixDimensionsHeader", "auto")))}</pl:fixDimensionsHeader>')
|
||||
lines.append(f'{si}<pl:fixTimeScaleHeader>{esc_xml(str(_pl_get(pl, "fixTimeScaleHeader", "auto")))}</pl:fixTimeScaleHeader>')
|
||||
lines.append(f'{si}<pl:fixDimensionsHeader>{esc_xml_text(str(_pl_get(pl, "fixDimensionsHeader", "auto")))}</pl:fixDimensionsHeader>')
|
||||
lines.append(f'{si}<pl:fixTimeScaleHeader>{esc_xml_text(str(_pl_get(pl, "fixTimeScaleHeader", "auto")))}</pl:fixTimeScaleHeader>')
|
||||
emit_planner_border(lines, pl, si, 'border')
|
||||
lines.append(f'{si}<pl:newItemsTextType>{esc_xml(str(_pl_get(pl, "newItemsTextType", "String")))}</pl:newItemsTextType>')
|
||||
lines.append(f'{si}<pl:newItemsTextType>{esc_xml_text(str(_pl_get(pl, "newItemsTextType", "String")))}</pl:newItemsTextType>')
|
||||
lines.append(f'{ind}</Settings>')
|
||||
|
||||
|
||||
@@ -3430,12 +3435,12 @@ def emit_chart_node(lines, name, val, ind):
|
||||
return
|
||||
if 'gap' in val:
|
||||
lines.append(f'{ind}<d4p1:{name} width="{val.get("width")}" gap="{_pl_bool(val.get("gap"))}">')
|
||||
lines.append(f'{ind}\t<v8ui:style xsi:type="v8ui:ChartLineType">{esc_xml(str(val.get("style")))}</v8ui:style>')
|
||||
lines.append(f'{ind}\t<v8ui:style xsi:type="v8ui:ChartLineType">{esc_xml_text(str(val.get("style")))}</v8ui:style>')
|
||||
lines.append(f'{ind}</d4p1:{name}>')
|
||||
return
|
||||
if 'style' in val and 'width' in val:
|
||||
lines.append(f'{ind}<d4p1:{name} width="{val.get("width")}">')
|
||||
lines.append(f'{ind}\t<v8ui:style xsi:type="v8ui:ControlBorderType">{esc_xml(str(val.get("style")))}</v8ui:style>')
|
||||
lines.append(f'{ind}\t<v8ui:style xsi:type="v8ui:ControlBorderType">{esc_xml_text(str(val.get("style")))}</v8ui:style>')
|
||||
lines.append(f'{ind}</d4p1:{name}>')
|
||||
return
|
||||
if any(fk in val for fk in CHART_FONT_KEYS):
|
||||
@@ -3456,7 +3461,7 @@ def emit_chart_node(lines, name, val, ind):
|
||||
if isinstance(val, bool):
|
||||
lines.append(f'{ind}<d4p1:{name}>{_pl_bool(val)}</d4p1:{name}>')
|
||||
return
|
||||
lines.append(f'{ind}<d4p1:{name}>{esc_xml(str(val))}</d4p1:{name}>')
|
||||
lines.append(f'{ind}<d4p1:{name}>{esc_xml_text(str(val))}</d4p1:{name}>')
|
||||
|
||||
|
||||
def emit_chart_settings(lines, chart, ind, ctype='d4p1:Chart'):
|
||||
@@ -3476,7 +3481,7 @@ def emit_appearance(lines, el, indent, profile='field'):
|
||||
continue
|
||||
tag, kind = APPEARANCE_SPEC[key]
|
||||
if kind == 'color':
|
||||
lines.append(f'{indent}<{tag}>{esc_xml(str(val))}</{tag}>')
|
||||
lines.append(f'{indent}<{tag}>{esc_xml_text(str(val))}</{tag}>')
|
||||
elif kind == 'font':
|
||||
emit_font_tag(lines, tag, val, indent)
|
||||
else:
|
||||
@@ -3588,7 +3593,7 @@ def emit_generic_scalars(lines, el, indent):
|
||||
v = str(el[key])
|
||||
if v == '':
|
||||
continue
|
||||
lines.append(f'{indent}<{tag}>{esc_xml(v)}</{tag}>')
|
||||
lines.append(f'{indent}<{tag}>{esc_xml_text(v)}</{tag}>')
|
||||
|
||||
|
||||
def emit_layout(lines, el, indent, skip_height=False, multi_line_default=False):
|
||||
@@ -4214,12 +4219,12 @@ def emit_input(lines, el, name, eid, indent):
|
||||
for key, tag in (('choiceForm', 'ChoiceForm'), ('choiceHistoryOnInput', 'ChoiceHistoryOnInput'),
|
||||
('choiceFoldersAndItems', 'ChoiceFoldersAndItems'), ('footerDataPath', 'FooterDataPath')):
|
||||
if el.get(key):
|
||||
lines.append(f'{inner}<{tag}>{esc_xml(str(el[key]))}</{tag}>')
|
||||
lines.append(f'{inner}<{tag}>{esc_xml_text(str(el[key]))}</{tag}>')
|
||||
# MinValue/MaxValue — типизированное. JSON-число → xs:decimal, строка → xs:string (тип сохранён декомпилятором).
|
||||
for key, tag in (('minValue', 'MinValue'), ('maxValue', 'MaxValue')):
|
||||
if el.get(key) is not None:
|
||||
mvt = 'xs:string' if isinstance(el[key], str) else 'xs:decimal'
|
||||
lines.append(f'{inner}<{tag} xsi:type="{mvt}">{esc_xml(str(el[key]))}</{tag}>')
|
||||
lines.append(f'{inner}<{tag} xsi:type="{mvt}">{esc_xml_text(str(el[key]))}</{tag}>')
|
||||
if el.get('choiceButtonRepresentation'):
|
||||
lines.append(f'{inner}<ChoiceButtonRepresentation>{el["choiceButtonRepresentation"]}</ChoiceButtonRepresentation>')
|
||||
emit_picture_ref(lines, el.get('choiceButtonPicture'), 'ChoiceButtonPicture', inner)
|
||||
@@ -4286,7 +4291,7 @@ def emit_check(lines, el, name, eid, indent):
|
||||
emit_mltext(lines, inner, 'WarningOnEdit', el['warningOnEdit'])
|
||||
# FooterDataPath / FooterText — общие cell-свойства колонки (как у input/labelField)
|
||||
if el.get('footerDataPath'):
|
||||
lines.append(f'{inner}<FooterDataPath>{esc_xml(str(el["footerDataPath"]))}</FooterDataPath>')
|
||||
lines.append(f'{inner}<FooterDataPath>{esc_xml_text(str(el["footerDataPath"]))}</FooterDataPath>')
|
||||
if el.get('footerText') is not None:
|
||||
emit_mltext(lines, inner, 'FooterText', el['footerText'])
|
||||
|
||||
@@ -4403,7 +4408,7 @@ def emit_label_field(lines, el, name, eid, indent):
|
||||
lines.append(f'{inner}<EditMode>{el["editMode"]}</EditMode>')
|
||||
# FooterDataPath — путь данных подвала колонки (общий cell-prop, как у input); после EditMode
|
||||
if el.get('footerDataPath'):
|
||||
lines.append(f'{inner}<FooterDataPath>{esc_xml(str(el["footerDataPath"]))}</FooterDataPath>')
|
||||
lines.append(f'{inner}<FooterDataPath>{esc_xml_text(str(el["footerDataPath"]))}</FooterDataPath>')
|
||||
# PasswordMode на LabelField — платформа эмитит явный false (редко); факт. значение
|
||||
if el.get('passwordMode') is not None:
|
||||
lines.append(f'{inner}<PasswordMode>{"true" if el["passwordMode"] else "false"}</PasswordMode>')
|
||||
@@ -4734,7 +4739,7 @@ def emit_button(lines, el, name, eid, indent, in_cmd_bar=False):
|
||||
if isinstance(btn_param, dict) and btn_param.get('type'):
|
||||
emit_type(lines, str(btn_param['type']), inner, tag='Parameter', tag_attrs=' xsi:type="v8:TypeDescription"')
|
||||
else:
|
||||
lines.append(f'{inner}<Parameter xsi:type="xr:MDObjectRef">{esc_xml(str(btn_param))}</Parameter>')
|
||||
lines.append(f'{inner}<Parameter xsi:type="xr:MDObjectRef">{esc_xml_text(str(btn_param))}</Parameter>')
|
||||
# DataPath — привязка команды кнопки к контексту (Объект.Ref, Items.X.CurrentData.Поле)
|
||||
if el.get('path'):
|
||||
lines.append(f'{inner}<DataPath>{el["path"]}</DataPath>')
|
||||
@@ -4787,9 +4792,9 @@ def emit_picture_decoration(lines, el, name, eid, indent):
|
||||
lt = 'true' if el.get('loadTransparent') is True else 'false'
|
||||
lines.append(f'{inner}<Picture>')
|
||||
if src_str.startswith('abs:'):
|
||||
lines.append(f'{inner}\t<xr:Abs>{esc_xml(src_str[4:])}</xr:Abs>')
|
||||
lines.append(f'{inner}\t<xr:Abs>{esc_xml_text(src_str[4:])}</xr:Abs>')
|
||||
else:
|
||||
lines.append(f'{inner}\t<xr:Ref>{esc_xml(src_str)}</xr:Ref>')
|
||||
lines.append(f'{inner}\t<xr:Ref>{esc_xml_text(src_str)}</xr:Ref>')
|
||||
lines.append(f'{inner}\t<xr:LoadTransparent>{lt}</xr:LoadTransparent>')
|
||||
tpx = el.get('transparentPixel')
|
||||
if tpx:
|
||||
@@ -4840,7 +4845,7 @@ def emit_picture_field(lines, el, name, eid, indent):
|
||||
|
||||
# FooterDataPath / FooterText — общие cell-свойства колонки (как у input/labelField)
|
||||
if el.get('footerDataPath'):
|
||||
lines.append(f'{inner}<FooterDataPath>{esc_xml(str(el["footerDataPath"]))}</FooterDataPath>')
|
||||
lines.append(f'{inner}<FooterDataPath>{esc_xml_text(str(el["footerDataPath"]))}</FooterDataPath>')
|
||||
if el.get('footerText') is not None:
|
||||
emit_mltext(lines, inner, 'FooterText', el['footerText'])
|
||||
|
||||
@@ -5198,30 +5203,30 @@ def emit_dl_value(lines, type_str, val, indent, value_list_allowed=False):
|
||||
val_str = str(val)
|
||||
t = type_str or ''
|
||||
if re.match(r'^(date|dateTime|time)', t):
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:dateTime">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:dateTime">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
elif t == 'boolean':
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:boolean">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:boolean">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
elif t == 'v8:Type':
|
||||
ns_attr = _value_type_ns_attr('v8:Type', val_str)
|
||||
lines.append(f'{indent}<dcssch:value{ns_attr} xsi:type="v8:Type">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value{ns_attr} xsi:type="v8:Type">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
elif re.match(r'^ent:', t):
|
||||
# системное перечисление (ent:X) — value несёт тот же xsi:type
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="{t}">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="{t}">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
elif re.match(r'^decimal', t):
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:decimal">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:decimal">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
elif re.match(r'^string', t):
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:string">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:string">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
elif re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|BusinessProcessRef|TaskRef|ExchangePlanRef)\.', t):
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="dcscor:DesignTimeValue">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="dcscor:DesignTimeValue">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
else:
|
||||
if re.match(r'^\d{4}-\d{2}-\d{2}T', val_str):
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:dateTime">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:dateTime">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
elif val_str in ('true', 'false'):
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:boolean">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:boolean">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
elif re.match(r'^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.', val_str) or re.match(r'^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.', val_str):
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="dcscor:DesignTimeValue">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="dcscor:DesignTimeValue">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
else:
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:string">{esc_xml(val_str)}</dcssch:value>')
|
||||
lines.append(f'{indent}<dcssch:value xsi:type="xs:string">{esc_xml_text(val_str)}</dcssch:value>')
|
||||
|
||||
|
||||
def emit_dl_value_type(lines, type_str, indent):
|
||||
@@ -5254,7 +5259,7 @@ def emit_dl_input_parameters(lines, ip, indent):
|
||||
lines.append(f'{indent}\t<dcscor:item>')
|
||||
if 'use' in item and item.get('use') is not None and not item.get('use'):
|
||||
lines.append(f'{indent}\t\t<dcscor:use>false</dcscor:use>')
|
||||
lines.append(f'{indent}\t\t<dcscor:parameter>{esc_xml(str(item.get("parameter", "")))}</dcscor:parameter>')
|
||||
lines.append(f'{indent}\t\t<dcscor:parameter>{esc_xml_text(str(item.get("parameter", "")))}</dcscor:parameter>')
|
||||
if 'choiceParameters' in item:
|
||||
cp_items = item.get('choiceParameters') or []
|
||||
if len(cp_items) == 0:
|
||||
@@ -5263,14 +5268,14 @@ def emit_dl_input_parameters(lines, ip, indent):
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:ChoiceParameters">')
|
||||
for cp in cp_items:
|
||||
lines.append(f'{indent}\t\t\t<dcscor:item>')
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:choiceParameter>{esc_xml(str(cp.get("name", "")))}</dcscor:choiceParameter>')
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:choiceParameter>{esc_xml_text(str(cp.get("name", "")))}</dcscor:choiceParameter>')
|
||||
for v in (cp.get('values') or []):
|
||||
if isinstance(v, bool):
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:value xsi:type="xs:boolean">{"true" if v else "false"}</dcscor:value>')
|
||||
elif isinstance(v, (int, float)):
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:value xsi:type="xs:decimal">{v}</dcscor:value>')
|
||||
else:
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:value xsi:type="dcscor:DesignTimeValue">{esc_xml(str(v))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:value xsi:type="dcscor:DesignTimeValue">{esc_xml_text(str(v))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t\t</dcscor:item>')
|
||||
lines.append(f'{indent}\t\t</dcscor:value>')
|
||||
elif 'choiceParameterLinks' in item:
|
||||
@@ -5281,8 +5286,8 @@ def emit_dl_input_parameters(lines, ip, indent):
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:ChoiceParameterLinks">')
|
||||
for cpl in cpl_items:
|
||||
lines.append(f'{indent}\t\t\t<dcscor:item>')
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:choiceParameter>{esc_xml(str(cpl.get("name", "")))}</dcscor:choiceParameter>')
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:value>{esc_xml(str(cpl.get("value", "")))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:choiceParameter>{esc_xml_text(str(cpl.get("name", "")))}</dcscor:choiceParameter>')
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:value>{esc_xml_text(str(cpl.get("value", "")))}</dcscor:value>')
|
||||
mode = str(cpl.get('mode') or 'Auto')
|
||||
lines.append(f'{indent}\t\t\t\t<dcscor:mode xmlns:d8p1="http://v8.1c.ru/8.1/data/enterprise" xsi:type="d8p1:LinkedValueChangeMode">{mode}</dcscor:mode>')
|
||||
lines.append(f'{indent}\t\t\t</dcscor:item>')
|
||||
@@ -5292,9 +5297,9 @@ def emit_dl_input_parameters(lines, ip, indent):
|
||||
tl = item.get('typeLink') or {}
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:TypeLink">')
|
||||
if tl.get('field') is not None:
|
||||
lines.append(f'{indent}\t\t\t<dcscor:field>{esc_xml(str(tl.get("field")))}</dcscor:field>')
|
||||
lines.append(f'{indent}\t\t\t<dcscor:field>{esc_xml_text(str(tl.get("field")))}</dcscor:field>')
|
||||
if tl.get('linkItem') is not None:
|
||||
lines.append(f'{indent}\t\t\t<dcscor:linkItem>{esc_xml(str(tl.get("linkItem")))}</dcscor:linkItem>')
|
||||
lines.append(f'{indent}\t\t\t<dcscor:linkItem>{esc_xml_text(str(tl.get("linkItem")))}</dcscor:linkItem>')
|
||||
lines.append(f'{indent}\t\t</dcscor:value>')
|
||||
elif 'value' in item:
|
||||
val = item.get('value')
|
||||
@@ -5305,7 +5310,7 @@ def emit_dl_input_parameters(lines, ip, indent):
|
||||
elif isinstance(val, dict):
|
||||
emit_dl_mltext(lines, f'{indent}\t\t', 'dcscor:value', val)
|
||||
else:
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml(str(val))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml_text(str(val))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t</dcscor:item>')
|
||||
lines.append(f'{indent}</dcssch:inputParameters>')
|
||||
|
||||
@@ -5394,7 +5399,7 @@ def emit_data_parameters(lines, items, indent, block_view_mode=None):
|
||||
lines.append(f'{indent}\t<dcscor:item xsi:type="dcsset:SettingsParameterValue">')
|
||||
if dp.get('use') is False:
|
||||
lines.append(f'{indent}\t\t<dcscor:use>false</dcscor:use>')
|
||||
lines.append(f'{indent}\t\t<dcscor:parameter>{esc_xml(str(dp.get("parameter", "")))}</dcscor:parameter>')
|
||||
lines.append(f'{indent}\t\t<dcscor:parameter>{esc_xml_text(str(dp.get("parameter", "")))}</dcscor:parameter>')
|
||||
vtype = str(dp.get('valueType') or '')
|
||||
val = dp.get('value')
|
||||
if isinstance(val, list):
|
||||
@@ -5403,11 +5408,11 @@ def emit_data_parameters(lines, items, indent, block_view_mode=None):
|
||||
for v in val:
|
||||
v_str = ('true' if v else 'false') if isinstance(v, bool) else str(v)
|
||||
if re.match(r'^[a-zA-Z]+:', avtype):
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="{avtype}">{esc_xml(v_str)}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="{avtype}">{esc_xml_text(v_str)}</dcscor:value>')
|
||||
elif re.match(r'^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.', v_str) or re.match(r'^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.', v_str):
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:DesignTimeValue">{esc_xml(v_str)}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:DesignTimeValue">{esc_xml_text(v_str)}</dcscor:value>')
|
||||
else:
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml(v_str)}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml_text(v_str)}</dcscor:value>')
|
||||
elif dp.get('nilValue') is True:
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:nil="true"/>')
|
||||
elif _test_empty_value(val) and vtype:
|
||||
@@ -5422,45 +5427,45 @@ def emit_data_parameters(lines, items, indent, block_view_mode=None):
|
||||
is_sbd = has_date or (not has_sd and variant.startswith('BeginningOf'))
|
||||
if is_sbd:
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="v8:StandardBeginningDate">')
|
||||
lines.append(f'{indent}\t\t\t<v8:variant xsi:type="v8:StandardBeginningDateVariant">{esc_xml(variant)}</v8:variant>')
|
||||
lines.append(f'{indent}\t\t\t<v8:variant xsi:type="v8:StandardBeginningDateVariant">{esc_xml_text(variant)}</v8:variant>')
|
||||
if variant == 'Custom':
|
||||
d = str(val.get('date') or '0001-01-01T00:00:00')
|
||||
lines.append(f'{indent}\t\t\t<v8:date>{esc_xml(d)}</v8:date>')
|
||||
lines.append(f'{indent}\t\t\t<v8:date>{esc_xml_text(d)}</v8:date>')
|
||||
lines.append(f'{indent}\t\t</dcscor:value>')
|
||||
else:
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="v8:StandardPeriod">')
|
||||
lines.append(f'{indent}\t\t\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml(variant)}</v8:variant>')
|
||||
lines.append(f'{indent}\t\t\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml_text(variant)}</v8:variant>')
|
||||
if variant == 'Custom':
|
||||
sd = str(val.get('startDate') or '0001-01-01T00:00:00')
|
||||
ed = str(val.get('endDate') or '0001-01-01T00:00:00')
|
||||
lines.append(f'{indent}\t\t\t<v8:startDate>{esc_xml(sd)}</v8:startDate>')
|
||||
lines.append(f'{indent}\t\t\t<v8:endDate>{esc_xml(ed)}</v8:endDate>')
|
||||
lines.append(f'{indent}\t\t\t<v8:startDate>{esc_xml_text(sd)}</v8:startDate>')
|
||||
lines.append(f'{indent}\t\t\t<v8:endDate>{esc_xml_text(ed)}</v8:endDate>')
|
||||
lines.append(f'{indent}\t\t</dcscor:value>')
|
||||
elif re.match(r'^[a-zA-Z]+:', vtype):
|
||||
v_str = str(val).lower() if isinstance(val, bool) else str(val)
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="{vtype}">{esc_xml(v_str)}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="{vtype}">{esc_xml_text(v_str)}</dcscor:value>')
|
||||
elif vtype == 'boolean' or isinstance(val, bool):
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:boolean">{esc_xml(str(val).lower())}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:boolean">{esc_xml_text(str(val).lower())}</dcscor:value>')
|
||||
elif re.match(r'^date', vtype) or re.match(r'^\d{4}-\d{2}-\d{2}T', str(val)):
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:dateTime">{esc_xml(str(val))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:dateTime">{esc_xml_text(str(val))}</dcscor:value>')
|
||||
elif re.match(r'^decimal', vtype):
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:decimal">{esc_xml(str(val))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:decimal">{esc_xml_text(str(val))}</dcscor:value>')
|
||||
elif re.match(r'^string', vtype):
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml(str(val))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml_text(str(val))}</dcscor:value>')
|
||||
elif re.match(r'^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.', str(val)) or re.match(r'^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.', str(val)):
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:DesignTimeValue">{esc_xml(str(val))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:DesignTimeValue">{esc_xml_text(str(val))}</dcscor:value>')
|
||||
else:
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml(str(val))}</dcscor:value>')
|
||||
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml_text(str(val))}</dcscor:value>')
|
||||
if dp.get('viewMode'):
|
||||
lines.append(f'{indent}\t\t<dcsset:viewMode>{esc_xml(str(dp["viewMode"]))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t\t<dcsset:viewMode>{esc_xml_text(str(dp["viewMode"]))}</dcsset:viewMode>')
|
||||
if dp.get('userSettingID'):
|
||||
uid = new_uuid() if str(dp['userSettingID']) == 'auto' else str(dp['userSettingID'])
|
||||
lines.append(f'{indent}\t\t<dcsset:userSettingID>{esc_xml(uid)}</dcsset:userSettingID>')
|
||||
lines.append(f'{indent}\t\t<dcsset:userSettingID>{esc_xml_text(uid)}</dcsset:userSettingID>')
|
||||
if dp.get('userSettingPresentation'):
|
||||
emit_us_presentation(lines, f'{indent}\t\t', 'dcsset:userSettingPresentation', dp['userSettingPresentation'])
|
||||
lines.append(f'{indent}\t</dcscor:item>')
|
||||
if block_view_mode is not None:
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml(str(block_view_mode))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}\t<dcsset:viewMode>{esc_xml_text(str(block_view_mode))}</dcsset:viewMode>')
|
||||
lines.append(f'{indent}</dcsset:dataParameters>')
|
||||
|
||||
|
||||
@@ -5468,7 +5473,7 @@ def emit_dl_parameter(lines, p, parsed, indent):
|
||||
is_obj = not isinstance(p, str)
|
||||
lines.append(f'{indent}<Parameter>')
|
||||
ci = f'{indent}\t'
|
||||
lines.append(f'{ci}<dcssch:name>{esc_xml(parsed["name"])}</dcssch:name>')
|
||||
lines.append(f'{ci}<dcssch:name>{esc_xml_text(parsed["name"])}</dcssch:name>')
|
||||
# Title: явный override (shorthand [..] / объект title/presentation) или авто из имени.
|
||||
title = None
|
||||
if parsed.get('title'):
|
||||
@@ -5508,7 +5513,7 @@ def emit_dl_parameter(lines, p, parsed, indent):
|
||||
# expression
|
||||
expr = str(p['expression']) if (is_obj and p.get('expression')) else None
|
||||
if expr:
|
||||
lines.append(f'{ci}<dcssch:expression>{esc_xml(expr)}</dcssch:expression>')
|
||||
lines.append(f'{ci}<dcssch:expression>{esc_xml_text(expr)}</dcssch:expression>')
|
||||
# availableValues
|
||||
if is_obj and p.get('availableValues'):
|
||||
for av in p['availableValues']:
|
||||
@@ -5532,7 +5537,7 @@ def emit_dl_parameter(lines, p, parsed, indent):
|
||||
lines.append(f'{ci}<dcssch:denyIncompleteValues>true</dcssch:denyIncompleteValues>')
|
||||
# use
|
||||
if is_obj and p.get('use'):
|
||||
lines.append(f'{ci}<dcssch:use>{esc_xml(str(p["use"]))}</dcssch:use>')
|
||||
lines.append(f'{ci}<dcssch:use>{esc_xml_text(str(p["use"]))}</dcssch:use>')
|
||||
lines.append(f'{indent}</Parameter>')
|
||||
|
||||
|
||||
@@ -5653,7 +5658,7 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None):
|
||||
if save_fields:
|
||||
lines.append(f'{inner}<Save>')
|
||||
for f in save_fields:
|
||||
lines.append(f'{inner}\t<Field>{esc_xml(f)}</Field>')
|
||||
lines.append(f'{inner}\t<Field>{esc_xml_text(f)}</Field>')
|
||||
lines.append(f'{inner}</Save>')
|
||||
# Проверка заполнения → <FillCheck> (реальный тег; <FillChecking> в схеме нет).
|
||||
# bool true → ShowError; строка → verbatim. Синоним fillChecking.
|
||||
@@ -5742,7 +5747,7 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None):
|
||||
lines.append(f'{si}<DynamicDataRead>{ddr}</DynamicDataRead>')
|
||||
if has_query:
|
||||
qtext = resolve_query_value(str(s['query']), QUERY_BASE_DIR)
|
||||
lines.append(f'{si}<QueryText>{esc_xml(qtext)}</QueryText>')
|
||||
lines.append(f'{si}<QueryText>{esc_xml_text(qtext)}</QueryText>')
|
||||
# Явные поля набора (редко): override title/dataPath
|
||||
if s.get('fields'):
|
||||
for fld in s['fields']:
|
||||
@@ -5762,9 +5767,9 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None):
|
||||
if dp == '':
|
||||
lines.append(f'{si}\t<dcssch:dataPath/>')
|
||||
else:
|
||||
lines.append(f'{si}\t<dcssch:dataPath>{esc_xml(dp)}</dcssch:dataPath>')
|
||||
lines.append(f'{si}\t<dcssch:dataPath>{esc_xml_text(dp)}</dcssch:dataPath>')
|
||||
if not is_folder:
|
||||
lines.append(f'{si}\t<dcssch:field>{esc_xml(str(fld.get("field", "")))}</dcssch:field>')
|
||||
lines.append(f'{si}\t<dcssch:field>{esc_xml_text(str(fld.get("field", "")))}</dcssch:field>')
|
||||
if fld.get('title'):
|
||||
lines.append(f'{si}\t<dcssch:title xsi:type="v8:LocalStringType">')
|
||||
emit_ml_items(lines, f'{si}\t\t', fld['title'])
|
||||
@@ -5774,7 +5779,7 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None):
|
||||
emit_restrict_block(lines, 'attributeUseRestriction', fld.get('attributeUseRestriction'), f'{si}\t')
|
||||
# presentationExpression поля — перед valueType (порядок исходника)
|
||||
if fld.get('presentationExpression'):
|
||||
lines.append(f'{si}\t<dcssch:presentationExpression>{esc_xml(str(fld["presentationExpression"]))}</dcssch:presentationExpression>')
|
||||
lines.append(f'{si}\t<dcssch:presentationExpression>{esc_xml_text(str(fld["presentationExpression"]))}</dcssch:presentationExpression>')
|
||||
# valueType поля набора (тип значения; вычисляемые/кастомные поля)
|
||||
if fld.get('valueType'):
|
||||
emit_dl_value_type(lines, fld['valueType'], f'{si}\t')
|
||||
@@ -5795,10 +5800,10 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None):
|
||||
# Ключ набора (query-based список без MainTable): KeyType (RowNumber/FieldValue/RowKey)
|
||||
# + KeyField* — после Parameter*, до MainTable. Захват/эмит факт. значений.
|
||||
if s.get('keyType'):
|
||||
lines.append(f'{si}<KeyType>{esc_xml(str(s["keyType"]))}</KeyType>')
|
||||
lines.append(f'{si}<KeyType>{esc_xml_text(str(s["keyType"]))}</KeyType>')
|
||||
if s.get('keyFields'):
|
||||
for kf in s['keyFields']:
|
||||
lines.append(f'{si}<KeyField>{esc_xml(str(kf))}</KeyField>')
|
||||
lines.append(f'{si}<KeyField>{esc_xml_text(str(kf))}</KeyField>')
|
||||
if s.get('mainTable'):
|
||||
lines.append(f'{si}<MainTable>{normalize_meta_type_ref(str(s["mainTable"]))}</MainTable>')
|
||||
# GetInvisibleFieldPresentations — после MainTable (дефолт true; эмитим только при заданном ключе = отклонении false).
|
||||
@@ -5937,7 +5942,7 @@ def emit_commands(lines, cmds, indent):
|
||||
cmd_table = (_cmd_norm.get('table') or _cmd_norm.get('associatedtableelementid')
|
||||
or _cmd_norm.get('используемаятаблица'))
|
||||
if cmd_table:
|
||||
lines.append(f'{inner}<AssociatedTableElementId xsi:type="xs:string">{esc_xml(str(cmd_table))}</AssociatedTableElementId>')
|
||||
lines.append(f'{inner}<AssociatedTableElementId xsi:type="xs:string">{esc_xml_text(str(cmd_table))}</AssociatedTableElementId>')
|
||||
|
||||
if cmd.get('shortcut'):
|
||||
lines.append(f'{inner}<Shortcut>{cmd["shortcut"]}</Shortcut>')
|
||||
@@ -6014,12 +6019,12 @@ def emit_command_interface(lines, ci, indent):
|
||||
if tree_group:
|
||||
grp = tree_group
|
||||
lines.append(f'{inner}\t<Item>')
|
||||
lines.append(f'{inner}\t\t<Command>{esc_xml(str(cmd))}</Command>')
|
||||
lines.append(f'{inner}\t\t<Command>{esc_xml_text(str(cmd))}</Command>')
|
||||
lines.append(f'{inner}\t\t<Type>{typ}</Type>')
|
||||
if attr:
|
||||
lines.append(f'{inner}\t\t<Attribute>{esc_xml(str(attr))}</Attribute>')
|
||||
lines.append(f'{inner}\t\t<Attribute>{esc_xml_text(str(attr))}</Attribute>')
|
||||
if grp:
|
||||
lines.append(f'{inner}\t\t<CommandGroup>{esc_xml(str(grp))}</CommandGroup>')
|
||||
lines.append(f'{inner}\t\t<CommandGroup>{esc_xml_text(str(grp))}</CommandGroup>')
|
||||
if idx is not None:
|
||||
lines.append(f'{inner}\t\t<Index>{idx}</Index>')
|
||||
if dv is not None:
|
||||
@@ -6573,7 +6578,7 @@ def main():
|
||||
if not str(nm):
|
||||
lines.append('\t\t\t<xr:Value xsi:type="xs:string"/>')
|
||||
else:
|
||||
lines.append(f'\t\t\t<xr:Value xsi:type="xs:string">{esc_xml(str(nm))}</xr:Value>')
|
||||
lines.append(f'\t\t\t<xr:Value xsi:type="xs:string">{esc_xml_text(str(nm))}</xr:Value>')
|
||||
lines.append('\t\t</xr:Item>')
|
||||
lines.append('\t</MobileDeviceCommandBarContent>')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# form-edit v1.11 — Edit 1C managed form elements (+resolve_type_str: срезание префикса cfg:/d5p1:)
|
||||
# form-edit v1.12 — Edit 1C managed form elements (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -270,6 +270,12 @@ function X {
|
||||
}
|
||||
|
||||
function Esc-Xml {
|
||||
param([string]$s)
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>').Replace('"','"')
|
||||
}
|
||||
|
||||
function Esc-XmlText {
|
||||
# Экранирование ТЕКСТА элемента: только & < > . Кавычки в тексте платформа НЕ экранирует —
|
||||
# пишет литерально (проверено: 92142 сырых кавычки на корпус, ни одной "). " платформа
|
||||
# принимает, но при выгрузке нормализует обратно в кавычку → лишний шум в роундтрипе.
|
||||
@@ -282,7 +288,7 @@ function Emit-MLText {
|
||||
X "$indent<$tag>"
|
||||
X "$indent`t<v8:item>"
|
||||
X "$indent`t`t<v8:lang>ru</v8:lang>"
|
||||
X "$indent`t`t<v8:content>$(Esc-Xml $text)</v8:content>"
|
||||
X "$indent`t`t<v8:content>$(Esc-XmlText $text)</v8:content>"
|
||||
X "$indent`t</v8:item>"
|
||||
X "$indent</$tag>"
|
||||
}
|
||||
@@ -617,7 +623,7 @@ function Emit-Label {
|
||||
X "$inner<Title formatted=`"$formatted`">"
|
||||
X "$inner`t<v8:item>"
|
||||
X "$inner`t`t<v8:lang>ru</v8:lang>"
|
||||
X "$inner`t`t<v8:content>$(Esc-Xml "$($el.title)")</v8:content>"
|
||||
X "$inner`t`t<v8:content>$(Esc-XmlText "$($el.title)")</v8:content>"
|
||||
X "$inner`t</v8:item>"
|
||||
X "$inner</Title>"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# form-edit v1.11 — Edit 1C managed form elements (Python port) (+resolve_type_str: срезание префикса cfg:/d5p1:)
|
||||
# form-edit v1.12 — Edit 1C managed form elements (Python port) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import json
|
||||
@@ -226,6 +226,11 @@ def local_name(node):
|
||||
# ── helpers ──────────────────────────────────────────────────
|
||||
|
||||
def esc_xml(s):
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
def esc_xml_text(s):
|
||||
"""Экранирование ТЕКСТА элемента: только & < > . Кавычки платформа в тексте не экранирует
|
||||
(92142 сырых кавычки на корпус, ни одной "); " она принимает, но нормализует обратно."""
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
@@ -521,7 +526,7 @@ def emit_mltext(tag, text, indent):
|
||||
X(f"{indent}<{tag}>")
|
||||
X(f"{indent}\t<v8:item>")
|
||||
X(f"{indent}\t\t<v8:lang>ru</v8:lang>")
|
||||
X(f"{indent}\t\t<v8:content>{esc_xml(text)}</v8:content>")
|
||||
X(f"{indent}\t\t<v8:content>{esc_xml_text(text)}</v8:content>")
|
||||
X(f"{indent}\t</v8:item>")
|
||||
X(f"{indent}</{tag}>")
|
||||
|
||||
@@ -749,7 +754,7 @@ def emit_label(el, name, _id, indent):
|
||||
X(f'{inner}<Title formatted="{formatted}">')
|
||||
X(f"{inner}\t<v8:item>")
|
||||
X(f"{inner}\t\t<v8:lang>ru</v8:lang>")
|
||||
X(f"{inner}\t\t<v8:content>{esc_xml(str(el['title']))}</v8:content>")
|
||||
X(f"{inner}\t\t<v8:content>{esc_xml_text(str(el['title']))}</v8:content>")
|
||||
X(f"{inner}\t</v8:item>")
|
||||
X(f"{inner}</Title>")
|
||||
emit_common_flags(el, inner)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-edit v1.34 — Edit existing 1C metadata object XML (+resolve_type_str: срезание префикса cfg:/d5p1:)
|
||||
# meta-edit v1.35 — Edit existing 1C metadata object XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[string]$DefinitionFile,
|
||||
@@ -2854,7 +2854,11 @@ function Build-ChoiceParametersXml([string]$indent, $cp) {
|
||||
$script:fillBoolTrue = @('true','истина','да')
|
||||
$script:fillBoolFalse = @('false','ложь','нет')
|
||||
|
||||
function Esc-XmlText([string]$s) { return $s.Replace('&','&').Replace('<','<').Replace('>','>') }
|
||||
function Esc-XmlText {
|
||||
param([string]$s)
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>')
|
||||
}
|
||||
|
||||
function Get-FillTypeCategory([string]$typeStr) {
|
||||
if (-not $typeStr) { return 'String' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-edit v1.34 — Edit existing 1C metadata object XML (+resolve_type_str: срезание префикса cfg:/d5p1:)
|
||||
# meta-edit v1.35 — Edit existing 1C metadata object XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -258,7 +258,8 @@ def localname(el):
|
||||
|
||||
|
||||
def esc_xml(s):
|
||||
return s.replace("&", "&").replace("<", "<").replace(">", ">").replace('"', """)
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-compile v1.10 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.11 — Compile 1C spreadsheet from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -477,6 +477,12 @@ foreach ($col in ($colWidthMap.Keys | Sort-Object)) {
|
||||
|
||||
# Helper: escape XML special characters
|
||||
function Esc-Xml {
|
||||
param([string]$s)
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>').Replace('"','"')
|
||||
}
|
||||
|
||||
function Esc-XmlText {
|
||||
# Экранирование ТЕКСТА элемента: только & < > . Кавычки в тексте платформа НЕ экранирует —
|
||||
# пишет литерально (проверено: 92142 сырых кавычки на корпус, ни одной "). " платформа
|
||||
# принимает, но при выгрузке нормализует обратно в кавычку → лишний шум в роундтрипе.
|
||||
@@ -760,7 +766,7 @@ foreach ($area in $def.areas) {
|
||||
X "`t`t`t`t`t<tl>"
|
||||
X "`t`t`t`t`t`t<v8:item>"
|
||||
X "`t`t`t`t`t`t`t<v8:lang>ru</v8:lang>"
|
||||
X "`t`t`t`t`t`t`t<v8:content>$(Esc-Xml $cellInfo.Text)</v8:content>"
|
||||
X "`t`t`t`t`t`t`t<v8:content>$(Esc-XmlText $cellInfo.Text)</v8:content>"
|
||||
X "`t`t`t`t`t`t</v8:item>"
|
||||
X "`t`t`t`t`t</tl>"
|
||||
}
|
||||
@@ -769,7 +775,7 @@ foreach ($area in $def.areas) {
|
||||
X "`t`t`t`t`t<tl>"
|
||||
X "`t`t`t`t`t`t<v8:item>"
|
||||
X "`t`t`t`t`t`t`t<v8:lang>ru</v8:lang>"
|
||||
X "`t`t`t`t`t`t`t<v8:content>$(Esc-Xml $cellInfo.Template)</v8:content>"
|
||||
X "`t`t`t`t`t`t`t<v8:content>$(Esc-XmlText $cellInfo.Template)</v8:content>"
|
||||
X "`t`t`t`t`t`t</v8:item>"
|
||||
X "`t`t`t`t`t</tl>"
|
||||
}
|
||||
@@ -885,7 +891,7 @@ foreach ($key in $formatRegistry.Keys) {
|
||||
X "`t`t<format>"
|
||||
X "`t`t`t<v8:item>"
|
||||
X "`t`t`t`t<v8:lang>ru</v8:lang>"
|
||||
X "`t`t`t`t<v8:content>$(Esc-Xml $fmt.NumberFormat)</v8:content>"
|
||||
X "`t`t`t`t<v8:content>$(Esc-XmlText $fmt.NumberFormat)</v8:content>"
|
||||
X "`t`t`t</v8:item>"
|
||||
X "`t`t</format>"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-compile v1.10 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.11 — Compile 1C spreadsheet from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import json
|
||||
@@ -188,6 +188,11 @@ def assert_edit_allowed(target_path, require):
|
||||
|
||||
|
||||
def esc_xml(s):
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
def esc_xml_text(s):
|
||||
"""Экранирование ТЕКСТА элемента: только & < > . Кавычки платформа в тексте не экранирует
|
||||
(92142 сырых кавычки на корпус, ни одной "); " она принимает, но нормализует обратно."""
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
@@ -725,7 +730,7 @@ def main():
|
||||
lines.append('\t\t\t\t\t<tl>')
|
||||
lines.append('\t\t\t\t\t\t<v8:item>')
|
||||
lines.append('\t\t\t\t\t\t\t<v8:lang>ru</v8:lang>')
|
||||
lines.append(f'\t\t\t\t\t\t\t<v8:content>{esc_xml(cell_info["Text"])}</v8:content>')
|
||||
lines.append(f'\t\t\t\t\t\t\t<v8:content>{esc_xml_text(cell_info["Text"])}</v8:content>')
|
||||
lines.append('\t\t\t\t\t\t</v8:item>')
|
||||
lines.append('\t\t\t\t\t</tl>')
|
||||
|
||||
@@ -733,7 +738,7 @@ def main():
|
||||
lines.append('\t\t\t\t\t<tl>')
|
||||
lines.append('\t\t\t\t\t\t<v8:item>')
|
||||
lines.append('\t\t\t\t\t\t\t<v8:lang>ru</v8:lang>')
|
||||
lines.append(f'\t\t\t\t\t\t\t<v8:content>{esc_xml(cell_info["Template"])}</v8:content>')
|
||||
lines.append(f'\t\t\t\t\t\t\t<v8:content>{esc_xml_text(cell_info["Template"])}</v8:content>')
|
||||
lines.append('\t\t\t\t\t\t</v8:item>')
|
||||
lines.append('\t\t\t\t\t</tl>')
|
||||
|
||||
@@ -829,7 +834,7 @@ def main():
|
||||
lines.append('\t\t<format>')
|
||||
lines.append('\t\t\t<v8:item>')
|
||||
lines.append('\t\t\t\t<v8:lang>ru</v8:lang>')
|
||||
lines.append(f'\t\t\t\t<v8:content>{esc_xml(fmt["NumberFormat"])}</v8:content>')
|
||||
lines.append(f'\t\t\t\t<v8:content>{esc_xml_text(fmt["NumberFormat"])}</v8:content>')
|
||||
lines.append('\t\t\t</v8:item>')
|
||||
lines.append('\t\t</format>')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# role-compile v1.19 — Compile 1C role from JSON (+detect_format_version: ветка автономной EPF/ERF)
|
||||
# role-compile v1.20 — Compile 1C role from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -171,6 +171,12 @@ function X {
|
||||
}
|
||||
|
||||
function Esc-Xml {
|
||||
param([string]$s)
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>').Replace('"','"')
|
||||
}
|
||||
|
||||
function Esc-XmlText {
|
||||
# Экранирование ТЕКСТА элемента: только & < > . Кавычки в тексте платформа НЕ экранирует —
|
||||
# пишет литерально (проверено: 92142 сырых кавычки на корпус, ни одной "). " платформа
|
||||
# принимает, но при выгрузке нормализует обратно в кавычку → лишний шум в роундтрипе.
|
||||
@@ -701,11 +707,11 @@ X "`t`t`t<Name>$roleName</Name>"
|
||||
X "`t`t`t<Synonym>"
|
||||
X "`t`t`t`t<v8:item>"
|
||||
X "`t`t`t`t`t<v8:lang>ru</v8:lang>"
|
||||
X "`t`t`t`t`t<v8:content>$(Esc-Xml $synonym)</v8:content>"
|
||||
X "`t`t`t`t`t<v8:content>$(Esc-XmlText $synonym)</v8:content>"
|
||||
X "`t`t`t`t</v8:item>"
|
||||
X "`t`t`t</Synonym>"
|
||||
if ($comment) {
|
||||
X "`t`t`t<Comment>$(Esc-Xml $comment)</Comment>"
|
||||
X "`t`t`t<Comment>$(Esc-XmlText $comment)</Comment>"
|
||||
} else {
|
||||
X "`t`t`t<Comment/>"
|
||||
}
|
||||
@@ -742,7 +748,7 @@ foreach ($obj in $parsedObjects) {
|
||||
X "`t`t`t<value>$($right.Value)</value>"
|
||||
if ($right.Condition) {
|
||||
X "`t`t`t<restrictionByCondition>"
|
||||
X "`t`t`t`t<condition>$(Esc-Xml $right.Condition)</condition>"
|
||||
X "`t`t`t`t<condition>$(Esc-XmlText $right.Condition)</condition>"
|
||||
X "`t`t`t</restrictionByCondition>"
|
||||
}
|
||||
X "`t`t</right>"
|
||||
@@ -756,8 +762,8 @@ $templateCount = 0
|
||||
if ($def.templates) {
|
||||
foreach ($tpl in $def.templates) {
|
||||
X "`t<restrictionTemplate>"
|
||||
X "`t`t<name>$(Esc-Xml "$($tpl.name)")</name>"
|
||||
X "`t`t<condition>$(Esc-Xml "$($tpl.condition)")</condition>"
|
||||
X "`t`t<name>$(Esc-XmlText "$($tpl.name)")</name>"
|
||||
X "`t`t<condition>$(Esc-XmlText "$($tpl.condition)")</condition>"
|
||||
X "`t</restrictionTemplate>"
|
||||
$templateCount++
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# role-compile v1.19 — Compile 1C role from JSON (+detect_format_version: ветка автономной EPF/ERF)
|
||||
# role-compile v1.20 — Compile 1C role from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import json
|
||||
@@ -228,6 +228,11 @@ def detect_eol(text):
|
||||
return '\r\n' if '\r\n' in text else '\n'
|
||||
|
||||
def esc_xml(s):
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
def esc_xml_text(s):
|
||||
"""Экранирование ТЕКСТА элемента: только & < > . Кавычки платформа в тексте не экранирует
|
||||
(92142 сырых кавычки на корпус, ни одной "); " она принимает, но нормализует обратно."""
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
@@ -240,7 +245,7 @@ def emit_mltext(lines, indent, tag, text):
|
||||
lines.append(f"{indent}<{tag}>")
|
||||
lines.append(f"{indent}\t<v8:item>")
|
||||
lines.append(f"{indent}\t\t<v8:lang>ru</v8:lang>")
|
||||
lines.append(f"{indent}\t\t<v8:content>{esc_xml(text)}</v8:content>")
|
||||
lines.append(f"{indent}\t\t<v8:content>{esc_xml_text(text)}</v8:content>")
|
||||
lines.append(f"{indent}\t</v8:item>")
|
||||
lines.append(f"{indent}</{tag}>")
|
||||
|
||||
@@ -712,11 +717,11 @@ def main():
|
||||
lines.append('\t\t\t<Synonym>')
|
||||
lines.append('\t\t\t\t<v8:item>')
|
||||
lines.append('\t\t\t\t\t<v8:lang>ru</v8:lang>')
|
||||
lines.append(f'\t\t\t\t\t<v8:content>{esc_xml(synonym)}</v8:content>')
|
||||
lines.append(f'\t\t\t\t\t<v8:content>{esc_xml_text(synonym)}</v8:content>')
|
||||
lines.append('\t\t\t\t</v8:item>')
|
||||
lines.append('\t\t\t</Synonym>')
|
||||
if comment:
|
||||
lines.append(f'\t\t\t<Comment>{esc_xml(comment)}</Comment>')
|
||||
lines.append(f'\t\t\t<Comment>{esc_xml_text(comment)}</Comment>')
|
||||
else:
|
||||
lines.append('\t\t\t<Comment/>')
|
||||
lines.append('\t\t</Properties>')
|
||||
@@ -752,7 +757,7 @@ def main():
|
||||
lines.append(f'\t\t\t<value>{right["Value"]}</value>')
|
||||
if right['Condition']:
|
||||
lines.append('\t\t\t<restrictionByCondition>')
|
||||
lines.append(f'\t\t\t\t<condition>{esc_xml(right["Condition"])}</condition>')
|
||||
lines.append(f'\t\t\t\t<condition>{esc_xml_text(right["Condition"])}</condition>')
|
||||
lines.append('\t\t\t</restrictionByCondition>')
|
||||
lines.append('\t\t</right>')
|
||||
total_rights += 1
|
||||
@@ -763,8 +768,8 @@ def main():
|
||||
if defn.get('templates'):
|
||||
for tpl in defn['templates']:
|
||||
lines.append('\t<restrictionTemplate>')
|
||||
lines.append(f'\t\t<name>{esc_xml(str(tpl["name"]))}</name>')
|
||||
lines.append(f'\t\t<condition>{esc_xml(str(tpl["condition"]))}</condition>')
|
||||
lines.append(f'\t\t<name>{esc_xml_text(str(tpl["name"]))}</name>')
|
||||
lines.append(f'\t\t<condition>{esc_xml_text(str(tpl["condition"]))}</condition>')
|
||||
lines.append('\t</restrictionTemplate>')
|
||||
template_count += 1
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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>")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# subsystem-compile v1.20 — Create 1C subsystem from JSON definition (+detect_format_version: ветка автономной EPF/ERF)
|
||||
# subsystem-compile v1.21 — Create 1C subsystem from JSON definition (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[string]$DefinitionFile,
|
||||
@@ -188,9 +188,15 @@ function X([string]$text) {
|
||||
$script:xml.AppendLine($text) | Out-Null
|
||||
}
|
||||
|
||||
function Esc-Xml([string]$s) {
|
||||
# Экранирование ТЕКСТА элемента: только & < > . Кавычки в тексте платформа НЕ экранирует —
|
||||
# пишет литерально (92142 сырых кавычки на корпус, ни одной ").
|
||||
function Esc-Xml {
|
||||
param([string]$s)
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>').Replace('"','"')
|
||||
}
|
||||
|
||||
function Esc-XmlText {
|
||||
param([string]$s)
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>')
|
||||
}
|
||||
|
||||
@@ -211,7 +217,7 @@ function Emit-MLText([string]$indent, [string]$tag, [string]$text) {
|
||||
X "$indent<$tag>"
|
||||
X "$indent`t<v8:item>"
|
||||
X "$indent`t`t<v8:lang>ru</v8:lang>"
|
||||
X "$indent`t`t<v8:content>$(Esc-Xml $text)</v8:content>"
|
||||
X "$indent`t`t<v8:content>$(Esc-XmlText $text)</v8:content>"
|
||||
X "$indent`t</v8:item>"
|
||||
X "$indent</$tag>"
|
||||
}
|
||||
@@ -227,7 +233,7 @@ function Write-ChildSubsystemStub([string]$childPath, [string]$childName, [strin
|
||||
[void]$sb.AppendLine("<MetaDataObject $($script:xmlnsDecl) version=`"$formatVersion`">")
|
||||
[void]$sb.AppendLine("`t<Subsystem uuid=`"$childUuid`">")
|
||||
[void]$sb.AppendLine("`t`t<Properties>")
|
||||
[void]$sb.AppendLine("`t`t`t<Name>$(Esc-Xml $childName)</Name>")
|
||||
[void]$sb.AppendLine("`t`t`t<Name>$(Esc-XmlText $childName)</Name>")
|
||||
[void]$sb.AppendLine("`t`t`t<Synonym/>")
|
||||
[void]$sb.AppendLine("`t`t`t<Comment/>")
|
||||
[void]$sb.AppendLine("`t`t`t<IncludeHelpInContents>true</IncludeHelpInContents>")
|
||||
@@ -483,14 +489,14 @@ X "`t<Subsystem uuid=`"$uuid`">"
|
||||
X "`t`t<Properties>"
|
||||
|
||||
# Name
|
||||
X "`t`t`t<Name>$(Esc-Xml $objName)</Name>"
|
||||
X "`t`t`t<Name>$(Esc-XmlText $objName)</Name>"
|
||||
|
||||
# Synonym
|
||||
Emit-MLText "`t`t`t" "Synonym" $synonym
|
||||
|
||||
# Comment
|
||||
if ($comment) {
|
||||
X "`t`t`t<Comment>$(Esc-Xml $comment)</Comment>"
|
||||
X "`t`t`t<Comment>$(Esc-XmlText $comment)</Comment>"
|
||||
} else {
|
||||
X "`t`t`t<Comment/>"
|
||||
}
|
||||
@@ -517,7 +523,7 @@ if ($picture) {
|
||||
if ($contentItems.Count -gt 0) {
|
||||
X "`t`t`t<Content>"
|
||||
foreach ($item in $contentItems) {
|
||||
X "`t`t`t`t<xr:Item xsi:type=`"xr:MDObjectRef`">$(Esc-Xml $item)</xr:Item>"
|
||||
X "`t`t`t`t<xr:Item xsi:type=`"xr:MDObjectRef`">$(Esc-XmlText $item)</xr:Item>"
|
||||
}
|
||||
X "`t`t`t</Content>"
|
||||
} else {
|
||||
@@ -530,7 +536,7 @@ X "`t`t</Properties>"
|
||||
if ($children.Count -gt 0) {
|
||||
X "`t`t<ChildObjects>"
|
||||
foreach ($ch in $children) {
|
||||
X "`t`t`t<Subsystem>$(Esc-Xml $ch)</Subsystem>"
|
||||
X "`t`t`t<Subsystem>$(Esc-XmlText $ch)</Subsystem>"
|
||||
}
|
||||
X "`t`t</ChildObjects>"
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# subsystem-compile v1.20 — Create 1C subsystem from JSON definition (+detect_format_version: ветка автономной EPF/ERF)
|
||||
# subsystem-compile v1.21 — Create 1C subsystem from JSON definition (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import json
|
||||
@@ -229,6 +229,11 @@ def detect_eol(text):
|
||||
return '\r\n' if '\r\n' in text else '\n'
|
||||
|
||||
def esc_xml(s):
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
def esc_xml_text(s):
|
||||
"""Экранирование ТЕКСТА элемента: только & < > . Кавычки платформа в тексте не экранирует
|
||||
(92142 сырых кавычки на корпус, ни одной "); " она принимает, но нормализует обратно."""
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
@@ -241,7 +246,7 @@ def emit_mltext(lines, indent, tag, text):
|
||||
lines.append(f"{indent}<{tag}>")
|
||||
lines.append(f"{indent}\t<v8:item>")
|
||||
lines.append(f"{indent}\t\t<v8:lang>ru</v8:lang>")
|
||||
lines.append(f"{indent}\t\t<v8:content>{esc_xml(text)}</v8:content>")
|
||||
lines.append(f"{indent}\t\t<v8:content>{esc_xml_text(text)}</v8:content>")
|
||||
lines.append(f"{indent}\t</v8:item>")
|
||||
lines.append(f"{indent}</{tag}>")
|
||||
|
||||
@@ -305,7 +310,7 @@ def write_child_subsystem_stub(child_path, child_name, format_version):
|
||||
lines.append(f'<MetaDataObject {XMLNS_DECL} version="{format_version}">')
|
||||
lines.append(f'\t<Subsystem uuid="{child_uuid}">')
|
||||
lines.append('\t\t<Properties>')
|
||||
lines.append(f'\t\t\t<Name>{esc_xml(child_name)}</Name>')
|
||||
lines.append(f'\t\t\t<Name>{esc_xml_text(child_name)}</Name>')
|
||||
lines.append('\t\t\t<Synonym/>')
|
||||
lines.append('\t\t\t<Comment/>')
|
||||
lines.append('\t\t\t<IncludeHelpInContents>true</IncludeHelpInContents>')
|
||||
@@ -493,14 +498,14 @@ def main():
|
||||
lines.append('\t\t<Properties>')
|
||||
|
||||
# Name
|
||||
lines.append(f'\t\t\t<Name>{esc_xml(obj_name)}</Name>')
|
||||
lines.append(f'\t\t\t<Name>{esc_xml_text(obj_name)}</Name>')
|
||||
|
||||
# Synonym
|
||||
emit_mltext(lines, '\t\t\t', 'Synonym', synonym)
|
||||
|
||||
# Comment
|
||||
if comment:
|
||||
lines.append(f'\t\t\t<Comment>{esc_xml(comment)}</Comment>')
|
||||
lines.append(f'\t\t\t<Comment>{esc_xml_text(comment)}</Comment>')
|
||||
else:
|
||||
lines.append('\t\t\t<Comment/>')
|
||||
|
||||
@@ -525,7 +530,7 @@ def main():
|
||||
if len(content_items) > 0:
|
||||
lines.append('\t\t\t<Content>')
|
||||
for item in content_items:
|
||||
lines.append(f'\t\t\t\t<xr:Item xsi:type="xr:MDObjectRef">{esc_xml(item)}</xr:Item>')
|
||||
lines.append(f'\t\t\t\t<xr:Item xsi:type="xr:MDObjectRef">{esc_xml_text(item)}</xr:Item>')
|
||||
lines.append('\t\t\t</Content>')
|
||||
else:
|
||||
lines.append('\t\t\t<Content/>')
|
||||
@@ -536,7 +541,7 @@ def main():
|
||||
if len(children) > 0:
|
||||
lines.append('\t\t<ChildObjects>')
|
||||
for ch in children:
|
||||
lines.append(f'\t\t\t<Subsystem>{esc_xml(ch)}</Subsystem>')
|
||||
lines.append(f'\t\t\t<Subsystem>{esc_xml_text(ch)}</Subsystem>')
|
||||
lines.append('\t\t</ChildObjects>')
|
||||
else:
|
||||
lines.append('\t\t<ChildObjects/>')
|
||||
@@ -637,14 +642,14 @@ def main():
|
||||
if not already_exists:
|
||||
# Use raw text manipulation to preserve formatting
|
||||
if '<ChildObjects/>' in raw_text:
|
||||
replacement = ('<ChildObjects>' + eol + f'\t\t\t<Subsystem>{esc_xml(obj_name)}</Subsystem>' + eol + '\t\t</ChildObjects>')
|
||||
replacement = ('<ChildObjects>' + eol + f'\t\t\t<Subsystem>{esc_xml_text(obj_name)}</Subsystem>' + eol + '\t\t</ChildObjects>')
|
||||
raw_text = raw_text.replace('<ChildObjects/>', replacement, 1)
|
||||
elif '</ChildObjects>' in raw_text:
|
||||
# Отступ вставки берём у закрывающего тега +1 уровень: подстановка
|
||||
# по голому '</ChildObjects>' удваивала бы уже присутствующий отступ
|
||||
# строки (получалось 5 табов вместо 3 — PS-порт через DOM даёт 3).
|
||||
raw_text = re.sub(r'([ \t]*)</ChildObjects>',
|
||||
lambda m: m.group(1) + '\t' + f'<Subsystem>{esc_xml(obj_name)}</Subsystem>' + eol + m.group(1) + '</ChildObjects>',
|
||||
lambda m: m.group(1) + '\t' + f'<Subsystem>{esc_xml_text(obj_name)}</Subsystem>' + eol + m.group(1) + '</ChildObjects>',
|
||||
raw_text, count=1)
|
||||
|
||||
write_utf8_bom(parent_xml_path, raw_text)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# subsystem-edit v1.15 — Edit existing 1C subsystem XML
|
||||
# subsystem-edit v1.16 — Edit existing 1C subsystem XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)][Alias('Path')][string]$SubsystemPath,
|
||||
@@ -320,9 +320,15 @@ foreach ($child in $script:propsEl.ChildNodes) {
|
||||
Info "Subsystem: $($script:objName)"
|
||||
|
||||
# --- XML manipulation helpers (from meta-edit pattern) ---
|
||||
function Esc-Xml([string]$s) {
|
||||
# Экранирование ТЕКСТА элемента: только & < > . Кавычки в тексте платформа НЕ экранирует —
|
||||
# пишет литерально (92142 сырых кавычки на корпус, ни одной ").
|
||||
function Esc-Xml {
|
||||
param([string]$s)
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>').Replace('"','"')
|
||||
}
|
||||
|
||||
function Esc-XmlText {
|
||||
param([string]$s)
|
||||
# Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми.
|
||||
return $s.Replace('&','&').Replace('<','<').Replace('>','>')
|
||||
}
|
||||
|
||||
@@ -337,7 +343,7 @@ function Write-ChildSubsystemStub([string]$childPath, [string]$childName, [strin
|
||||
[void]$sb.AppendLine("<MetaDataObject $($script:xmlnsDecl) version=`"$formatVersion`">")
|
||||
[void]$sb.AppendLine("`t<Subsystem uuid=`"$childUuid`">")
|
||||
[void]$sb.AppendLine("`t`t<Properties>")
|
||||
[void]$sb.AppendLine("`t`t`t<Name>$(Esc-Xml $childName)</Name>")
|
||||
[void]$sb.AppendLine("`t`t`t<Name>$(Esc-XmlText $childName)</Name>")
|
||||
[void]$sb.AppendLine("`t`t`t<Synonym/>")
|
||||
[void]$sb.AppendLine("`t`t`t<Comment/>")
|
||||
[void]$sb.AppendLine("`t`t`t<IncludeHelpInContents>true</IncludeHelpInContents>")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# subsystem-edit v1.15 — Edit existing 1C subsystem XML
|
||||
# subsystem-edit v1.16 — Edit existing 1C subsystem XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -193,6 +193,11 @@ def new_uuid():
|
||||
|
||||
|
||||
def esc_xml(s):
|
||||
# Эскейп ЗНАЧЕНИЯ АТРИБУТА: & < > и кавычка — внутри "..." литеральная " невалидна.
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
|
||||
|
||||
|
||||
def esc_xml_text(s):
|
||||
"""Экранирование ТЕКСТА элемента: только & < > . Кавычки платформа в тексте не экранирует
|
||||
(92142 сырых кавычки на корпус, ни одной "); " она принимает, но нормализует обратно."""
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
@@ -250,7 +255,7 @@ def write_child_subsystem_stub(child_path, child_name, format_version):
|
||||
lines.append(f'<MetaDataObject {XMLNS_DECL} version="{format_version}">')
|
||||
lines.append(f'\t<Subsystem uuid="{child_uuid}">')
|
||||
lines.append('\t\t<Properties>')
|
||||
lines.append(f'\t\t\t<Name>{esc_xml(child_name)}</Name>')
|
||||
lines.append(f'\t\t\t<Name>{esc_xml_text(child_name)}</Name>')
|
||||
lines.append('\t\t\t<Synonym/>')
|
||||
lines.append('\t\t\t<Comment/>')
|
||||
lines.append('\t\t\t<IncludeHelpInContents>true</IncludeHelpInContents>')
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<Configuration uuid="UUID-001">
|
||||
<InternalInfo>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-002</xr:ClassId>
|
||||
<xr:ObjectId>UUID-003</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-004</xr:ClassId>
|
||||
<xr:ObjectId>UUID-005</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-006</xr:ClassId>
|
||||
<xr:ObjectId>UUID-007</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-008</xr:ClassId>
|
||||
<xr:ObjectId>UUID-009</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-010</xr:ClassId>
|
||||
<xr:ObjectId>UUID-011</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-012</xr:ClassId>
|
||||
<xr:ObjectId>UUID-013</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-014</xr:ClassId>
|
||||
<xr:ObjectId>UUID-015</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>Экранирование</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Кавычка " апостроф ' амперсанд & угол <</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<NamePrefix/>
|
||||
<ConfigurationExtensionCompatibilityMode>Version8_3_24</ConfigurationExtensionCompatibilityMode>
|
||||
<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
||||
<UsePurposes>
|
||||
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
|
||||
</UsePurposes>
|
||||
<ScriptVariant>Russian</ScriptVariant>
|
||||
<DefaultRoles/>
|
||||
<Vendor/>
|
||||
<Version/>
|
||||
<UpdateCatalogAddress/>
|
||||
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||
<UseManagedFormInOrdinaryApplication>false</UseManagedFormInOrdinaryApplication>
|
||||
<UseOrdinaryFormInManagedApplication>false</UseOrdinaryFormInManagedApplication>
|
||||
<AdditionalFullTextSearchDictionaries/>
|
||||
<CommonSettingsStorage/>
|
||||
<ReportsUserSettingsStorage/>
|
||||
<ReportsVariantsStorage/>
|
||||
<FormDataSettingsStorage/>
|
||||
<DynamicListsUserSettingsStorage/>
|
||||
<URLExternalDataStorage/>
|
||||
<Content/>
|
||||
<DefaultReportForm/>
|
||||
<DefaultReportVariantForm/>
|
||||
<DefaultReportSettingsForm/>
|
||||
<DefaultReportAppearanceTemplate/>
|
||||
<DefaultDynamicListSettingsForm/>
|
||||
<DefaultSearchForm/>
|
||||
<DefaultDataHistoryChangeHistoryForm/>
|
||||
<DefaultDataHistoryVersionDataForm/>
|
||||
<DefaultDataHistoryVersionDifferencesForm/>
|
||||
<DefaultCollaborationSystemUsersChoiceForm/>
|
||||
<RequiredMobileApplicationPermissions/>
|
||||
<UsedMobileApplicationFunctionalities>
|
||||
<app:functionality>
|
||||
<app:functionality>Biometrics</app:functionality>
|
||||
<app:use>true</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Location</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BackgroundLocation</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BluetoothPrinters</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>WiFiPrinters</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Contacts</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Calendars</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>PushNotifications</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>LocalNotifications</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>InAppPurchases</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>PersonalComputerFileExchange</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Ads</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>NumberDialing</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>CallProcessing</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>CallLog</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AutoSendSMS</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>ReceiveSMS</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>SMSLog</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Camera</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Microphone</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>MusicLibrary</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>PictureAndVideoLibraries</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AudioPlaybackAndVibration</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BackgroundAudioPlaybackAndVibration</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>InstallPackages</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>OSBackup</app:functionality>
|
||||
<app:use>true</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>ApplicationUsageStatistics</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BarcodeScanning</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BackgroundAudioRecording</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AllFilesAccess</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Videoconferences</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>NFC</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>DocumentScanning</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>SpeechToText</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Geofences</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>IncomingShareRequests</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AllIncomingShareRequestsTypesProcessing</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
</UsedMobileApplicationFunctionalities>
|
||||
<StandaloneConfigurationRestrictionRoles/>
|
||||
<MobileApplicationURLs/>
|
||||
<AllowedIncomingShareRequestTypes/>
|
||||
<MainClientApplicationWindowMode>Normal</MainClientApplicationWindowMode>
|
||||
<DefaultInterface/>
|
||||
<DefaultStyle/>
|
||||
<DefaultLanguage>Language.Русский</DefaultLanguage>
|
||||
<BriefInformation/>
|
||||
<DetailedInformation/>
|
||||
<Copyright/>
|
||||
<VendorInformationAddress/>
|
||||
<ConfigurationInformationAddress/>
|
||||
<DataLockControlMode>Managed</DataLockControlMode>
|
||||
<ObjectAutonumerationMode>NotAutoFree</ObjectAutonumerationMode>
|
||||
<ModalityUseMode>DontUse</ModalityUseMode>
|
||||
<SynchronousPlatformExtensionAndAddInCallUseMode>DontUse</SynchronousPlatformExtensionAndAddInCallUseMode>
|
||||
<InterfaceCompatibilityMode>TaxiEnableVersion8_2</InterfaceCompatibilityMode>
|
||||
<DatabaseTablespacesUseMode>DontUse</DatabaseTablespacesUseMode>
|
||||
<CompatibilityMode>Version8_3_24</CompatibilityMode>
|
||||
<DefaultConstantsForm/>
|
||||
</Properties>
|
||||
<ChildObjects>
|
||||
<Language>Русский</Language>
|
||||
</ChildObjects>
|
||||
</Configuration>
|
||||
</MetaDataObject>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
|
||||
<top>
|
||||
<panel id="UUID-001">
|
||||
<uuid>UUID-002</uuid>
|
||||
</panel>
|
||||
</top>
|
||||
<left>
|
||||
<panel id="UUID-003">
|
||||
<uuid>UUID-004</uuid>
|
||||
</panel>
|
||||
</left>
|
||||
<panelDef id="UUID-004"/>
|
||||
<panelDef id="UUID-005"/>
|
||||
<panelDef id="UUID-006"/>
|
||||
<panelDef id="UUID-002"/>
|
||||
<panelDef id="UUID-007"/>
|
||||
</ClientApplicationInterface>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<Language uuid="UUID-001">
|
||||
<Properties>
|
||||
<Name>Русский</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Русский</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<LanguageCode>ru</LanguageCode>
|
||||
</Properties>
|
||||
</Language>
|
||||
</MetaDataObject>
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "Спецсимволы в синониме: экранируются только & < >",
|
||||
"params": {
|
||||
"name": "Экранирование"
|
||||
},
|
||||
"args_extra": [
|
||||
"-Synonym",
|
||||
"Кавычка \" апостроф ' амперсанд & угол <"
|
||||
],
|
||||
"expect": {
|
||||
"files": ["Configuration.xml"],
|
||||
"fileContains": {
|
||||
"file": "Configuration.xml",
|
||||
"text": "<v8:content>Кавычка \" апостроф ' амперсанд & угол <</v8:content>"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "Кавычка в значении атрибута экранируется ("), иначе XML невалиден",
|
||||
"preRun": [
|
||||
{
|
||||
"script": "meta-compile/scripts/meta-compile",
|
||||
"input": { "type": "DataProcessor", "name": "Экранирование" },
|
||||
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
||||
},
|
||||
{
|
||||
"script": "form-add/scripts/form-add",
|
||||
"args": { "-ObjectPath": "{workDir}/DataProcessors/Экранирование.xml", "-FormName": "Форма" }
|
||||
}
|
||||
],
|
||||
"params": { "outputPath": "DataProcessors/Экранирование/Forms/Форма/Ext/Form.xml" },
|
||||
"validatePath": "DataProcessors/Экранирование/Forms/Форма/Ext/Form.xml",
|
||||
"input": {
|
||||
"attributes": [ { "name": "Значение", "type": "String" } ],
|
||||
"elements": [
|
||||
{
|
||||
"input": "Поле",
|
||||
"path": "Значение",
|
||||
"choiceParameters": [
|
||||
{ "name": "Отбор.Наименование \"в кавычках\" & <угол>", "value": "тест" }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"expect": {
|
||||
"fileContains": {
|
||||
"file": "DataProcessors/Экранирование/Forms/Форма/Ext/Form.xml",
|
||||
"text": "name=\"Отбор.Наименование "в кавычках" & <угол>\""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<Configuration uuid="UUID-001">
|
||||
<InternalInfo>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-002</xr:ClassId>
|
||||
<xr:ObjectId>UUID-003</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-004</xr:ClassId>
|
||||
<xr:ObjectId>UUID-005</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-006</xr:ClassId>
|
||||
<xr:ObjectId>UUID-007</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-008</xr:ClassId>
|
||||
<xr:ObjectId>UUID-009</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-010</xr:ClassId>
|
||||
<xr:ObjectId>UUID-011</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-012</xr:ClassId>
|
||||
<xr:ObjectId>UUID-013</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
<xr:ContainedObject>
|
||||
<xr:ClassId>UUID-014</xr:ClassId>
|
||||
<xr:ObjectId>UUID-015</xr:ObjectId>
|
||||
</xr:ContainedObject>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>TestConfig</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>TestConfig</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<NamePrefix/>
|
||||
<ConfigurationExtensionCompatibilityMode>Version8_3_24</ConfigurationExtensionCompatibilityMode>
|
||||
<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
||||
<UsePurposes>
|
||||
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
|
||||
</UsePurposes>
|
||||
<ScriptVariant>Russian</ScriptVariant>
|
||||
<DefaultRoles/>
|
||||
<Vendor/>
|
||||
<Version/>
|
||||
<UpdateCatalogAddress/>
|
||||
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||
<UseManagedFormInOrdinaryApplication>false</UseManagedFormInOrdinaryApplication>
|
||||
<UseOrdinaryFormInManagedApplication>false</UseOrdinaryFormInManagedApplication>
|
||||
<AdditionalFullTextSearchDictionaries/>
|
||||
<CommonSettingsStorage/>
|
||||
<ReportsUserSettingsStorage/>
|
||||
<ReportsVariantsStorage/>
|
||||
<FormDataSettingsStorage/>
|
||||
<DynamicListsUserSettingsStorage/>
|
||||
<URLExternalDataStorage/>
|
||||
<Content/>
|
||||
<DefaultReportForm/>
|
||||
<DefaultReportVariantForm/>
|
||||
<DefaultReportSettingsForm/>
|
||||
<DefaultReportAppearanceTemplate/>
|
||||
<DefaultDynamicListSettingsForm/>
|
||||
<DefaultSearchForm/>
|
||||
<DefaultDataHistoryChangeHistoryForm/>
|
||||
<DefaultDataHistoryVersionDataForm/>
|
||||
<DefaultDataHistoryVersionDifferencesForm/>
|
||||
<DefaultCollaborationSystemUsersChoiceForm/>
|
||||
<RequiredMobileApplicationPermissions/>
|
||||
<UsedMobileApplicationFunctionalities>
|
||||
<app:functionality>
|
||||
<app:functionality>Biometrics</app:functionality>
|
||||
<app:use>true</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Location</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BackgroundLocation</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BluetoothPrinters</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>WiFiPrinters</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Contacts</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Calendars</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>PushNotifications</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>LocalNotifications</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>InAppPurchases</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>PersonalComputerFileExchange</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Ads</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>NumberDialing</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>CallProcessing</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>CallLog</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AutoSendSMS</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>ReceiveSMS</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>SMSLog</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Camera</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Microphone</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>MusicLibrary</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>PictureAndVideoLibraries</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AudioPlaybackAndVibration</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BackgroundAudioPlaybackAndVibration</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>InstallPackages</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>OSBackup</app:functionality>
|
||||
<app:use>true</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>ApplicationUsageStatistics</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BarcodeScanning</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>BackgroundAudioRecording</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AllFilesAccess</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Videoconferences</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>NFC</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>DocumentScanning</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>SpeechToText</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>Geofences</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>IncomingShareRequests</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
<app:functionality>
|
||||
<app:functionality>AllIncomingShareRequestsTypesProcessing</app:functionality>
|
||||
<app:use>false</app:use>
|
||||
</app:functionality>
|
||||
</UsedMobileApplicationFunctionalities>
|
||||
<StandaloneConfigurationRestrictionRoles/>
|
||||
<MobileApplicationURLs/>
|
||||
<AllowedIncomingShareRequestTypes/>
|
||||
<MainClientApplicationWindowMode>Normal</MainClientApplicationWindowMode>
|
||||
<DefaultInterface/>
|
||||
<DefaultStyle/>
|
||||
<DefaultLanguage>Language.Русский</DefaultLanguage>
|
||||
<BriefInformation/>
|
||||
<DetailedInformation/>
|
||||
<Copyright/>
|
||||
<VendorInformationAddress/>
|
||||
<ConfigurationInformationAddress/>
|
||||
<DataLockControlMode>Managed</DataLockControlMode>
|
||||
<ObjectAutonumerationMode>NotAutoFree</ObjectAutonumerationMode>
|
||||
<ModalityUseMode>DontUse</ModalityUseMode>
|
||||
<SynchronousPlatformExtensionAndAddInCallUseMode>DontUse</SynchronousPlatformExtensionAndAddInCallUseMode>
|
||||
<InterfaceCompatibilityMode>TaxiEnableVersion8_2</InterfaceCompatibilityMode>
|
||||
<DatabaseTablespacesUseMode>DontUse</DatabaseTablespacesUseMode>
|
||||
<CompatibilityMode>Version8_3_24</CompatibilityMode>
|
||||
<DefaultConstantsForm/>
|
||||
</Properties>
|
||||
<ChildObjects>
|
||||
<Language>Русский</Language>
|
||||
<DataProcessor>Экранирование</DataProcessor>
|
||||
</ChildObjects>
|
||||
</Configuration>
|
||||
</MetaDataObject>
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<DataProcessor uuid="UUID-001">
|
||||
<InternalInfo>
|
||||
<xr:GeneratedType name="DataProcessorObject.Экранирование" category="Object">
|
||||
<xr:TypeId>UUID-002</xr:TypeId>
|
||||
<xr:ValueId>UUID-003</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="DataProcessorManager.Экранирование" category="Manager">
|
||||
<xr:TypeId>UUID-004</xr:TypeId>
|
||||
<xr:ValueId>UUID-005</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>Экранирование</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Экранирование</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<UseStandardCommands>true</UseStandardCommands>
|
||||
<DefaultForm>DataProcessor.Экранирование.Form.Форма</DefaultForm>
|
||||
<AuxiliaryForm/>
|
||||
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||
<ExtendedPresentation/>
|
||||
<Explanation/>
|
||||
</Properties>
|
||||
<ChildObjects>
|
||||
<Form>Форма</Form>
|
||||
</ChildObjects>
|
||||
</DataProcessor>
|
||||
</MetaDataObject>
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<Form uuid="UUID-001">
|
||||
<Properties>
|
||||
<Name>Форма</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Форма</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<FormType>Managed</FormType>
|
||||
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||
<UsePurposes>
|
||||
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
|
||||
<v8:Value xsi:type="app:ApplicationUsePurpose">MobilePlatformApplication</v8:Value>
|
||||
</UsePurposes>
|
||||
<ExtendedPresentation/>
|
||||
</Properties>
|
||||
</Form>
|
||||
</MetaDataObject>
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Form xmlns="http://v8.1c.ru/8.3/xcf/logform" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core" xmlns:dcssch="http://v8.1c.ru/8.1/data-composition-system/schema" xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<AutoCommandBar name="ФормаКоманднаяПанель" id="-1"/>
|
||||
<ChildItems>
|
||||
<InputField name="Поле" id="1">
|
||||
<DataPath>Значение</DataPath>
|
||||
<ChoiceParameters>
|
||||
<app:item name="Отбор.Наименование "в кавычках" & <угол>">
|
||||
<app:value xsi:type="FormChoiceListDesTimeValue">
|
||||
<Presentation/>
|
||||
<Value xsi:type="xs:string">тест</Value>
|
||||
</app:value>
|
||||
</app:item>
|
||||
</ChoiceParameters>
|
||||
<ContextMenu name="ПолеКонтекстноеМеню" id="2"/>
|
||||
<ExtendedTooltip name="ПолеРасширеннаяПодсказка" id="3"/>
|
||||
</InputField>
|
||||
</ChildItems>
|
||||
<Attributes>
|
||||
<Attribute name="Значение" id="4">
|
||||
<Title>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Значение</v8:content>
|
||||
</v8:item>
|
||||
</Title>
|
||||
<Type>
|
||||
<v8:Type>xs:string</v8:Type>
|
||||
<v8:StringQualifiers>
|
||||
<v8:Length>0</v8:Length>
|
||||
<v8:AllowedLength>Variable</v8:AllowedLength>
|
||||
</v8:StringQualifiers>
|
||||
</Type>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Form>
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#Область ОбработчикиСобытийФормы
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область ОбработчикиСобытийЭлементовФормы
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область ОбработчикиКомандФормы
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область ОбработчикиОповещений
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область СлужебныеПроцедурыИФункции
|
||||
|
||||
#КонецОбласти
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
|
||||
<top>
|
||||
<panel id="UUID-001">
|
||||
<uuid>UUID-002</uuid>
|
||||
</panel>
|
||||
</top>
|
||||
<left>
|
||||
<panel id="UUID-003">
|
||||
<uuid>UUID-004</uuid>
|
||||
</panel>
|
||||
</left>
|
||||
<panelDef id="UUID-004"/>
|
||||
<panelDef id="UUID-005"/>
|
||||
<panelDef id="UUID-006"/>
|
||||
<panelDef id="UUID-002"/>
|
||||
<panelDef id="UUID-007"/>
|
||||
</ClientApplicationInterface>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<Language uuid="UUID-001">
|
||||
<Properties>
|
||||
<Name>Русский</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Русский</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment/>
|
||||
<LanguageCode>ru</LanguageCode>
|
||||
</Properties>
|
||||
</Language>
|
||||
</MetaDataObject>
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "additionalProperties: ключ идёт в значение атрибута — кавычка экранируется",
|
||||
"params": {
|
||||
"outputPath": "Template.xml"
|
||||
},
|
||||
"input": {
|
||||
"dataSets": [
|
||||
{
|
||||
"name": "Основной",
|
||||
"query": "ВЫБРАТЬ 1 КАК Поле1",
|
||||
"fields": ["Поле1: Число(1,0)"]
|
||||
}
|
||||
],
|
||||
"settingsVariants": [
|
||||
{
|
||||
"name": "Основной",
|
||||
"presentation": "Основной вариант",
|
||||
"settings": {
|
||||
"additionalProperties": {
|
||||
"Ключ \"в кавычках\" & <угол>": "Значение \"в кавычках\" & <угол>"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"validatePath": "Template.xml",
|
||||
"expect": {
|
||||
"fileContains": {
|
||||
"file": "Template.xml",
|
||||
"text": [
|
||||
"<v8:Property name=\"Ключ "в кавычках" & <угол>\">",
|
||||
"<v8:Value xsi:type=\"xs:string\">Значение \"в кавычках\" & <угол></v8:Value>"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<DataCompositionSchema xmlns="http://v8.1c.ru/8.1/data-composition-system/schema" xmlns:dcscom="http://v8.1c.ru/8.1/data-composition-system/common" xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core" xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<dataSource>
|
||||
<name>ИсточникДанных1</name>
|
||||
<dataSourceType>Local</dataSourceType>
|
||||
</dataSource>
|
||||
<dataSet xsi:type="DataSetQuery">
|
||||
<name>Основной</name>
|
||||
<field xsi:type="DataSetFieldField">
|
||||
<dataPath>Поле1</dataPath>
|
||||
<field>Поле1</field>
|
||||
<valueType>
|
||||
<v8:Type>xs:decimal</v8:Type>
|
||||
<v8:NumberQualifiers>
|
||||
<v8:Digits>1</v8:Digits>
|
||||
<v8:FractionDigits>0</v8:FractionDigits>
|
||||
<v8:AllowedSign>Any</v8:AllowedSign>
|
||||
</v8:NumberQualifiers>
|
||||
</valueType>
|
||||
</field>
|
||||
<dataSource>ИсточникДанных1</dataSource>
|
||||
<query>ВЫБРАТЬ 1 КАК Поле1</query>
|
||||
</dataSet>
|
||||
<settingsVariant>
|
||||
<dcsset:name>Основной</dcsset:name>
|
||||
<dcsset:presentation xsi:type="v8:LocalStringType">
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Основной вариант</v8:content>
|
||||
</v8:item>
|
||||
</dcsset:presentation>
|
||||
<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">
|
||||
<dcsset:additionalProperties>
|
||||
<v8:Property name="Ключ "в кавычках" & <угол>">
|
||||
<v8:Value xsi:type="xs:string">Значение "в кавычках" & <угол></v8:Value>
|
||||
</v8:Property>
|
||||
</dcsset:additionalProperties>
|
||||
</dcsset:settings>
|
||||
</settingsVariant>
|
||||
</DataCompositionSchema>
|
||||
@@ -3,9 +3,13 @@
|
||||
// копируются в каждый .ps1/.py — docs/python-porting-guide.md), поэтому нужен гард от расхождения
|
||||
// копий. Реестр семей держим здесь же: реестр про дрейф не должен дрейфовать относительно проверки.
|
||||
//
|
||||
// Часть расхождений ЗАКОННА (например esc_xml без " в form-* ради раундтрипа), поэтому семья
|
||||
// хранит не одно эталонное тело, а список вариантов. У законного варианта обязано быть поле `why`;
|
||||
// вариант без `why` — необоснованный, попадает в список долга (WARN).
|
||||
// Семья хранит не одно эталонное тело, а список вариантов: расхождение бывает и законным. У такого
|
||||
// варианта обязано быть поле `why`; вариант без `why` — необоснованный, идёт в список долга (WARN).
|
||||
//
|
||||
// Важно не путать «вариант» с «разными задачами под одним именем»: esc_xml и esc_xml_text — это
|
||||
// ДВЕ семьи, а не два варианта одной. Платформа в тексте элемента экранирует только & < >, а в
|
||||
// значении атрибута добавляет ", поэтому им нужны разные функции с говорящими именами, каждая
|
||||
// со своим единственным эталоном. Свести такое в один вариант с флагом — значит спрятать разницу.
|
||||
//
|
||||
// Запуск: node tests/skills/check-inline-drift.mjs [--list]
|
||||
// Выход 1 при ERROR, 0 при WARN. Кандидатов в реестр искать: node debug/inline-utils/scan-dupes.mjs
|
||||
@@ -119,22 +123,24 @@ const FAMILIES = [
|
||||
},
|
||||
|
||||
// ─── Экранирование XML ───────────────────────────────────────────────────
|
||||
// Платформа в ТЕКСТЕ элемента экранирует только & < > (кавычка и апостроф остаются сырыми —
|
||||
// проверено раундтрипом через базу), а в ЗНАЧЕНИИ АТРИБУТА добавляет ": внутри "..."
|
||||
// литеральная кавычка невалидна. Отсюда две функции, а не одна с переключателем.
|
||||
{
|
||||
name: 'esc_xml', py: 'esc_xml', ps1: 'Esc-Xml',
|
||||
name: 'esc_xml (значение атрибута)', py: 'esc_xml', ps1: 'Esc-Xml',
|
||||
variants: [
|
||||
{ id: 'text-no-quot', authority: 'form-compile',
|
||||
why: 'экранирование ТЕКСТА элемента: платформа кавычки в тексте не экранирует, " ломает раундтрип',
|
||||
consumers: ['form-edit', 'mxl-compile', 'role-compile', 'skd-compile', 'skd-edit'],
|
||||
consumersPy: ['subsystem-compile', 'subsystem-edit'] },
|
||||
{ id: 'text-no-quot-subsystem-ps1', authority: 'subsystem-compile',
|
||||
consumers: [], consumersPs1: ['subsystem-edit'], port: 'ps1' },
|
||||
{ id: 'attr-with-quot', authority: 'cf-init', port: 'py',
|
||||
why: 'экранирование ЗНАЧЕНИЯ АТРИБУТА: там " обязателен (init-навыки, PS1-порт функции не имеет)',
|
||||
consumers: ['cfe-init', 'epf-init', 'erf-init'] },
|
||||
{ id: 'meta-attr-with-quot', authority: 'meta-compile',
|
||||
why: 'парный esc_xml_text экранирует текст, сам esc_xml применяется только к значениям атрибутов',
|
||||
consumers: ['meta-edit'] },
|
||||
{ id: 'meta-edit-own-py', authority: 'meta-edit', consumers: [], port: 'py' },
|
||||
{ id: 'attr-with-quot', authority: 'meta-compile',
|
||||
consumers: ['form-compile', 'form-edit', 'meta-edit', 'mxl-compile', 'role-compile',
|
||||
'skd-compile', 'skd-edit', 'subsystem-compile', 'subsystem-edit'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'esc_xml_text (текст элемента)', py: 'esc_xml_text', ps1: 'Esc-XmlText',
|
||||
variants: [
|
||||
{ id: 'text-no-quot', authority: 'meta-compile',
|
||||
consumers: ['cf-init', 'cfe-init', 'epf-init', 'erf-init', 'form-compile', 'form-edit',
|
||||
'meta-edit', 'mxl-compile', 'role-compile', 'skd-compile', 'skd-edit',
|
||||
'subsystem-compile', 'subsystem-edit'] },
|
||||
],
|
||||
},
|
||||
// ─── Сохранение стиля XML при round-trip (#44/#46/#47) ───────────────────
|
||||
|
||||
Reference in New Issue
Block a user