Как исправить ошибку схемы при загрузке XML через XMLParser в 1С 7.7?

Программист 1С v7.7
← На главную

При работе в 1С 7.7 с внешними XML-файлами (например, при загрузке Электронных Счетов-Фактур — ЭСЧФ) разработчики часто сталкиваются с ошибкой валидации: Attribute schemaLocation has an invalid value according to the DTD/Schema. Проблема возникает из-за того, что стандартная компонента v7plus.dll (объект AddIn.XMLParser) крайне чувствительна к синтаксису системных атрибутов XML. В частности, атрибут xsi:schemaLocation по стандартам W3C должен содержать два значения через пробел: пространство имен и путь к файлу схемы. Если в файле указано только одно значение или путь недоступен, парсер выдает ошибку и прекращает загрузку.

Рассмотрим подробнее, как обойти это ограничение и успешно прочитать данные, даже если структура заголовка XML не соответствует строгим правилам компоненты.

Причина возникновения ошибки и диагностика

Проанализируем ситуацию на примере типичного заголовка проблемного файла:


<issuance xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xmlns="http://www.w3schools.com" 
          xsi:schemaLocation="http://www.w3schools.com" 
          sender="192950049">

Выясним причину: в данном примере атрибут xsi:schemaLocation содержит только http://www.w3schools.com. Компонента v7plus.dll, базирующаяся на старых версиях MSXML, ожидает увидеть здесь пару: «ПространствоИмен СсылкаНаФайл.xsd». Не найдя второго аргумента, парсер выбрасывает исключение. Попытки изменить свойство РазрешатьВнешниеСсылки в объекте XMLParser часто не приносят результата, так как это свойство может игнорироваться при первичном разборе структуры документа.

Способ 1: Предварительная текстовая очистка XML-файла

Если вы хотите продолжать использовать привычный v7plus.dll, самым эффективным и быстрым решением будет предварительное удаление проблемного атрибута из текста файла перед его загрузкой в парсер. Разберем этот алгоритм по шагам.

Проанализируем пример функции, которая считывает файл как текст, удаляет объявление схемы и передает чистый XML в объект XMLParser:


// Создаем объект для работы с текстом
ТекстФайла = СоздатьОбъект("Текст");
ТекстФайла.Открыть(ИмяФайлаXML);

// Преобразуем весь текст в одну строку для удобства замены
ПолныйТекст = "";
Для Ном = 1 По ТекстФайла.КоличествоСтрок() Цикл
    ПолныйТекст = ПолныйТекст + ТекстФайла.ПолучитьСтроку(Ном) + РазделительСтрок;
КонецЦикла;

// Выполняем замену проблемного атрибута на пустую строку
// Можно искать конкретное значение или использовать более универсальный подход
ПроблемнаяСтрока = "xsi:schemaLocation=""http://www.w3schools.com""";
ПолныйТекст = СтрЗаменить(ПолныйТекст, ПроблемнаяСтрока, "xsi:schemaLocation=""""");

// Теперь загружаем очищенный текст
XML = СоздатьОбъект("AddIn.XMLParser");
XML_Документ = XML.СоздатьДокумент();
XML_Документ.ЗагрузитьИзСтроки(ПолныйТекст);

Если XML_Документ.КоличествоУзлов() = 0 Тогда
    Сообщить("Ошибка загрузки после очистки!");
КонецЕсли;

Этот метод хорош тем, что он гарантированно устраняет причину ошибки, не требуя установки дополнительных библиотек. Однако стоит помнить, что при работе с очень большими файлами (более 10-20 Мб) операции со строками в 1С 7.7 могут замедлять работу системы.

Способ 2: Использование MSXML2.DOMDocument (COM-объект)

Более профессиональным и гибким способом является отказ от v7plus.dll в пользу прямого обращения к библиотекам Windows через COMОбъект. Это позволяет тонко настроить параметры валидации. Рассмотрим, как реализовать загрузку через MSXML2.DOMDocument.

Посмотрим на пример кода, где мы принудительно отключаем проверку схем:


// Рекомендуется использовать версию 6.0 как наиболее стабильную и быструю
xmlDoc = СоздатьОбъект("Msxml2.DOMDocument.6.0");

// Отключаем проверку на соответствие схеме (валидацию)
xmlDoc.validateOnParse = 0;

// Запрещаем парсеру пытаться скачивать внешние файлы схем из интернета
xmlDoc.resolveExternals = 0;

// Асинхронная загрузка должна быть выключена для корректной работы в коде
xmlDoc.async = 0;

Если xmlDoc.load(ИмяФайлаXML) = 0 Тогда
    // Если загрузка не удалась, анализируем ошибку
    Ош = xmlDoc.parseError;
    Сообщить("Ошибка в строке " + Ош.line + ": " + Ош.reason);
Иначе
    // Работаем с документом
    Корень = xmlDoc.documentElement;
    Сообщить("Файл успешно загружен. Корневой узел: " + Корень.nodeName);
КонецЕсли;

Разберем важные настройки этого объекта:

Работа с пространствами имен (Namespaces)

При использовании MSXML2.DOMDocument для файлов ЭСЧФ часто возникает сложность с поиском узлов (метод selectSingleNode возвращает пустоту), так как в файле определено пространство имен (xmlns). Чтобы решить эту проблему, проанализируем следующий прием:


// Установка соответствия префиксов для XPath
xmlDoc.setProperty("SelectionNamespaces", "xmlns:ns='http://www.w3schools.com'");

// Теперь поиск узла будет выглядеть так:
УзелОбщие = xmlDoc.selectSingleNode("//ns:general");
Если ПустоеЗначение(УзелОбщие) = 0 Тогда
    Сообщить("Номер документа: " + УзелОбщие.selectSingleNode("ns:number").text);
КонецЕсли;

Сравнение подходов и выводы

Выясним, какой метод лучше выбрать для вашей задачи. Если ваша конфигурация жестко завязана на методы v7plus.dll и вы не хотите переписывать логику обхода узлов, используйте Способ 1 (текстовая замена). Это "костыль", но он работает быстро и надежно на небольших файлах.

Если же вы строите надежную систему обмена данными (особенно с порталом ЭСЧФ), мы рекомендуем Способ 2. Использование MSXML2.DOMDocument.6.0 снимает ограничения на размер файла (в современных ОС лимит практически неограничен объемом ОЗУ) и предоставляет гораздо больше инструментов для обработки ошибок. Проблемы с лимитом в 500 Кб, которые упоминались в старых форумах, давно не актуальны для версий MSXML 4.0 и выше.

Важный момент для пользователей из Беларуси: Файлы ЭСЧФ с официального портала могут содержать специфические кодировки. При использовании DOMDocument убедитесь, что в системе установлены последние обновления безопасности Windows, так как библиотеки парсинга обновляются вместе с ними.

← На главную