При интеграции с внешними системами и разборе выгрузок (например, каталогов товаров или прайс-листов) разработчики часто сталкиваются с путаницей в терминологии XML и особенностями работы встроенных объектов 1С. Рассмотрим структуру типового фрагмента XML и разберем, как корректно извлекать значения узлов и их параметров.
Посмотрим на пример структуры XML:
<offer id="20" available="true">
<url>Адрес_ссылки</url>
<price>900</price>
<picture>Ссылка_на_картинку</picture>
<name>Название_товара</name>
<param name="Цвет">Зеленый</param>
<param name="Вес" unit="Кг">3</param>
</offer>
В данном фрагменте важно четко различать два понятия:
offer, price, name. Текст внутри них (например, 900) является текстовым содержимым элемента (тип узла ТипУзлаXML.Текст).id="20" или name="Цвет".Объект ЧтениеXML осуществляет последовательное чтение документа. Это самый быстрый способ с минимальным потреблением оперативной памяти, что критично для больших файлов. Разберем по шагам, как построить логику обработки элементов и атрибутов.
При потоковом чтении мы отслеживаем смену типа узла. Когда курсор попадает на ТипУзлаXML.НачалоЭлемента, мы можем прочитать имя тега и получить его атрибуты. Когда курсор переходит на ТипУзлаXML.Текст, мы считываем строковое значение.
Посмотрим на пример кода разбора предложений в таблицу значений или табличную часть:
ЧтениеXML = Новый ЧтениеXML;
Попытка
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
ИмяТекущегоЭлемента = "";
НоваяСтрока = Неопределено;
Пока ЧтениеXML.Прочитать() Цикл
// 1. Обработка начала элементов и атрибутов
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ИмяТекущегоЭлемента = ЧтениеXML.Имя;
Если ИмяТекущегоЭлемента = "offer" Тогда
НоваяСтрока = ТаблицаТоваров.Добавить();
// Получаем значение конкретного атрибута напрямую по имени
НоваяСтрока.ID = ЧтениеXML.ПолучитьАтрибут("id");
НоваяСтрока.Доступен = ЧтениеXML.ПолучитьАтрибут("available");
КонецЕсли;
// 2. Обработка текстового содержимого тегов
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
Если НоваяСтрока <> Неопределено Тогда
Если ИмяТекущегоЭлемента = "price" Тогда
НоваяСтрока.Цена = Число(ЧтениеXML.Значение);
ИначеЕсли ИмяТекущегоЭлемента = "name" Тогда
НоваяСтрока.Название = ЧтениеXML.Значение;
ИначеЕсли ИмяТекущегоЭлемента = "url" Тогда
НоваяСтрока.Ссылка = ЧтениеXML.Значение;
КонецЕсли;
КонецЕсли;
// 3. Обработка закрывающих тегов
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
Если ЧтениеXML.Имя = "offer" Тогда
НоваяСтрока = Неопределено;
КонецЕсли;
ИмяТекущегоЭлемента = "";
КонецЕсли;
КонецЦикла;
Исключение
Сообщить("Ошибка при чтении XML: " + ОписаниеОшибки());
КонецПопытки;
ЧтениеXML.Закрыть();
Важные нюансы при потоковом чтении:
ПолучитьАтрибут("ИмяАтрибута") прямо на узле ТипУзлаXML.НачалоЭлемента, не сдвигая курсор ручным вызовом ПрочитатьАтрибут().ЧтениеXML.Закрыть() в блоке обработки исключений или после завершения цикла, чтобы файл не оставался заблокированным в операционной системе.Если размер XML-документа небольшой (до нескольких десятков мегабайт), удобнее использовать объектную модель ДокументDOM. Это избавляет от необходимости вручную управлять состояниями парсера.
Разберем пример чтения через DOM:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
Построитель = Новый ПостроительDOM;
ДокументDOM = Построитель.Прочитать(ЧтениеXML);
ЧтениеXML.Закрыть();
// Получаем все узлы <offer>
СписокОфферов = ДокументDOM.ПолучитьЭлементыПоИмени("offer");
Для Каждого УзелOffer Из СписокОфферов Цикл
НоваяСтрока = ТаблицаТоваров.Добавить();
// Чтение атрибутов
Если УзелOffer.ЕстьАтрибуты() Тогда
АтрибутID = УзелOffer.Атрибуты.ПолучитьИменованныйЭлемент("id");
Если АтрибутID <> Неопределено Тогда
НоваяСтрока.ID = АтрибутID.ЗначениеУзла;
КонецЕсли;
КонецЕсли;
// Чтение дочерних элементов
Для Каждого ДочернийУзел Из УзелOffer.ДочерниеУзлы Цикл
Если ДочернийУзел.ТипУзла = ТипУзлаDOM.Элемент Тогда
Если ДочернийУзел.ИмяУзла = "price" Тогда
НоваяСтрока.Цена = Число(ДочернийУзел.ТекстовоеСодержимое);
ИначеЕсли ДочернийУзел.ИмяУзла = "name" Тогда
НоваяСтрока.Название = ДочернийУзел.ТекстовоеСодержимое;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Для регулярного обмена данными по строгой спецификации наилучшим решением является использование механизма XDTO. С помощью XSD-схемы в конфигурации создается пакет XDTO, после чего файл десериализуется в строго типизированные объекты 1С с помощью ФабрикаXDTO.ПрочитатьXML(). Это полностью исключает ручной парсинг тегов и проверку типов данных.