При работе в 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 часто не приносят результата, так как это свойство может игнорироваться при первичном разборе структуры документа.
Если вы хотите продолжать использовать привычный 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 могут замедлять работу системы.
Более профессиональным и гибким способом является отказ от 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);
КонецЕсли;
Разберем важные настройки этого объекта:
XPath для извлечения данных из DOM-дерева.При использовании 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, так как библиотеки парсинга обновляются вместе с ними.