При разработке механизмов обмена данными в среде 1С:Предприятие 7.7 программисты часто сталкиваются с ограничениями стандартной компоненты v7plus.dll. Одной из типичных задач является изменение структуры XML-файла, когда данные должны передаваться не в виде атрибутов тега, а внутри самого элемента. Кроме того, часто требуется тонкая настройка заголовков и пространств имен (Namespaces) для соответствия внешним стандартам. В этой статье мы подробно разберем, как решить эти задачи программно. При необходимости можно воспользоваться обработкой выгрузки документов из 1С 7.7 в XML-формат EnterpriseData.
Рассмотрим ситуацию, когда по умолчанию выгрузка формирует строку вида <attribute BegPeriod="2020-02-01"></attribute>, а принимающая сторона ожидает формат <BegPeriod>2020-02-01</BegPeriod>. Проанализируем, почему это происходит: при использовании метода УстановитьАтрибут данные всегда записываются внутрь открывающего тега. Чтобы записать значение именно как текст между тегами, нам нужно создать подчиненный элемент и установить его свойство Текст.
Разберем по шагам правильный алгоритм действий:
СоздатьПодчиненныйЭлемент.Текст созданного узла.Посмотрим на практический пример кода:
// Предположим, хмлКорень уже создан
// Создаем тег для даты начала периода
хмлЯчейка = хмлКорень.СоздатьПодчиненныйЭлемент("BegPeriod");
// Форматируем дату в стандарт XML (ГГГГ-ММ-ДД) и записываем в текст тега
хмлЯчейка.Текст = Формат(ДатаГод(НачДата),"Ч(0)4")+"-"+Формат(ДатаМесяц(НачДата),"Ч(0)2")+"-"+Формат(ДатаЧисло(НачДата),"Ч(0)2");
// Аналогично для даты окончания периода
хмлЯчейка = хмлКорень.СоздатьПодчиненныйЭлемент("EndPeriod");
хмлЯчейка.Текст = Формат(ДатаГод(КонДата),"Ч(0)4")+"-"+Формат(ДатаМесяц(КонДата),"Ч(0)2")+"-"+Формат(ДатаЧисло(КонДата),"Ч(0)2");
Важный нюанс: В 1С 7.7 нет встроенного метода УстановитьТекст для объектов v7plus, поэтому прямое обращение к свойству Текст является наиболее корректным способом записи данных внутрь тега.
Поскольку 1С 7.7 хранит даты во внутреннем формате, для корректной выгрузки в XML их необходимо преобразовывать в строку формата YYYY-MM-DD. Выясним причину использования сложной конструкции с Формат: стандартный метод преобразования даты в строку в "семерке" выдает формат ДД.ММ.ГГ, который не валиден для большинства XML-схем.
Мы можем оптимизировать код форматирования, создав вспомогательную функцию, или использовать возможности v7plus (если версия компоненты поддерживает метод СформироватьДатуXML). Однако ручная сборка строки остается самым надежным методом:
Функция ГГГГММДД(Знач ТекДата)
Возврат "" + ДатаГод(ТекДата) + "-" +
Формат(ДатаМесяц(ТекДата),"Ч(0)2") + "-" +
Формат(ДатаЧисло(ТекДата),"Ч(0)2");
КонецФункции
Часто государственные информационные системы или банковские шлюзы требуют наличия специфических пространств имен в корневом теге документа. Например, xmlns:xsd или xmlns:xsi. Рассмотрим, как правильно добавить эти декларации, не превращая XML в обычную текстовую строку.
Проанализируем ситуацию: использование УстановитьАтрибут("xmlns:xsd", "...") может привести к ошибкам, так как xmlns — это зарезервированное слово. Правильнее использовать специализированный метод УстановитьПространствоИмен.
Пример настройки корневого элемента с несколькими пространствами имен:
// Создаем корень с основным пространством имен
хмлКорень = хмлФайлДанных.СоздатьПодчиненныйЭлемент("DataType", , "http://www.dipo.org");
// Добавляем дополнительные пространства имен (xsd и xsi)
хмлКорень.УстановитьПространствоИмен("http://www.w3.org/2001/XMLSchema", "xsd");
хмлКорень.УстановитьПространствоИмен("http://www.w3.org/2001/XMLSchema-instance", "xsi");
Обратите внимание: Согласно стандартам XML, порядок следования атрибутов xmlns внутри тега не имеет значения для парсеров. Если принимающая система требует строго определенного порядка, это говорит о некорректности парсера на той стороне. Однако, если изменить порядок программно через DOM не удается, можно прибегнуть к "текстовому" методу коррекции файла.
Если возможности v7plus.dll исчерпаны или компонента работает нестабильно (например, из-за конфликта версий MSXML в системе), рассмотрим альтернативные пути решения задачи.
1. Метод прямой правки текста
Если вам нужно убрать стандартный заголовок <?xml version="1.0" encoding="UTF-8"?> или вставить специфические символы, которые XML-анализатор удаляет, можно обработать файл как текст после его сохранения. Для этого используем объект V7TextFile или стандартный Текст.
ТекстФайл = СоздатьОбъект("Текст");
ТекстФайл.Открыть(ИмяФайла);
ВсегоСтрок = ТекстФайл.КоличествоСтрок();
Если ВсегоСтрок > 0 Тогда
ПерваяСтрока = ТекстФайл.ПолучитьСтроку(1);
// Заменяем заголовок или модифицируем его
НоваяСтрока = СтрЗаменить(ПерваяСтрока, "<?xml version=""1.0"" encoding=""UTF-8""?>", "");
ТекстФайл.ЗаменитьСтроку(1, НоваяСтрока);
ТекстФайл.Записать(ИмяФайла);
КонецЕсли;
2. Использование прямого COM-соединения с MSXML
Вместо обертки v7plus мы можем использовать объект Microsoft XML (MSXML) напрямую. Это даст больше гибкости при работе с кодировками и сложными структурами.
// Создаем объект DOM документа напрямую
хмлДок = СоздатьОбъект("MSXML2.DOMDocument.6.0");
хмлКорень = хмлДок.createElement("DataType");
хмлДок.appendChild(хмлКорень);
// Добавление атрибута пространства имен вручную
хмлКорень.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
хмлДок.save(ПутьКФайлу);
Подводя итог, можно сказать, что для большинства задач выгрузки в 1С 7.7 достаточно грамотного использования v7plus.dll. Главное — помнить, что для создания структуры "значение внутри тега" мы используем свойство Текст подчиненного элемента, а для управления метаданными — методы работы с пространствами имен. Если же внешняя система предъявляет избыточные требования к форматированию (порядок атрибутов, отсутствие заголовков), всегда можно воспользоваться постобработкой файла через объект Текст.