Как убрать кавычки при выгрузке данных в XML из 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С со сторонними информационными системами разработчики часто сталкиваются с жесткими требованиями к формату файлов обмена. Одной из типичных проблем является появление нежелательных кавычек в результирующем XML-файле. Например, вместо ожидаемого значения <olcode>99997</olcode> принимающая система получает строку вида <olcode>="99997"</olcode> или атрибуты, которые жестко заключены в кавычки, что вызывает ошибки при парсинге на стороне контрагента.

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

Выясняем причину: разница между атрибутами и элементами

Для начала проанализируем, как устроен формат XML и почему платформа 1С записывает данные в кавычках. В XML-документе данные могут храниться двумя способами:

  1. В виде значений элементов (тегов) — текст располагается между открывающим и закрывающим тегом: <olcode>99997</olcode>. В этом случае кавычки не используются.
  2. В виде атрибутов элементов — параметры записываются внутри открывающего тега: <obj olcode="99997" />.

Согласно строгому международному стандарту W3C XML, значения любых атрибутов обязательно должны быть заключены в кавычки (одинарные или двойные). Платформа 1С строго следует спецификации XML. Если в коде используется метод ЗаписатьАтрибут(), платформа автоматически и принудительно обернет значение в кавычки. Обойти это поведение при записи атрибутов штатными средствами невозможно.

В исходном коде автора темы использовалась следующая конструкция:


ЗаписьXML.ЗаписатьАтрибут("olcode", СокрЛП(СтрЗаменить(СтрокаТЗ.КодТРТ, Символы.НПП, "")));

Именно использование метода ЗаписатьАтрибут() приводило к тому, что в итоговом файле данные выгружались с кавычками. Если принимающая сторона требует передавать «чистые» значения без кавычек, это означает, что данные должны быть записаны как текстовое содержимое элементов, а не как их атрибуты.

---

Решение 1. Переход от атрибутов к текстовым элементам (стандартный способ)

Рассмотрим, как правильно переписать код формирования XML, чтобы избавиться от кавычек. Вместо записи атрибутов мы будем создавать полноценные вложенные теги (элементы) и записывать в них текст с помощью метода ЗаписатьТекст().

Посмотрим на пример преобразования кода:

Было (с кавычками):

ЗаписьXML.ЗаписатьАтрибут("olcode", СокрЛП(СтрокаТЗ.КодТРТ));

Стало (без кавычек):


ЗаписьXML.ЗаписатьНачалоЭлемента("olcode");
ЗаписьXML.ЗаписатьТекст(СокрЛП(СтрокаТЗ.КодТРТ));
ЗаписьXML.ЗаписатьКонецЭлемента();

Давайте полностью переработаем исходный алгоритм выгрузки из сообщения автора с учетом этого правила. Мы заменим выгрузку всех ключевых реквизитов с атрибутной модели на элементную:


ТЗДолги = ПолучитьХОДляВыгрузки(Производитель, ГруппаХО, КонецПериода);

ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(КаталогСервера + "pos.xml", Новый ПараметрыЗаписиXML("windows-1251", , Ложь, Ложь)); 

ЗаписьXML.ЗаписатьОбъявлениеXML(); // Записываем объявление XML

ЗаписьXML.ЗаписатьНачалоЭлемента("objects"); // Начало корневого элемента

Для Каждого СтрокаТЗ Из ТЗДолги Цикл 
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("obj"); // Начало элемента объекта
    
    // Выгружаем "custid" как элемент
    ЗаписьXML.ЗаписатьНачалоЭлемента("custid");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(СтрокаТЗ.КодЗавода));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    // Выгружаем "posid" как элемент с проверкой на заполнение
    ЗаписьXML.ЗаписатьНачалоЭлемента("posid");
    Если ЗначениеЗаполнено(СтрокаТЗ.УИДХО) Тогда
        ЗаписьXML.ЗаписатьТекст(XMLСтрока(Число(СокрЛП(СтрокаТЗ.УИДХО))));
    Else
        ЗаписьXML.ЗаписатьТекст(XMLСтрока(0));
    КонецЕсли;
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    // Выгружаем "olcode" без кавычек
    ЗаписьXML.ЗаписатьНачалоЭлемента("olcode");
    ЗаписьXML.ЗаписатьТекст(СокрЛП(СтрЗаменить(СтрокаТЗ.КодТРТ, Символы.НПП, "")));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    // Выгружаем техническое состояние
    ЗаписьXML.ЗаписатьНачалоЭлемента("technicalcondition");
    ЗаписьXML.ЗаписатьТекст(СокрЛП(СтрокаТЗ.СостояниеХО));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    // Пустой элемент reasonrepair
    ЗаписьXML.ЗаписатьНачалоЭлемента("reasonrepair");
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    // Номер документа
    ЗаписьXML.ЗаписатьНачалоЭлемента("tsconno");
    ЗаписьXML.ЗаписатьТекст(СокрЛП(СтрокаТЗ.НомерДок));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    // Текущая дата в формате XML (ГГГГ-ММ-ДД)
    ЗаписьXML.ЗаписатьНачалоЭлемента("dtlm");
    ЗаписьXML.ЗаписатьТекст(Формат(ТекущаяДата(), "ДФ=yyyy-MM-dd"));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Конец элемента obj
    
КонецЦикла;

ЗаписьXML.ЗаписатьКонецЭлемента(); // Конец элемента objects
ЗаписьXML.Закрыть();

Такой подход гарантирует создание валидного XML-файла, где все текстовые данные будут выгружены без кавычек.

---

Решение 2. Использование метода ЗаписатьБезОбработки() для обхода стандартов

Иногда возникают ситуации, когда принимающая сторона использует некорректно написанный ("самописный") парсер, который требует нарушить стандарты XML. Например, если от вас требуют выгрузить атрибуты вообще без кавычек (что с точки зрения спецификации XML является ошибкой): <obj custid=99997>.

Стандартный метод ЗаписатьАтрибут() всегда добавит кавычки. Чтобы обойти это жесткое ограничение платформы, мы можем воспользоваться методом ЗаписатьБезОбработки() объекта ЗаписьXML.

Проанализируем пример использования этого метода:


// Записываем тег и атрибут без кавычек напрямую в поток
СтрокаАтрибутов = "<obj custid=" + XMLСтрока(СтрокаТЗ.КодЗавода) + ">";
ЗаписьXML.ЗаписатьБезОбработки(СтрокаАтрибутов);

Важное предупреждение: При использовании метода ЗаписатьБезОбработки() вся ответственность за валидность структуры XML-документа, экранирование спецсимволов (таких как &, <, >) и кодировку полностью ложится на плечи разработчика. Платформа 1С в данном случае не выполняет никаких проверок.

---

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

Если структура итогового XML-документа должна содержать спецсимволы в особом формате, или если вам нужно программно убрать определенные кавычки из уже готового файла, можно прибегнуть к пост-обработке файла как обычного текста.

Разберем по шагам, как это реализовать:

  1. Сначала формируем XML-документ стандартными методами платформы (например, через ЗаписьXML) и закрываем его, чтобы сохранить данные на диск.
  2. Затем читаем полученный файл с помощью объекта ТекстовыйДокумент.
  3. Выполняем замену нежелательных символов с помощью функции СтрЗаменить().
  4. Записываем измененный текст обратно в файл.

Рассмотрим пример кода, который заменяет автоматически экранированные кавычки (сущности &quot;) обратно на стандартные символы кавычек, если принимающий парсер не умеет их декодировать:


ПутьКФайлу = КаталогСервера + "pos.xml";

// Читаем сформированный XML как текстовый файл
ТекстДокумента = Новый ТекстовыйДокумент;
ТекстДокумента.Прочитать(ПутьКФайлу, КодировкаТекста.UTF8);

// Получаем текст файла
ИсходныйТекст = ТекстДокумента.ПолучитьТекст();

// Заменяем экранированные сущности на физические кавычки
НовыйТекст = СтрЗаменить(ИсходныйТекст, "&quot;", """");

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

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

---

Важная рекомендация: использование функции XMLСтрока()

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

Выясним, почему это критично:

Применяйте рассмотренные методики в зависимости от требований принимающей стороны, и ваши файлы обмена всегда будут обрабатываться корректно и без ошибок!

← На главную