Ошибка преобразования данных XDTO: Текст XML содержит недопустимый символ

Публикация № 179688

Разработка - Практика программирования

Преобразование строкового значения к допустимому для XML.
Типовое, нетиповое, RegExp.

СПРАВКА:

Аббревиатура XDTO (англ. XML Data Transfer Objects). XDTO является механизмом объектного моделирования данных, описываемых с помощью схемы XML.
1С: Механизм XDTO: http://v8.1c.ru/overview/xdto.htm

Аббревиатура XML (англ. eXtensible Markup Language). Расширяемый язык разметки.
1С: XML-сериализация: http://v8.1c.ru/overview/Term_000000318.htm


ИСТОЧНИК ОШИБОК:

Ситуации, когда возможно появление этой проблемы:
- Обмен в распределенной базе данных.
- Обновление конфигурации 1С.
- Импорт из внешних источников в 1С.

В частности, проблема обнаружилась при разработке обработки:
1С:Системный Администратор (WSH&WMI): //infostart.ru/public/172189/
при считывании данных из реестра Windows.


ПРОБЛЕМА:

{Форма.Управляемая.Форма(1000)}: Ошибка при вызове метода контекста (ПолучитьСписокНаСервере)
по причине:
Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа.
по причине:
Ошибка преобразования данных XDTO:
Запись значения свойства 'v':
    форма: Элемент
    имя: {http://v8.1c.ru/8.2/uobjects}v
по причине:
Текст XML содержит недопустимый символ в позиции 5 :
?{?{?U


ВАРИАНТЫ РЕШЕНИЯ:

&НаСервере
Перем RegExp;

&НаКлиенте
Процедура Старт(Команда)
    
    АнализируемыйТекст = "§ | §§ "" | a86;a87;♥♦♣♠•`88;`75;`89;a92;b34;b35;a88;`58;`68;U97;R52;¶§`44;V16;↑↓→←W35;↔`50;`60; !
    | ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
    | АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя
    | ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω
    | 0123456789
    | ~`!@#$%^&*(){}[]_-=+\|/*:;.<>?,№ !  
    | ' | © | ® | µ | «» | ¤¢€£¥ | § | ½¼¾ | ¹²³ | °±×÷؃§ µ";
    
    ТекстРезультат = СтартНаСервере(АнализируемыйТекст);
    
    Сообщить(""+АнализируемыйТекст+"
    |"+ТекстРезультат);
    
КонецПроцедуры

&НаСервере
Функция СтартНаСервере(Знач Текст)
    
    RegEXP_Инициализация();
    
    Если RegExp = Неопределено Тогда
        Value = ИсключитьНеЧитаемыеСимволыИзСтроки(Текст);                 // Вариант "НЕТИПОВОЙ 1С".
    Иначе
        Value = ИсключитьНеЧитаемыеСимволыИзСтроки_REGEXP(Текст);    // Вариант "НЕТИПОВОЙ RegExp".
    КонецЕсли;
    //Value = ЗаменитьНедопустимыеСимволыXML(Value);                           // Вариант "ТИПОВОЙ 1С".
    
    Возврат Value;
    
КонецФункции


ВАРИАНТ РЕШЕНИЯ "ТИПОВОЙ 1С":

// Функция (ТИПОВАЯ 1С), оставляющая в строке только допустимые для XML символы и цифры.
//
// Возвращаемое значение:
//    Строка.
//
&НаСервере
Функция ЗаменитьНедопустимыеСимволыXML(Знач Текст, СимволЗамены = " ")
    
    Позиция = НайтиНедопустимыеСимволыXML(Текст);
    Пока Позиция > 0 Цикл
        ТекущийСимвол = Сред(Текст, Позиция, 1);
        Если КодСимвола(ТекущийСимвол) = 21 Тогда    // Параграф.
            Текст = СтрЗаменить(Текст, ТекущийСимвол, Символ(167));
            Позиция = НайтиНедопустимыеСимволыXML(Текст);
            Продолжить;
        КонецЕсли;
        Текст = СтрЗаменить(Текст, ТекущийСимвол, СимволЗамены);
        Позиция = НайтиНедопустимыеСимволыXML(Текст);
    КонецЦикла;
    
    Возврат Текст;
    
КонецФункции

Достоинства:
- Максимально возможное сохранение содержимого исходной строки.
Исключаются только недопустимые для XML символы.
- Самая быстрая функция.
Недостатки:
- В итоговой строке могут присутствовать нечитаемье символы ("аброказаябры").


ВАРИАНТ РЕШЕНИЯ "НЕТИПОВОЙ RegExp":

// Функция (RegExp), инициализация.
//
// Возвращаемое значение:
//    Строка.
//
&НаСервере
Функция RegEXP_Инициализация()

    // Читаемые символы.
    // Латиница = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    // Кирилица = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя";
    // Греческие = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω";
    // Цифры = "0123456789";
    // СпециальныеСимволы = "~`!@#$%^&*(){}[]_-=+\|/*:;.<>?,№«» ";
    ДвойнаяКавычка = "^""";
    ОдинарнаяКавычка = "^'";
    АпострофОбратный = "^" + Символ(769);    // КодСимвола 769. Обратный для символа на букве "Ё".
    АвторскоеПраво = "^©";                             // КодСимвола 169. "Copyright" - латинская буква C в окружности - авторское право.
    Зарезервировано = "^®";                           // КодСимвола 174. "Registered" - латинская буква R в окружности - товарный знак.
    ТоварныйЗнак = "^™";                               // Верхний  индекс ТМ.
    ШирокоеТире = "^—";                                // КодСимвола 8212.
    ДенежныеСимволы = "^¤^¢^€^£^¥";         // Денежная единица, Цент, Евро, Фунт стерлингов, Иена или юань.
    ДробныеСимволы = "^½^¼^¾";                // Дроби: 1/2, 1/4, 3/4.
    СимволыСтепени = "^¹^²^³";                    // Степени: 1, 2, 3.
    ПрочиеСимволы = "^°^±^×^÷^Ø^ƒ^µ^"+Символ(167);    // Градус, Плюс/Минус, Знак умножения, Знак деления, Диаметр, Знак функции, Микро, Параграф.
    
    ЧитаемыеСимволы = "[";
    ЧитаемыеСимволы = ЧитаемыеСимволы + "^a-z^A-Z^а-я^А-Я^0-9^Ё^ё^Α-Ω^α-ω";    // Латиница + Кирилица + Цифры + Греческие.
    ЧитаемыеСимволы = ЧитаемыеСимволы + "^~^`^!^@^#^\$^%^\^^&^\*^\(^\)^\{^\}^\[^\]^_^\-^=^\+^\\^\|^/^\*^:^;^\.^^\?^,^№^«^»^ ";    // СпециальныеСимволы.
    ЧитаемыеСимволы = ЧитаемыеСимволы + ДвойнаяКавычка + ОдинарнаяКавычка + АпострофОбратный + АвторскоеПраво + Зарезервировано + ТоварныйЗнак;
    ЧитаемыеСимволы = ЧитаемыеСимволы + ШирокоеТире + ДенежныеСимволы + ДробныеСимволы + СимволыСтепени + ПрочиеСимволы;
    ЧитаемыеСимволы = ЧитаемыеСимволы + "]";
    
    ПолучитьCOMОбъектREGEXP(ЧитаемыеСимволы, Ложь, Истина, Ложь);
    
КонецФункции

// СПАСИБО Evg-Lylyk: //infostart.ru/public/64222/
//
&НаСервере
Процедура ПолучитьCOMОбъектREGEXP(Шаблон, ИскатьДоПервогоСовпадения = Истина, МногоСтрок = Истина, ИгнорироватьРегистр = Истина)

    Если RegExp = Неопределено Тогда   // Нужна инициализация.
        Попытка
            RegExp = Новый COMОбъект("VBScript.RegExp");    // Создаем объект для работы с регулярными выражениями.
        Исключение
            RegExp = Неопределено;
            Возврат;
        КонецПопытки;
    КонецЕсли;

    // Заполняем данные.
    RegExp.MultiLine = МногоСтрок;                              // Истина — текст многострочный, Ложь — одна строка.
    RegExp.Global = НЕ ИскатьДоПервогоСовпадения;   // Истина — поиск по всей строке, Ложь — до первого совпадения.
    RegExp.IgnoreCase = ИгнорироватьРегистр;           // Истина — игнорировать регистр строки при поиске.
    RegExp.Pattern = Шаблон;                                     // Шаблон (регулярное выражение).
    
КонецПроцедуры

// Функция (НЕТИПОВАЯ REGEXP), оставляющая в строке только читаемые(допустимые) для XML символы и цифры.
//
// Возвращаемое значение:
//    Строка.
//
&НаСервере
Функция ИсключитьНеЧитаемыеСимволыИзСтроки_REGEXP(Знач АнализируемыйТекст, ЗаменятьСимволы = Истина, СимволЗамены = " ")
    
    Если НЕ RegExp.Test(АнализируемыйТекст) Тогда
        Возврат АнализируемыйТекст;
    КонецЕсли;
    
    // Формирование результирующей строки.
    ИтоговаяСтрока = АнализируемыйТекст;
    
    РезультатАнализаСтроки = RegExp.Execute(АнализируемыйТекст);
    
    Для Каждого Результат ИЗ РезультатАнализаСтроки Цикл
        ТекущийСимвол = Результат.Value;
        Если КодСимвола(ТекущийСимвол) = 21 Тогда    // Параграф.
            ИтоговаяСтрока = СтрЗаменить(ИтоговаяСтрока, ТекущийСимвол, Символ(167));
            Продолжить;
        КонецЕсли;
        Если ЗаменятьСимволы Тогда
            // Замена символа в строке.
            ИтоговаяСтрока = СтрЗаменить(ИтоговаяСтрока, ТекущийСимвол, СимволЗамены);
        Иначе
            // Сокращение строки на символ.
            ИтоговаяСтрока = СтрЗаменить(ИтоговаяСтрока, ТекущийСимвол, "");
        КонецЕсли;
    КонецЦикла;
    
    Возврат ИтоговаяСтрока;
    
КонецФункции


Достоинства:
- Остаются только визуализируемые, понятно читаемые допустимые для XML символы.
- Сопоставима по скорости с функцией ЗаменитьНедопустимыеСимволыXML (~ 0.5%).
Недостатки:
- Отдельные, возможно, необходимые символы могут исключаться.
(необходимо дополнить переменную ЧитаемыеСимволы).


ВАРИАНТ РЕШЕНИЯ "НЕТИПОВОЙ 1С":

// Функция (НЕТИПОВАЯ 1С), оставляющая в строке только читаемые(допустимые) для XML символы и цифры.
//
// Возвращаемое значение:
//    Строка.
//
&НаСервере
Функция ИсключитьНеЧитаемыеСимволыИзСтроки(Знач АнализируемыйТекст, ЗаменятьСимволы = Истина, СимволЗамены = " ")

    // Читаемые символы.
    Латиница = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    Кирилица = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя";
    Греческие = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω";
    Цифры = "0123456789";
    СпециальныеСимволы = "~`!@#$%^&*(){}[]_-=+\|/*:;.<>?,№«» ";
    ДвойнаяКавычка = """";
    ОдинарнаяКавычка = "'";
    АпострофОбратный = "L9;";           // КодСимвола 769. Обратный для символа на букве "Ё".
    АвторскоеПраво = "©";             // КодСимвола 169. "Copyright" - латинская буква C в окружности - авторское право.
    Зарезервировано = "®";           // КодСимвола 174. "Registered" - латинская буква R в окружности - товарный знак.
    ТоварныйЗнак = "™";               // Верхний  индекс ТМ.
    ШирокоеТире = "—";                // КодСимвола 8212.
    ДенежныеСимволы = "¤¢€£¥";  // Денежная единица, Цент, Евро, Фунт стерлингов, Иена или юань.
    ДробныеСимволы = "½¼¾";    // Дроби: 1/2, 1/4, 3/4.
    СимволыСтепени = "¹²³";         // Степени: 1, 2, 3
    ПрочиеСимволы = "°±×÷؃µ"+Символ(167);    // Градус, Плюс/Минус, Знак умножения, Знак деления, Диаметр, Знак функции, Микро, Параграф.
    
    ЧитаемыеСимволы = Латиница + Кирилица + Греческие + Цифры + СпециальныеСимволы + ШирокоеТире
    + ДвойнаяКавычка + ОдинарнаяКавычка + АпострофОбратный + АвторскоеПраво + Зарезервировано + ТоварныйЗнак
    + ДенежныеСимволы + ДробныеСимволы + СимволыСтепени + ПрочиеСимволы;
    
    // Формирование результирующей строки.
    ИтоговаяСтрока = "";
    Для НомерСимвола = 1 ПО СтрДлина(АнализируемыйТекст) Цикл
        ТекущийСимвол = Сред(АнализируемыйТекст, НомерСимвола, 1);
        // Заменяемые символы. Системный набор значений: "Символы":
        Если ТекущийСимвол = Символы.ВК ИЛИ ТекущийСимвол = Символы.ВТаб ИЛИ ТекущийСимвол = Символы.НПП
            ИЛИ ТекущийСимвол = Символы.ПС ИЛИ ТекущийСимвол = Символы.ПФ ИЛИ ТекущийСимвол = Символы.Таб Тогда
            ТекущийСимвол = СимволЗамены;
        КонецЕсли;
        Если КодСимвола(ТекущийСимвол) = 21 Тогда    // Параграф.
            ТекущийСимвол = Символ(167);
        КонецЕсли;
        Если Найти(ЧитаемыеСимволы, ТекущийСимвол) > 0 Тогда
            ИтоговаяСтрока = ИтоговаяСтрока + ТекущийСимвол;
        Иначе
            Если ЗаменятьСимволы Тогда
                ИтоговаяСтрока = ИтоговаяСтрока + СимволЗамены;
            Иначе
                // Сокращение строки на символ.
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    Возврат ИтоговаяСтрока;
    
КонецФункции

Достоинства:
- Остаются только визуализируемые, понятно читаемые допустимые для XML символы.
Недостатки:
- Отдельные, возможно, необходимые символы могут исключаться.
(необходимо дополнить переменную ЧитаемыеСимволы).
- Медленнее предыдущих на 30 %.

В целях недопущения искажений текста в ссылках на скачивание находится обработка с текстом функций.

МА! С уважением к сообществу МА!


Скачать файлы

Наименование Файл Версия Размер
Заменить недопустимые символы XML (epf)

.epf 8,37Kb
207
.epf 8,37Kb 207 Скачать

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Рейтинг 1-го уровня
11. OrsoBear 08.04.13 14:53 Сейчас в теме
У меня такие ошибки выпадали после импорта из 1С 7.7
Как правило, в процессе работы вываливались конкретные справочники и элементы, в которых ошибка.
И вываливалось при поиске или отборах. Если тупо колесиком до нужного пункта докрутить, то не вываливалось.
Открывал карточку, видел в поле среди букв какой-нибудь спецсимвол. Ручками исправлял, и удалял файл индексации.
После этого вопрос решался.
Тестирования и прочие стандартные методы нивкакую ошибки не находили.
StepByStep; +1 Ответить 1
26. adhocprog 1195 28.05.20 13:07 Сейчас в теме
Спасибо, помогло!
Воспользовался первым вариантом.
20. dima_kystym 27.09.14 14:56 Сейчас в теме
что то у меня не запускается эта обработка, под тонким вот такое сообщаение и все., а под толстым вообще не открывается. что может быть. Управление торговлей, редакция 11.1 (11.1.2.6)
§ | §§ " | ☺☻♥♦♣♠•◘○◙♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщ­ъыьэюя
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω
0123456789
~`!@#$%^&*(){}[]_-=+\|/*:;.<>?,№ !
' | © | ® | µ | «» | ¤¢€£¥ | § | ½¼¾ | ¹²³ | °±×÷؃§ µ
§ | §§ " | § ! ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщ­ъыьэюя ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω 0123456789 ~`!@#$%^&*(){}[]_-=+\|/*:;.<>?,№ ! ' | © | ® | µ | «» | ¤¢€£¥ | § | ½¼¾ | ¹²³ | °±×÷؃§ µ
24. kote 521 02.06.18 20:33 Сейчас в теме
17. kraynev-navi 483 18.12.13 17:04 Сейчас в теме
"Если звезды зажигают, значит это кому-нибудь нужно"
А что если недопустимые символы очень даже нужны? А мы их просто берем и удаляем...

Столкнулись с ситуацией при обмене. Строковый реквизит стандартным средством СоздатьЗаписьСообщения выдает ошибку из-за символов с кодом 01. В базе таковых 2000+ записей. Можно, конечно, все это просмотреть и принять решение по каждому. Но дальше же снова будут появляться такие документы. Нет уверенности, что удаление будет показано всем.

Проблемы можно было бы избежать, кодируй 1С значение банальным base64. Но нет, версия 8.2 лепит как есть.
Кто и как ходил путем "неудаления"?
16. kiruha 386 02.08.13 12:26 Сейчас в теме
Спасибо большое - буду проверять.
Знак ">" в xml знак тэга. Я так понял - не влияет при экспорте ?
27. tvssm 19.02.21 10:07 Сейчас в теме
Мне очень понравилась статья. Хороший, понятный код
19. nadinvital 19.05.14 08:28 Сейчас в теме
Спасибо,очень полезная штука, а главное актуальная
12. ArikiteSun 08.04.13 15:28 Сейчас в теме
Спабсибо! Полезная информация!
23. igo1 244 21.08.15 12:30 Сейчас в теме
25. SlaSla 24 17.12.18 08:25 Сейчас в теме
Подскажите по 7.7 есть аналогичный вариант?
22. a_E 27.11.14 16:07 Сейчас в теме
14. kiruha 386 01.08.13 10:08 Сейчас в теме
Вопрос - для вебсервисов, если передаются наименования - нужно ли их проверять на недопустимые символы ?
И как со знаками "<", ">" ?
Оставьте свое сообщение

См. также

Безопасная работа с транзакциями во встроенном языке Промо

Практика программирования v8 1cv8.cf Абонемент ($m)

Разбираемся с опасностями использования транзакций во встроенном языке 1С. Познаем ошибку "В данной транзакции уже происходили ошибки". Учимся защищаться от них.

1 стартмани

25.03.2019    38121    tormozit    54