Skip to content

Commit 9a518c3

Browse files
authored
Fixes #2449 Allow more permissive Xml serialization and deserialization (#2450)
1 parent d434107 commit 9a518c3

File tree

11 files changed

+82
-18
lines changed

11 files changed

+82
-18
lines changed

src/OSPSuite.Core/Serialization/Exchange/SimulationPersistor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ public void Save(SimulationTransfer simulationTransfer, string fileName)
3232
{
3333
var serializer = _xmlSerializerRepository.SerializerFor(simulationTransfer);
3434
var element = serializer.Serialize(simulationTransfer, serializationContext);
35-
element.Save(fileName);
35+
36+
element.PermissiveSave(fileName);
3637
}
3738
}
3839

src/OSPSuite.Core/Serialization/XElementExtensions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,10 @@ public static int GetPKMLVersion(this XElement element)
1515

1616
return versionString.ConvertedTo<int>();
1717
}
18+
19+
public static void PermissiveSave(this XElement element, string fileName)
20+
{
21+
XElementSerializer.PermissiveSave(element, fileName);
22+
}
1823
}
1924
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.IO;
2+
using System.Xml;
3+
using System.Xml.Linq;
4+
5+
namespace OSPSuite.Core.Serialization
6+
{
7+
public static class XElementSerializer
8+
{
9+
/// <summary>
10+
/// Saves XElement to <paramref name="fileName"/> allowing illegal characters to be escaped and saved
11+
/// </summary>
12+
public static void PermissiveSave(XElement element, string fileName)
13+
{
14+
using (var xmlWriter = XmlWriter.Create(fileName, new XmlWriterSettings
15+
{
16+
CheckCharacters = false,
17+
Indent = true
18+
}))
19+
{
20+
element.Save(xmlWriter);
21+
}
22+
}
23+
24+
public static XElement PermissiveLoad(Stream stream)
25+
{
26+
using (var xmlReader = XmlReader.Create(stream, new XmlReaderSettings { CheckCharacters = false }))
27+
{
28+
return XElement.Load(xmlReader);
29+
}
30+
}
31+
32+
public static XElement PermissiveLoad(string fileName)
33+
{
34+
using (var xmlReader = XmlReader.Create(fileName, new XmlReaderSettings { CheckCharacters = false }))
35+
{
36+
return XElement.Load(xmlReader);
37+
}
38+
}
39+
}
40+
}

src/OSPSuite.Core/Serialization/Xml/AbstractPersistor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public virtual void Save(T objectToSerialize, string fileName)
2727
{
2828
var serializer = _serializerRepository.SerializerFor(objectToSerialize);
2929
var xel = serializer.Serialize(objectToSerialize, serializationContext);
30-
xel.Save(fileName);
30+
xel.PermissiveSave(fileName);
3131
}
3232
}
3333

@@ -36,7 +36,7 @@ public virtual void Load(T objectToLoad, string fileName)
3636
using (var serializationContext = SerializationTransaction.Create(_container))
3737
{
3838
var serializer = _serializerRepository.SerializerFor(objectToLoad);
39-
var element = XElement.Load(fileName);
39+
var element = XElementSerializer.PermissiveLoad(fileName);
4040
serializer.Deserialize(objectToLoad, element, serializationContext);
4141
}
4242
}

src/OSPSuite.Core/Serialization/Xml/DataPersistor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ public virtual void Save<T>(T obj, string fileName)
4343
using (var serializationContext = SerializationTransaction.Create(_container))
4444
{
4545
var xel = Serialize(obj, serializationContext);
46-
xel.Save(fileName);
46+
xel.PermissiveSave(fileName);
4747
}
4848
}
4949

5050
public virtual T Load<T>(string fileName, IDimensionFactory dimensionFactory = null, IEnumerable<DataRepository> dataRepositories = null)
5151
{
5252
using (var serializationContext = SerializationTransaction.Create(_container, dimensionFactory, dataRepositories: dataRepositories))
5353
{
54-
var xel = XElement.Load(fileName);
54+
var xel = XElementSerializer.PermissiveLoad(fileName);
5555
return Deserialize<T>(xel, serializationContext);
5656
}
5757
}

src/OSPSuite.Core/Serialization/Xml/GroupRepositoryPersistor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public override void Load(IGroupRepository groupRepository, string fileName)
2323
using (var serializationContext = SerializationTransaction.Create(_container, withIdRepository: new WithIdRepository()))
2424
{
2525
var serializer = _serializerRepository.SerializerFor(groupRepository);
26-
var element = XElement.Load(fileName);
26+
var element = XElementSerializer.PermissiveLoad(fileName);
2727
serializer.Deserialize(groupRepository, element, serializationContext);
2828
}
2929

src/OSPSuite.Core/Serialization/Xml/PKMLPersistor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void SaveToPKML<T>(T entityToSerialize, string fileName)
6262
{
6363
var xElement = serializeModelPart(entityToSerialize, serializationContext);
6464
xElement.AddAttribute(Constants.Serialization.Attribute.VERSION, Constants.PKML_VERSION.ToString());
65-
xElement.Save(fileName);
65+
xElement.PermissiveSave(fileName);
6666
}
6767
}
6868

@@ -81,7 +81,7 @@ public T Load<T>(string pkmlFileFullPath,
8181
withIdRepository ?? new WithIdRepository(),
8282
cloneManagerForModel ?? _cloneManagerForModel))
8383
{
84-
var element = XElement.Load(pkmlFileFullPath);
84+
var element = XElementSerializer.PermissiveLoad(pkmlFileFullPath);
8585
version = element.GetPKMLVersion();
8686

8787
convertXml(element, version);

src/OSPSuite.Core/Serialization/Xml/PKParameterRepositoryLoader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public void Load(IPKParameterRepository pkParameterMetaDataRepository, string fi
3232
using (var serializationContext = SerializationTransaction.Create(_container, _dimensionFactory))
3333
{
3434
var serializer = _modelingXmlSerializerRepository.SerializerFor(pkParameterMetaDataRepository);
35-
var xel = XElement.Load(fileName);
35+
var xel = XElementSerializer.PermissiveLoad(fileName);
3636
serializer.Deserialize(pkParameterMetaDataRepository, xel, serializationContext);
3737
}
3838
}

src/OSPSuite.Core/Services/ChartTemplatePersistor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public CurveChartTemplate DeserializeFromFile(string fileFullPath)
102102
{
103103
try
104104
{
105-
return Deserialize(XElement.Load(fileFullPath));
105+
return Deserialize(XElementSerializer.PermissiveLoad(fileFullPath));
106106
}
107107
catch (XmlException)
108108
{
@@ -164,7 +164,7 @@ public void SerializeToFileBasedOn(CurveChart chart, string fileFullPath)
164164
private void saveTemplateToFile(XElement element, string fileFullPath)
165165
{
166166
element.AddAttribute(Constants.Serialization.Attribute.VERSION, PKMLVersion.CURRENT);
167-
element.Save(fileFullPath);
167+
element.PermissiveSave(fileFullPath);
168168
}
169169
}
170170
}

tests/OSPSuite.Core.IntegrationTests/SimulationPersistorSpecs.cs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
using System.Collections.Generic;
22
using System.IO;
33
using System.Linq;
4+
using System.Text;
45
using OSPSuite.BDDHelper;
56
using OSPSuite.BDDHelper.Extensions;
67
using OSPSuite.Core.Domain;
78
using OSPSuite.Core.Domain.Data;
8-
using OSPSuite.Core.Helpers;
99
using OSPSuite.Core.Serialization.Exchange;
1010
using OSPSuite.Core.Serialization.Xml;
1111
using OSPSuite.Core.Serializers;
@@ -37,12 +37,30 @@ public override void Cleanup()
3737
}
3838
}
3939

40+
internal class When_serializing_and_deserializing_an_entity_with_illegal_xml_characters : concern_for_SimulationPersistor
41+
{
42+
[Observation]
43+
public void should_return_a_simulation_transfer_containing_a_valid_simulation()
44+
{
45+
var x1 = new SimulationTransfer { Simulation = _simulation };
46+
var illegalXmlString = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes("F1").Concat(new byte[] { 0x1F }).ToArray());
47+
x1.Favorites.Add(illegalXmlString);
48+
49+
_simulationPersistor.Save(x1, _filePath);
50+
File.Exists(_filePath).ShouldBeTrue();
51+
var deserializationObjectBaseRepository = IoC.Resolve<IWithIdRepository>();
52+
53+
var x2 = _simulationPersistor.Load(_filePath, deserializationObjectBaseRepository);
54+
x2.Favorites.First().ShouldBeEqualTo(illegalXmlString);
55+
}
56+
}
57+
4058
internal class When_deserializing_a_valid_simulation_file_containing_some_licenses : concern_for_SimulationPersistor
4159
{
4260
[Observation]
4361
public void should_return_a_simulation_transfer_containing_a_valid_simulation()
4462
{
45-
var x1 = new SimulationTransfer {Simulation = _simulation};
63+
var x1 = new SimulationTransfer { Simulation = _simulation };
4664
x1.Favorites.Add("F1");
4765
x1.Favorites.Add("F2");
4866
_simulationPersistor.Save(x1, _filePath);
@@ -90,12 +108,12 @@ protected override void Context()
90108
WeightedObservedData = new WeightedObservedData(_obsData),
91109
OutputSelection = new SimulationQuantitySelection(_simulation, new QuantitySelection("A|B|C", QuantityType.Complex))
92110
};
93-
_outputMappings = new OutputMappings {_outputMapping};
111+
_outputMappings = new OutputMappings { _outputMapping };
94112

95-
_simulationTransfer = new SimulationTransfer
113+
_simulationTransfer = new SimulationTransfer
96114
{
97115
Simulation = _simulation,
98-
AllObservedData = new List<DataRepository>{ _obsData },
116+
AllObservedData = new List<DataRepository> { _obsData },
99117
OutputMappings = _outputMappings
100118
};
101119
}

0 commit comments

Comments
 (0)