gifts2017

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

Опубликовал Андрей М. (StepByStep) в раздел Программирование - Практика программирования

Преобразование строкового значения к допустимому для 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): http://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: http://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
28.03.13
159
.epf 8,37Kb 159 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

2. Андрей М. (StepByStep) 27.03.13 10:53
(1) CagoBHuK,
На мой взгляд - воспользоваться типовым вариантом предложенным в статье.
3. Яков Коган (Yashazz) 27.03.13 12:34
(1) Соглашусь. Для больших объёмов регулярные выражения быстрее будут, чем посимвольный обход.
4. Данила Елистратов (CagoBHuK) 27.03.13 12:46
(2) Видимо, Вы не работали с большими объемами данных. При файлах более 100 мегабайт Ваша обработка встанет колом.
5. Андрей М. (StepByStep) 27.03.13 13:04
(4) CagoBHuK,
Да. Если база большая и "шерстить" все - это медленно, но верно.
Издержки посимвольного обхода.
6. Данила Елистратов (CagoBHuK) 27.03.13 13:05
(5) А с каких пор регулярные выражения - это неверно?
7. Андрей М. (StepByStep) 27.03.13 13:08
(6) CagoBHuK,
Регулярные выражения не рассматривал, надо попробовать.
8. Андрей М. (StepByStep) 27.03.13 14:56
(6) CagoBHuK,
СПАСИБО. ТОЖЕ ВЕРНО!
9. Данила Елистратов (CagoBHuK) 27.03.13 15:00
(8) Не за что. Приятно, когда люди прислушиваются к твоим словам.
10. Андрей М. (StepByStep) 28.03.13 09:55
(9) CagoBHuK,
Еще раз спасибо. Добавил функцию на RegExp.
11. Alex Steiner (OrsoBear) 08.04.13 14:53
У меня такие ошибки выпадали после импорта из 1С 7.7
Как правило, в процессе работы вываливались конкретные справочники и элементы, в которых ошибка.
И вываливалось при поиске или отборах. Если тупо колесиком до нужного пункта докрутить, то не вываливалось.
Открывал карточку, видел в поле среди букв какой-нибудь спецсимвол. Ручками исправлял, и удалял файл индексации.
После этого вопрос решался.
Тестирования и прочие стандартные методы нивкакую ошибки не находили.
StepByStep; +1 Ответить 1
12. Arikite (ArikiteSun) 08.04.13 15:28
Спабсибо! Полезная информация!
13. Андрей М. (StepByStep) 09.04.13 20:04
(11) OrsoBear,
СПАСИБО.
Да, в семерке при экспорте-импорте из ТиС в Бухгалтерию неоднократно встречалась проблема с недопустимыми символами XML. И тоже ручками исправлял.
На 8-ке решил, что надо по-другому ...
14. kiruha Дронов (kiruha) 01.08.13 10:08
Вопрос - для вебсервисов, если передаются наименования - нужно ли их проверять на недопустимые символы ?
И как со знаками "<", ">" ?
15. Андрей М. (StepByStep) 02.08.13 10:07
(14) kiruha,

По опыту работы с 1С 7.7, а теперь и 1С 8.Х, я пришел к такому выводу:
Все, что приходит из внешнего источника данных в рабочую базу обязательно должно проходить проверку.

В данном случае речь идет о чистке строковых значений для реквизитов 1С.

Символы "<" (меньше) или ">" (больше) - в строковом реквизите это вполне допустимый символ, если это не запрещено в конкретной конфигурации.
16. kiruha Дронов (kiruha) 02.08.13 12:26
Спасибо большое - буду проверять.
Знак ">" в xml знак тэга. Я так понял - не влияет при экспорте ?
17. С К (kraynev-navi) 18.12.13 17:04
"Если звезды зажигают, значит это кому-нибудь нужно"
А что если недопустимые символы очень даже нужны? А мы их просто берем и удаляем...

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

Проблемы можно было бы избежать, кодируй 1С значение банальным base64. Но нет, версия 8.2 лепит как есть.
Кто и как ходил путем "неудаления"?
18. С К (kraynev-navi) 18.12.13 17:08
(16) kiruha, вроде как нормально конвертирует, ошибок нет
Данные реквизита:
выапвыапвы<st yle>[]{}

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