При выгрузке и обмене данными в платформе 1С:Предприятие 7.7 часто возникает необходимость обработать каталог с несколькими XML-файлами. В отличие от платформы 1С 8.х, в версии 7.7 отсутствуют встроенные высокоуровневые объекты вроде ЧтениеXML, поэтому для решения задачи используются специализированные COM-объекты Windows или внешняя компонента v7plus.dll.
Рассмотрим подробнее, как правильно построить цикл поиска файлов в каталоге, загрузить XML-документы и рекурсивно обойти их узлы.
Перед тем как переходить к написанию кода, проанализируем важные особенности работы с XML в платформе 7.7:
Текст: Попытка распарсить XML-файл как обычный текстовый документ приводит к ошибкам при встрече спецсимволов (таких как &, <, >), атрибутов или нестандартных кодировок.Microsoft.XMLDOM или более современный MSXML2.DOMDocument.6.0).Load() следует отключить асинхронный режим, установив свойство async = 0.v7plus.dll (объект AddIn.XMLParser).Выясним, как организовать поиск и перебор всех XML-файлов в папке. Для этого используем встроенный объект ФС (Файловая Система) и его методы НайтиПервыйФайл() и НайтиСледующийФайл().
Разберем пример кода, который ищет файлы по маске и передает каждый из них на обработку:
КаталогЗагрузки = "C:\XML_Data\";
МаскаПоиска = КаталогЗагрузки + "*.xml";
ИмяФайла = ФС.НайтиПервыйФайл(МаскаПоиска);
Пока ПустаяСтрока(ИмяФайла) = 0 Цикл
Если (ИмяФайла <> ".") И (ИмяФайла <> "..") Тогда
ПолныйПутьКФайлу = КаталогЗагрузки + ИмяФайла;
Сообщить("Обработка файла: " + ПолныйПутьКФайлу);
// Вызов процедуры чтения XML
ОбработатьФайлXML(ПолныйПутьКФайлу);
КонецЕсли;
ИмяФайла = ФС.НайтиСледующийФайл();
КонецЦикла;
После того как файл найден, его необходимо загрузить в объект DOM-модели и распарсить теги и атрибуты. Рассмотрим пример чтения структуры с помощью объекта Microsoft.XMLDOM.
Посмотрим на алгоритм загрузки документа и вызова рекурсивной обработки:
Процедура ОбработатьФайлXML(ФайлДанных)
Иксемель = СоздатьОбъект("Microsoft.XMLDOM");
Иксемель.async = 0; // Включаем синхронный режим загрузки
Если Иксемель.Load(ФайлДанных) = 0 Тогда
Сообщить("Ошибка загрузки XML-файла: " + ФайлДанных);
Возврат;
КонецЕсли;
Корень = Иксемель.DocumentElement;
ОбработатьУзел(Корень, 0);
КонецПроцедуры
Для обхода всех дочерних элементов используется рекурсивная процедура. Она проверяет тип узла, считывает его атрибуты, текстовое значение и переходит на следующий уровень вложенности.
Разберем код процедуры ОбработатьУзел:
Процедура ОбработатьУзел(Узел, Уровень=0)
Состояние("Обработка уровня: " + Уровень);
КолвоУзлов = Узел.childNodes.length;
Для СчУзлов = 0 По КолвоУзлов - 1 Цикл
ТекУзел = Узел.childNodes.item(СчУзлов);
// Проверяем, что узел является элементом (nodeType = 1)
Если ТекУзел.nodeType <> 1 Тогда
Продолжить;
КонецЕсли;
СтрПрефикс = Формат("", "С" + Уровень * 4);
// Считывание атрибутов текущего узла
СтрАтрибуты = "";
Для счАтрибутов = 0 По ТекУзел.attributes.length - 1 Цикл
Атрибут = ТекУзел.attributes.item(счАтрибутов);
СтрАтрибуты = СтрАтрибуты + ?(СтрАтрибуты = "", "", "; ") + Атрибут.nodeName + "=" + Атрибут.value;
КонецЦикла;
// Получение текстового значения узла
ТекстУзла = "";
Если ТекУзел.childNodes.length = 1 Тогда
Если ТекУзел.childNodes.item(0).nodeType = 3 Тогда
ТекстУзла = ТекУзел.childNodes.item(0).text;
КонецЕсли;
КонецЕсли;
// Вывод информации в окно сообщений
СтрИтог = СтрПрефикс + ТекУзел.tagName + ?(СтрАтрибуты = "", "", " (" + СтрАтрибуты + ")") + ": " + ТекстУзла;
Сообщить(СтрИтог);
// Рекурсивный вызов для дочерних узлов
ОбработатьУзел(ТекУзел, Уровень + 1);
КонецЦикла;
Состояние("");
КонецПроцедуры
Помимо рекурсивного перебора узлов childNodes, при работе с XML в 1С 7.7 применяются следующие решения:
selectNodes() и selectSingleNode(). Это существенно ускоряет выборку нужных данных.AddIn.XMLParser, который позволяет считывать файлы без прямого обращения к COM-объектам Windows.