Skip to content

Commit 70e0bf2

Browse files
authored
Merge pull request #1349 from Mr-Rm/fix/1332
исправления функций работы с XML, fix #1332
2 parents 99d3376 + 1044231 commit 70e0bf2

File tree

2 files changed

+235
-10
lines changed

2 files changed

+235
-10
lines changed

src/ScriptEngine.HostedScript/Library/Xml/XmlGlobalFunctions.cs

Lines changed: 107 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This Source Code Form is subject to the terms of the
77
using ScriptEngine.Machine;
88
using ScriptEngine.Machine.Contexts;
99
using System;
10+
using System.Collections.Generic;
1011
using System.Xml;
1112

1213
using ScriptEngine.HostedScript.Library.Binary;
@@ -16,11 +17,44 @@ namespace ScriptEngine.HostedScript.Library.Xml
1617
[GlobalContext(Category="Функции работы с XML")]
1718
public class XmlGlobalFunctions : GlobalContextBase<XmlGlobalFunctions>
1819
{
20+
private static readonly Dictionary<TypeDescriptor, EnumerationContext> _allowedEnums
21+
= new Dictionary<TypeDescriptor, EnumerationContext>();
22+
23+
private static readonly TypeDescriptor _binaryDataTypeDescriptor;
24+
private static readonly TypeDescriptor _nullTypeDescriptor;
25+
private static readonly TypeDescriptor _guidTypeDescriptor;
26+
27+
static XmlGlobalFunctions()
28+
{
29+
_binaryDataTypeDescriptor = TypeManager.GetTypeByFrameworkType(typeof(BinaryDataContext));
30+
_nullTypeDescriptor = TypeManager.GetTypeByName("NULL");
31+
_guidTypeDescriptor = TypeManager.GetTypeByFrameworkType(typeof(GuidWrapper));
32+
33+
foreach (var e in new []{typeof(AllowedSignEnum), typeof(AllowedLengthEnum), typeof(DateFractionsEnum) })
34+
{
35+
_allowedEnums.Add(TypeManager.GetTypeByFrameworkType(e), GlobalsManager.GetSimpleEnum(e));
36+
}
37+
}
38+
39+
/// <summary>
40+
/// Получает XML представление значения для помещения в текст элемента или значение атрибута XML.
41+
/// </summary>
42+
/// <param name="value">
43+
/// Значение. Допустимые типы: Булево, Число, Строка, Дата, УникальныйИдентификатор, ДвоичныеДанные,
44+
/// Неопределено, Null, а также значения перечислений ДопустимыйЗнак, ДопустимаяДлина, ЧастиДаты
45+
/// </param>
46+
/// <returns>
47+
/// Строковое представление значения. Для двоичных данных - строка в формате Вase64.
48+
/// При недопустимом типе значения выбрасывается исключение
49+
/// </returns>
50+
///
1951
[ContextMethod("XMLСтрока", "XMLString")]
2052
public string XMLString(IValue value)
2153
{
2254
switch(value.DataType)
2355
{
56+
case DataType.String:
57+
return value.AsString();
2458
case DataType.Undefined:
2559
return "";
2660
case DataType.Boolean:
@@ -29,23 +63,53 @@ public string XMLString(IValue value)
2963
return XmlConvert.ToString(value.AsDate(), XmlDateTimeSerializationMode.Unspecified);
3064
case DataType.Number:
3165
return XmlConvert.ToString(value.AsNumber());
66+
67+
case DataType.Enumeration:
68+
if (_allowedEnums.TryGetValue(value.SystemType, out var enumeration))
69+
{
70+
return value.AsString();
71+
}
72+
break;
73+
3274
default:
33-
34-
if(value.SystemType.Equals(TypeManager.GetTypeByFrameworkType(typeof(BinaryDataContext))))
75+
if(value.SystemType.Equals(_binaryDataTypeDescriptor))
3576
{
3677
var bdc = value.GetRawValue() as BinaryDataContext;
3778
System.Diagnostics.Debug.Assert(bdc != null);
3879

3980
return Convert.ToBase64String(bdc.Buffer, Base64FormattingOptions.InsertLineBreaks);
4081
}
41-
else
82+
else if (value.SystemType.Equals(_guidTypeDescriptor))
4283
{
43-
return value.GetRawValue().AsString();
84+
return value.AsString();;
4485
}
45-
86+
else if (value.SystemType.Equals(_nullTypeDescriptor))
87+
{
88+
return "";
89+
}
90+
break;
4691
}
92+
93+
throw RuntimeException.InvalidArgumentValue();
4794
}
4895

96+
/// <summary>
97+
/// Выполняет преобразование из строки, полученной из текста элемента или значения атрибута XML,
98+
/// в значение в соответствии с указанным типом. Действие, обратное действию метода XMLСтрока
99+
/// </summary>
100+
/// <param name="givenType">
101+
/// Тип, значение которого надо получить при преобразовании из строкового представления XML.
102+
/// Допустимые типы: Булево, Число, Строка, Дата, УникальныйИдентификатор, ДвоичныеДанные,
103+
/// Неопределено, Null, перечисления ДопустимыйЗнак, ДопустимаяДлина, ЧастиДаты
104+
/// </param>
105+
/// <param name="presentation">
106+
/// Строка, содержащая строковое представление значения соответствующего типа
107+
/// </param>
108+
/// <returns>
109+
/// Значение заданного типа.
110+
/// При недопустимом типе или неправильном строковом представлении выбрасывается исключение
111+
/// </returns>
112+
///
49113
[ContextMethod("XMLЗначение", "XMLValue")]
50114
public IValue XMLValue(IValue givenType, string presentation)
51115
{
@@ -67,20 +131,53 @@ public IValue XMLValue(IValue givenType, string presentation)
67131
{
68132
return ValueFactory.Create(presentation);
69133
}
70-
else if (typeValue.Equals(TypeDescriptor.FromDataType(DataType.Undefined)) && presentation == "")
134+
else if (typeValue.Equals(TypeDescriptor.FromDataType(DataType.Undefined)))
71135
{
72-
return ValueFactory.Create();
136+
if ( presentation.Trim() == "")
137+
return ValueFactory.Create();
138+
else
139+
{
140+
throw RuntimeException.InvalidNthArgumentValue(2);
141+
}
73142
}
74-
else if (typeValue.Equals(TypeManager.GetTypeByFrameworkType(typeof(BinaryDataContext))))
143+
else if (typeValue.Equals(_nullTypeDescriptor))
144+
{
145+
if (presentation.Trim() == "")
146+
return ValueFactory.CreateNullValue();
147+
else
148+
{
149+
throw RuntimeException.InvalidNthArgumentValue(2);
150+
}
151+
}
152+
else if (typeValue.Equals(_binaryDataTypeDescriptor))
75153
{
76154
byte[] bytes = Convert.FromBase64String(presentation);
77155
return new BinaryDataContext(bytes);
78156
}
79-
else
157+
else if (typeValue.Equals(_guidTypeDescriptor))
158+
{
159+
try
160+
{
161+
return new GuidWrapper(presentation);
162+
}
163+
catch
164+
{
165+
throw RuntimeException.InvalidNthArgumentValue(2);
166+
}
167+
}
168+
else if (_allowedEnums.TryGetValue(typeValue, out var enumerationContext))
80169
{
81-
throw RuntimeException.InvalidArgumentValue();
170+
try
171+
{
172+
return enumerationContext[presentation];
173+
}
174+
catch (RuntimeException)
175+
{
176+
throw RuntimeException.InvalidNthArgumentValue(2);
177+
}
82178
}
83179

180+
throw RuntimeException.InvalidNthArgumentValue(1);
84181
}
85182

86183
public static IAttachableContext CreateInstance()

tests/global-funcs.os

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@
4343
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаДвоичныеДанные");
4444
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаСтрокаИзПеременной");
4545
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеДвоичныеДанные");
46+
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаNULL");
47+
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаGUID");
48+
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаПеречисления");
49+
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаНедопустимыеТипы");
50+
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеNULL");
51+
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеGUID");
52+
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеПеречисления");
53+
ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеНедопустимыеТипы");
54+
4655
ВсеТесты.Добавить("ТестДолжен_ПроверитьЗаписьВBase64");
4756
ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтениеИзBase64");
4857

@@ -374,6 +383,125 @@
374383

375384
КонецПроцедуры
376385

386+
Процедура ТестДолжен_Проверить_XMLСтрокаNULL() Экспорт
387+
388+
юТест.ПроверитьРавенство("", XMLСтрока(NULL));
389+
390+
КонецПроцедуры
391+
392+
Процедура ТестДолжен_Проверить_XMLЗначениеNULL() Экспорт
393+
394+
Тип = Тип("NULL");
395+
396+
Значение = XMLЗначение(Тип, " ");
397+
юТест.ПроверитьТип(Значение, Тип);
398+
399+
БылоИсключение = Ложь;
400+
Попытка
401+
Значение = XMLЗначение(Тип, "NULL");
402+
Исключение
403+
БылоИсключение = Истина;
404+
КонецПопытки;
405+
406+
юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом представлении NULL в XMLЗначение");
407+
408+
КонецПроцедуры
409+
410+
411+
Процедура ТестДолжен_Проверить_XMLСтрокаGUID() Экспорт
412+
413+
Строка = "ae1d6d78-c3d5-4ef0-b096-2fb4f8e4717e";
414+
GUID = Новый УникальныйИдентификатор(Строка);
415+
юТест.ПроверитьРавенство(Строка, XMLСтрока(GUID));
416+
417+
КонецПроцедуры
418+
419+
Процедура ТестДолжен_Проверить_XMLЗначениеGUID() Экспорт
420+
421+
Тип = Тип("УникальныйИдентификатор");
422+
Строка = "ae1d6d78-c3d5-4ef0-b096-2fb4f8e4717e";
423+
424+
Значение = XMLЗначение(Тип, Строка);
425+
юТест.ПроверитьТип(Значение, Тип);
426+
юТест.ПроверитьРавенство(Строка(Значение), Строка);
427+
428+
БылоИсключение = Ложь;
429+
Попытка
430+
Значение = XMLЗначение(Тип, "-a-e1d6d78c3d54ef0b0962fb4f8e4717e");
431+
Исключение
432+
БылоИсключение = Истина;
433+
КонецПопытки;
434+
435+
юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом представлении GUID в XMLЗначение");
436+
437+
КонецПроцедуры
438+
439+
440+
Процедура ТестДолжен_Проверить_XMLСтрокаПеречисления() Экспорт
441+
442+
Перечисление = ДопустимыйЗнак.Неотрицательный;
443+
юТест.ПроверитьРавенство("Неотрицательный", XMLСтрока(Перечисление)); // нужно "Nonnegative"
444+
445+
КонецПроцедуры
446+
447+
Процедура ТестДолжен_Проверить_XMLЗначениеПеречисления() Экспорт
448+
Тип = Тип("ДопустимаяДлина");
449+
Значение = XMLЗначение(Тип, "Fixed");
450+
451+
юТест.ПроверитьТип(Значение, Тип);
452+
юТест.ПроверитьРавенство(Значение, ДопустимаяДлина.Фиксированная);
453+
454+
КонецПроцедуры
455+
456+
457+
Процедура ТестДолжен_Проверить_XMLСтрокаНедопустимыеТипы() Экспорт
458+
459+
Массив = Новый Массив(1);
460+
БылоИсключение = Ложь;
461+
Попытка
462+
Стр = XMLСтрока(Массив);
463+
Исключение
464+
БылоИсключение = Истина;
465+
КонецПопытки;
466+
467+
юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом типе в XMLСтрока");
468+
469+
Перечисление = НаправлениеСортировки.Возр;
470+
БылоИсключение = Ложь;
471+
Попытка
472+
Стр = XMLСтрока(Перечисление);
473+
Исключение
474+
БылоИсключение = Истина;
475+
КонецПопытки;
476+
477+
юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом перечислении в XMLСтрока");
478+
479+
КонецПроцедуры
480+
481+
Процедура ТестДолжен_Проверить_XMLЗначениеНедопустимыеТипы() Экспорт
482+
483+
БылоИсключение = Ложь;
484+
Попытка
485+
Значение = XMLЗначение(Тип("НаправлениеСортировки"), "Возр");
486+
Исключение
487+
БылоИсключение = Истина;
488+
КонецПопытки;
489+
490+
юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом типе в XMLСтрока");
491+
492+
Перечисление = НаправлениеСортировки.Возр;
493+
БылоИсключение = Ложь;
494+
Попытка
495+
Значение = XMLЗначение(Тип("ДопустимаяДлина"), "Возр");
496+
Исключение
497+
БылоИсключение = Истина;
498+
КонецПопытки;
499+
500+
юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом значении в XMLСтрока");
501+
502+
КонецПроцедуры
503+
504+
377505
Функция ПрочитатьФайлСкрипта(Знач Файл)
378506

379507
Ч = Новый ЧтениеТекста(Файл);

0 commit comments

Comments
 (0)