Как правильно записать кавычки в элемент XML-файла в 1С 7.7 без двойного экранирования

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При выгрузке данных в формат XML с использованием внешней компоненты v7plus.dll (объект XMLParser) в среде «1С:Предприятие 7.7» разработчики часто сталкиваются со следующей проблемой. Попытка вручную заменить кавычки в строке на стандартную XML-сущность " приводит к тому, что в итоговом файле вместо ожидаемых кавычек появляется странная конструкция вида ".

Давайте подробно разберем, почему возникает этот эффект «двойного экранирования», как работает стандарт XML в контексте текстовых узлов и какие практические способы решения этой задачи существуют.

Выясняем причину: почему парсер удваивает экранирование?

Главная ошибка кроется в ручной предобработке строки перед ее передачей в свойство Значение XML-элемента. Рассмотрим типичный ошибочный код:


// Попытка заменить кавычки на " вручную
comments.Значение = СтрЗаменить(НазваниеОрганизации, """", """);

Внешняя компонента v7plus.dll под капотом использует стандартную библиотеку Microsoft MSXML. Эта библиотека строго следует спецификации XML. Согласно правилам консорциума W3C:

  1. Внутри текстового содержимого элементов (между открывающим и закрывающим тегами) двойные кавычки " являются абсолютно легальными символами. Их экранирование не требуется. Обязательными к экранированию в этой области являются только символы «меньше» (< превращается в &lt;) и амперсанд (& превращается в &amp;).
  2. Когда вы принудительно заменяете кавычку на &quot;, парсер видит в строке символ амперсанда (&). Поскольку для XML-парсера это спецсимвол, требующий обязательного экранирования в текстовом поле, он честно заменяет его на &amp;. В результате ваша строка &quot; превращается в файле в &amp;quot;.

Таким образом, парсер просто выполняет свою работу по защите структуры документа, предотвращая ручное вмешательство в формирование спецсимволов.

---

Решение 1. Передача строки «как есть» (Рекомендуемый стандартный способ)

Поскольку кавычки внутри тегов XML являются валидными символами, самым правильным и простым решением будет отказаться от ручной замены. Вам нужно передать строку с физическими кавычками напрямую в объект. Парсер запишет их в файл без изменений.

Рассмотрим, как передать кавычки программно, если их изначально нет в переменной:


// Вариант А: Использование удвоенных кавычек в строковом литерале 1С
comments.Значение = """" + НазваниеОрганизации + """";

// Вариант Б: Использование функции Симв(34) для получения символа кавычки
Кавычка = Симв(34);
comments.Значение = Кавычка + НазваниеОрганизации + Кавычка;

В итоговом XML-файле мы получим корректный и валидный тег:

<comments>"ООО Контральт"</comments> ---

Решение 2. Обходной путь через секции CDATA

Если по какой-то причине принимающая сторона отказывается обрабатывать обычные кавычки в текстовом поле (хотя это стандартное поведение любого XML-декодера) и требует изоляции текста, мы можем использовать секции <![CDATA[...]]>. Внутри таких секций парсеры полностью игнорируют любые спецсимволы, включая кавычки, амперсанды и скобки.

Для создания CDATA-секции в XMLParser необходимо создать подчиненный узел с типом 4 (что соответствует константе NODE_CDATA_SECTION):


// Создаем элемент комментария
comments = invoice.СоздатьПодчиненныйЭлемент("comments");

// Создаем специальный узел CDATA (тип узла - 4)
УзелCDATA = xmlКорень.СоздатьУзел(4, "");
УзелCDATA.Значение = НазваниеОрганизации; // Кавычки здесь будут записаны в исходном виде

// Добавляем созданный CDATA-узел внутрь нашего элемента comments
comments.ДобавитьПодчиненный(УзелCDATA);

На выходе в файле мы получим следующую структуру:

<comments><![CDATA["ООО Контральт"]]></comments> ---

Решение 3. Пост-обработка готового XML-файла

Если информационная система приемника написана некорректно (например, она разбирает XML-файл «самописными» регулярными выражениями вместо стандартного парсера) и жестко требует наличия именно сущностей &quot; внутри тегов, стандартный парсер 1С нам напрямую не поможет. Он всегда будет экранировать амперсанд.

В этом случае мы можем применить хитрость: выгрузить файл стандартным путем (как в Решении 1), а затем открыть его как обычный текст и произвести точечную замену символов.

Проанализируем пример кода для пост-обработки файла:


// Сначала сохраняем XML-документ на диск
ПутьКФайлу = КаталогИБ() + "export.xml";
xmlКорень.Записать(ПутьКФайлу);

// Открываем файл как текстовый документ для точечной замены
ТекстФайла = СоздатьОбъект("Текст");
ТекстФайла.Открыть(ПутьКФайлу);

Для НомерСтроки = 1 По ТекстФайла.КоличествоСтрок() Цикл
    ТекущаяСтрока = ТекстФайла.ПолучитьСтроку(НомерСтроки);
    
    // Выполняем замену только в нужных строках, чтобы не испортить служебные кавычки XML-заголовка
    Если Найти(ТекущаяСтрока, "<comments>") > 0 Тогда
        // Заменяем физическую кавычку Симв(34) на текстовую сущность &quot;
        НоваяСтрока = СтрЗаменить(ТекущаяСтрока, Симв(34), "&quot;");
        ТекстФайла.ЗаменитьСтроку(НомерСтроки, НоваяСтрока);
    КонецЕсли;
КонецЦикла;

// Перезаписываем измененный файл
ТекстФайла.Записать(ПутьКФайлу);

---

Решение 4. Ручная сборка XML-документа без v7plus.dll

В современной практике разработки под 1С 7.7 внешняя компонента v7plus.dll часто признается устаревшей. Она требует регистрации в системном реестре Windows, медленно работает с файлами большого объема и может вызывать сбои на 64-разрядных операционных системах.

Альтернативным и крайне надежным решением является ручная сборка структуры XML через встроенный объект Текст. При таком подходе вы получаете абсолютный контроль над каждым записываемым символом и можете расставлять любые сущности без оглядки на ограничения парсера.

Разберем по шагам шаблон ручного формирования XML:


// Создаем текстовый объект
ТекстXML = СоздатьОбъект("Текст");

// Записываем стандартный заголовок документа
ТекстXML.ДобавитьСтроку("<?xml version=""1.0"" encoding=""windows-1251""?>");
ТекстXML.ДобавитьСтроку("<invoice>");

// Формируем значение с принудительной заменой кавычек на &quot;
ПодготовленныйТекст = СтрЗаменить(НазваниеОрганизации, Симв(34), "&quot;");

// Добавляем строку с тегом comments
ТекстXML.ДобавитьСтроку("    <comments>" + ПодготовленныйТекст + "</comments>");
ТекстXML.ДобавитьСтроку("</invoice>");

// Сохраняем файл на диск
ПутьКФайлу = КаталогИБ() + "manual_export.xml";
ТекстXML.Записать(ПутьКФайлу);

Этот способ гарантирует получение именно той структуры, которую ожидает ваша принимающая система, исключая любые конфликты с логикой работы компоненты v7plus.dll.

← На главную