fix(skd-edit): гард на CDATA при нормализации пустого тега

skd-edit нормализовал ` />` в `/>` без проверки на CDATA и комментарии, в отличие
от остальных 23 мест, где такая нормализация есть. Вскрылось сверкой копий:
конструкция повторяется в 24 местах, и вариантов формы должно быть ровно два —
с гардом и никак иначе.

Гард нужен потому, что `>` не экранируется только внутри CDATA и комментариев —
там ` />` может оказаться содержимым, а не концом тега. В 1С-метаданных ни того,
ни другого не встречается (0 из 476 943 XML корпуса), так что практического
расхождения поведения нет — но полагаться на это в одном месте и защищаться
в остальных двадцати трёх непоследовательно.

Правка в обоих портах: у py-порта нормализация тоже была без гарда (она там
защитная — lxml и так пишет плотно).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-05 20:05:47 +03:00
co-authored by Claude Opus 5
parent 67185657c1
commit 4c64b97cec
2 changed files with 12 additions and 8 deletions
+5 -4
View File
@@ -1,4 +1,4 @@
# skd-edit v1.30 — Atomic 1C DCS editor
# skd-edit v1.31 — Atomic 1C DCS editor
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: парный .py собирает выражения автодат вне f-string ради совместимости с python 3.9 (PEP 701).
param(
@@ -4045,9 +4045,10 @@ if ($script:RawRootOpening) {
$content = [regex]::Replace($content, '<DataCompositionSchema\b[^>]*>', { param($m) $script:RawRootOpening })
}
# (2) normalize self-closing tags: `.NET XmlDocument` adds a space before `/>`
# (`<foo bar="x" />`) but 1C-Designer writes `<foo bar="x"/>`. Strip the space.
$content = [regex]::Replace($content, '(?<=\S) />', '/>')
# (2) Пустой элемент: XmlWriter отдаёт `<a />`, Конфигуратор пишет `<a/>`. Гард на
# CDATA/комментарии: только там `>` не экранируется, и ` />` может быть
# содержимым, а не концом тега.
if ($content -notmatch '<!\[CDATA\[|<!--') { $content = [regex]::Replace($content, '(?<=\S) />', '/>') }
# (3) normalize line endings to match source — operations may mix LF (from new
# fragments) with whatever the source used (CRLF on Windows, LF on Linux/git).
+7 -4
View File
@@ -1,4 +1,4 @@
# skd-edit v1.30 — Atomic 1C DCS editor (Python port)
# skd-edit v1.31 — Atomic 1C DCS editor (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import json
@@ -3440,9 +3440,12 @@ xml_bytes = xml_bytes.replace(
xml_text = xml_bytes.decode("utf-8")
if raw_root_opening:
xml_text = re.sub(r"<DataCompositionSchema\b[^>]*>", lambda m: raw_root_opening, xml_text, count=1, flags=re.DOTALL)
# Normalize self-closing tags: lxml writes `<foo bar="x"/>` already (no space), but be
# defensive — strip any space before `/>` so PS and PY ports stay byte-equivalent.
xml_text = re.sub(r"(?<=\S) />", "/>", xml_text)
# Пустой элемент: XmlWriter отдаёт `<a />`, Конфигуратор пишет `<a/>` (lxml и так
# пишет плотно — правка защитная, чтобы порты оставались байт-эквивалентны). Гард на
# CDATA/комментарии: только там `>` не экранируется, и ` />` может быть содержимым,
# а не концом тега.
if "<![CDATA[" not in xml_text and "<!--" not in xml_text:
xml_text = re.sub(r"(?<=\S) />", "/>", xml_text)
# Канонизировать переносы к LF (убирает возможный &#13;), затем к стилю источника.
xml_text = xml_text.replace("&#13;\n", "\n").replace("&#13;", "").replace("\r\n", "\n").replace("\r", "\n")