При настройке регулярной выгрузки товаров и свойств из 1С на сайт (например, под управлением CMS «1С-Битрикс») разработчики часто сталкиваются с непредвиденным прерыванием процесса обмена. Одной из наиболее коварных ошибок является сбой валидации XDTO-пакета из-за несоответствия ограничению длины строки. В этой статье мы подробно разберем, почему возникает ошибка «Несоответствие фасету MaxLength = '80'», проанализируем её причины и рассмотрим три практических способа решения проблемы с примерами кода.
Давайте разберем архитектуру обмена данными. В основе большинства интеграций 1С с интернет-магазинами лежит стандарт CommerceML 2.x или 3.x. Передача информации происходит через XML-файлы, структура которых жестко регламентирована встроенными XML-схемами (XSD).
В этих схемах для каждого реквизита задается строгий тип данных с ограничениями (фасетами). В частности, для идентификаторов объектов часто используется глобальный тип Идентификатор80 или аналогичные ему типы со свойством maxLength = "80". Это означает, что любое значение, передаваемое в данный XML-атрибут, обязано быть длиной не более 80 символов.
В реальных базах данных (особенно в отраслевых конфигурациях, например, для ювелирной торговли, одежды или автозапчастей) идентификаторы свойств или характеристик могут формироваться динамически. Программа пытается транслитерировать длинное наименование свойства (например, состав камней в украшении: «10mm-nit-silikonovaya-pokrytaya-zhemchuzhnoj-ehmuls...») или собирает составной ключ из нескольких уникальных идентификаторов (GUID). Если длина итоговой строки превышает 80 символов, платформа 1С генерирует ошибку соответствия типов XDTO, и выгрузка полностью прекращается.
Ниже мы подробно рассмотрим три метода решения этой проблемы, начиная с простых «быстрых» правок кода и заканчивая надежными архитектурными подходами.
Самый простой и очевидный способ обойти ошибку — принудительно обрезать передаваемую в XML-атрибут строку до разрешенных 80 (или чуть меньше) символов непосредственно перед формированием XDTO-объекта.
Рассмотрим ситуацию на примере общего модуля Б_ОбменССайтомСервер. Посмотрим на строку кода, которая вызывает падение системы:
XDTOСправочник.ИдЗначения = XMLСтрока(ВыборкаЗначенийСвойств.ПереченьКамнейТранслит);
Для устранения ошибки нам необходимо применить встроенную функцию 1С Лев(), которая возвращает указанное количество символов с начала строки. Изменим код следующим образом:
// Ограничиваем длину передаваемой строки до безопасных 75 символов
ИдентификаторТранслит = ВыборкаЗначенийСвойств.ПереченьКамнейТранслит;
XDTOСправочник.ИдЗначения = XMLСтрока(Лев(ИдентификаторТранслит, 75));
Аналогично следует поступить со всеми остальными полями идентификаторов, где потенциально может возникнуть переполнение длины строки (например, Предложение.Ид при выгрузке торговых предложений с характеристиками):
// Пример обрезки составного идентификатора торгового предложения
XDTOПредложение.Ид = XMLСтрока(Лев(СтрокаИдентификатораПредложения, 80));
Важное предупреждение о рисках коллизий: Этот метод прост в реализации, однако таит в себе серьезную опасность. Если в вашей базе есть два похожих свойства, у которых первые 75 символов транслита совпадают (например, разница кроется лишь в самом конце длинного описания), после обрезки они получат абсолютно одинаковые идентификаторы. При загрузке на сайт это приведет к тому, что одно свойство перезапишет другое, либо CMS выдаст ошибку уникальности данных.
Если вы хотите избежать риска коллизий из-за обрезки уникальных ключей, правильным решением будет расширить лимит длины строки в самой схеме XSD, которую использует модуль обмена 1С.
В современных типовых конфигурациях (например, «Управление торговлей 11», «Управление нашей фирмой» или «Комплексная автоматизация») схема XML-обмена хранится непосредственно в метаданных. Давайте разберем по шагам процесс изменения этой схемы:
Б_ОбменССайтом или ОбменССайтом).ИдентификаторГлобальныйТип или найдите ограничение типа, вызывающее ошибку (в нашем случае ищем maxLength value="80").80 на более просторное, например, 254:
<xsd:restriction base="xsd:string">
<xsd:maxLength value="254"/>
</xsd:restriction>
Обратите внимание на ограничения стороны CMS: Увеличение лимита в 1С успешно решит проблему формирования XML-файла. Однако убедитесь, что база данных вашего сайта готова принимать такие длинные идентификаторы. Если в таблицах интернет-магазина под хранение внешних кодов отведено поле типа VARCHAR(80), сайт либо выдаст ошибку импорта, либо незаметно «обрежет» строку при записи, что нарушит последующую синхронизацию.
Как быть, если обрезать строки нельзя из-за риска дублей, а менять схему XSD нежелательно из-за будущих обновлений конфигурации? В профессиональной разработке для решения этой проблемы применяется алгоритм хэширования.
Вместо того чтобы передавать на сайт длинный нечитаемый транслит описания, мы можем сгенерировать из этого описания уникальный хэш-код по алгоритму MD5. Хэш MD5 от строки абсолютно любой длины всегда имеет фиксированный размер — ровно 32 символа (состоит из латинских букв и цифр). Это идеально вписывается в любые ограничения стандартов CommerceML (и 40, и 80 символов).
При этом гарантируется математическая уникальность: даже при минимальном отличии в исходных описаниях товаров мы получим два совершенно разных хэш-кода. Рассмотрим, как реализовать этот подход в коде 1С с использованием встроенного объекта ХешированиеДанных:
// Функция для генерации уникального MD5-идентификатора из исходного текста
Функция ПолучитьMD5ХэшСтроки(ИсходнаяСтрока) Экспорт
Хеш = Новый ХешированиеДанных(ХешФункция.MD5);
Хеш.Добавить(ИсходнаяСтрока);
СтрокаХеша = СтрЗаменить(Строка(Хеш.ХешСумма), " ", "");
Возврат НРег(СтрокаХеша); // Возвращаем хэш в нижнем регистре
КонецФункции
Теперь мы можем применить эту функцию в модуле обмена при заполнении реквизита XDTO:
// Заменяем длинный транслит на надежный и компактный MD5-хэш
ТекстКамней = ВыборкаЗначенийСвойств.ПереченьКамнейТранслит;
XDTOСправочник.ИдЗначения = XMLСтрока(ПолучитьMD5ХэшСтроки(ТекстКамней));
Использование хэширования — наиболее стабильный, безопасный и отказоустойчивый метод интеграции, исключающий любые коллизии и падения валидатора XML.
Если вы вносите правки непосредственно в общий модуль Б_ОбменССайтомСервер, то при первом же обновлении модуля обмена или конфигурации 1С ваши изменения будут затёрты. Чтобы избежать этого, настоятельно рекомендуется выполнять доработку через механизм расширений конфигурации.
Создайте новое расширение, добавьте в него общий модуль Б_ОбменССайтомСервер и перехватите необходимую процедуру (например, отвечающую за выгрузку свойств товаров) с помощью аннотации &Вместо или &После, реализуя в ней логику хэширования или безопасной обрезки строк.