Skip to content

Commit f3f01d0

Browse files
mrsuciuromanett
andauthored
Fix XML Encoding and decoding of Matrix Element in Variant to conform to spec (#3053) (#3054)
* Fix XML Encoding and decoding to conform to spec * fix test on linux * fix typo * Add missing DataValue & DiagnosticInfo Array Types Co-authored-by: romanett <romanett98@gmail.com>
1 parent 7586fd2 commit f3f01d0

File tree

3 files changed

+86
-8
lines changed

3 files changed

+86
-8
lines changed

Stack/Opc.Ua.Core/Types/Encoders/XmlDecoder.cs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2740,15 +2740,15 @@ private Matrix ReadMatrix(string fieldName)
27402740
{
27412741
PushNamespace(Namespaces.OpcUaXsd);
27422742

2743+
dimensions = ReadInt32Array("Dimensions");
2744+
27432745
if (BeginField("Elements", true))
27442746
{
2745-
object contents = ReadVariantContents(out typeInfo);
2746-
elements = contents as Array;
2747+
typeInfo = MapElementTypeToTypeInfo(m_reader.LocalName);
2748+
elements = ReadArray(null, typeInfo.ValueRank, typeInfo.BuiltInType, null);
27472749
EndField("Elements");
27482750
}
27492751

2750-
dimensions = ReadInt32Array("Dimensions");
2751-
27522752
PopNamespace();
27532753

27542754
EndField(fieldName);
@@ -2782,6 +2782,43 @@ private Matrix ReadMatrix(string fieldName)
27822782
}
27832783
}
27842784

2785+
/// <summary>
2786+
/// Maps an element type name to its corresponding TypeInfo.Arrays value.
2787+
/// </summary>
2788+
/// <param name="elementTypeName">The name of the element type.</param>
2789+
/// <returns>The corresponding TypeInfo.Arrays value.</returns>
2790+
private TypeInfo MapElementTypeToTypeInfo(string elementTypeName)
2791+
{
2792+
return elementTypeName switch {
2793+
"Boolean" => TypeInfo.Arrays.Boolean,
2794+
"SByte" => TypeInfo.Arrays.SByte,
2795+
"Byte" => TypeInfo.Arrays.Byte,
2796+
"Int16" => TypeInfo.Arrays.Int16,
2797+
"UInt16" => TypeInfo.Arrays.UInt16,
2798+
"Int32" => TypeInfo.Arrays.Int32,
2799+
"UInt32" => TypeInfo.Arrays.UInt32,
2800+
"Int64" => TypeInfo.Arrays.Int64,
2801+
"UInt64" => TypeInfo.Arrays.UInt64,
2802+
"Float" => TypeInfo.Arrays.Float,
2803+
"Double" => TypeInfo.Arrays.Double,
2804+
"String" => TypeInfo.Arrays.String,
2805+
"DateTime" => TypeInfo.Arrays.DateTime,
2806+
"Guid" => TypeInfo.Arrays.Guid,
2807+
"ByteString" => TypeInfo.Arrays.ByteString,
2808+
"XmlElement" => TypeInfo.Arrays.XmlElement,
2809+
"NodeId" => TypeInfo.Arrays.NodeId,
2810+
"ExpandedNodeId" => TypeInfo.Arrays.ExpandedNodeId,
2811+
"StatusCode" => TypeInfo.Arrays.StatusCode,
2812+
"QualifiedName" => TypeInfo.Arrays.QualifiedName,
2813+
"LocalizedText" => TypeInfo.Arrays.LocalizedText,
2814+
"ExtensionObject" => TypeInfo.Arrays.ExtensionObject,
2815+
"Variant" => TypeInfo.Arrays.Variant,
2816+
"DataValue" => TypeInfo.Arrays.DataValue,
2817+
"DiagnosticInfo" => TypeInfo.Arrays.DiagnosticInfo,
2818+
_ => throw new ServiceResultException(StatusCodes.BadDecodingError, $"Unsupported element type: {elementTypeName}")
2819+
};
2820+
}
2821+
27852822
/// <summary>
27862823
/// Read array items from current ListOf element
27872824
/// </summary>

Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,11 +2175,9 @@ private void WriteMatrix(string fieldName, Matrix value)
21752175

21762176
if (value != null)
21772177
{
2178-
m_writer.WriteStartElement("Elements", Namespaces.OpcUaXsd);
2179-
WriteVariantContents(value.Elements, new TypeInfo(value.TypeInfo.BuiltInType, ValueRanks.OneDimension));
2180-
m_writer.WriteEndElement();
2181-
21822178
WriteInt32Array("Dimensions", value.Dimensions);
2179+
2180+
WriteArray("Elements", value.Elements, ValueRanks.OneDimension, value.TypeInfo.BuiltInType);
21832181
}
21842182

21852183
PopNamespace();

Tests/Opc.Ua.Core.Tests/Types/Encoders/XmlEncoderTests.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,49 @@ public void EncodeDecodeDouble(double binaryValue, string expectedXmlValue)
133133
else
134134
Assert.AreEqual(actualBinaryValue, binaryValue);
135135
}
136+
137+
/// <summary>
138+
/// Validate the encoding and decoding of the a variant that consists of a matrix.
139+
/// </summary>
140+
[Test]
141+
public void EncodeDecodeVariantMatrix()
142+
{
143+
var value = new Matrix(
144+
new int[] { 1, 2, 3, 4 },
145+
BuiltInType.Int32,
146+
new int[] { 2, 2 }
147+
);
148+
var variant = new Variant(value);
149+
150+
string expected = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<uax:VariantTest xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:uax=\"http://opcfoundation.org/UA/2008/02/Types.xsd\">\r\n <uax:Test>\r\n <uax:Value>\r\n <uax:Matrix>\r\n <uax:Dimensions>\r\n <uax:Int32>2</uax:Int32>\r\n <uax:Int32>2</uax:Int32>\r\n </uax:Dimensions>\r\n <uax:Elements>\r\n <uax:Int32>1</uax:Int32>\r\n <uax:Int32>2</uax:Int32>\r\n <uax:Int32>3</uax:Int32>\r\n <uax:Int32>4</uax:Int32>\r\n </uax:Elements>\r\n </uax:Matrix>\r\n </uax:Value>\r\n </uax:Test>\r\n</uax:VariantTest>";
151+
152+
// Encode
153+
var context = new ServiceMessageContext();
154+
string actualXmlValue;
155+
using (IEncoder xmlEncoder = new XmlEncoder(new XmlQualifiedName("VariantTest", Namespaces.OpcUaXsd), null, context))
156+
{
157+
xmlEncoder.PushNamespace(Namespaces.OpcUaXsd);
158+
xmlEncoder.WriteVariant("Test", variant);
159+
xmlEncoder.PopNamespace();
160+
actualXmlValue = xmlEncoder.CloseAndReturnText();
161+
}
162+
163+
// Check encode result against expected XML value
164+
Assert.AreEqual(expected.Replace("\r", "").Replace("\n", ""), actualXmlValue.Replace("\r", "").Replace("\n", ""));
165+
166+
// Decode
167+
Variant actualVariant;
168+
using (XmlReader reader = XmlReader.Create(new StringReader(actualXmlValue)))
169+
{
170+
using (IDecoder xmlDecoder = new XmlDecoder(null, reader, context))
171+
{
172+
actualVariant = xmlDecoder.ReadVariant("Test");
173+
}
174+
}
175+
176+
// Check decode result against input value
177+
Assert.AreEqual(actualVariant, variant);
178+
}
136179
#endregion
137180
}
138181
}

0 commit comments

Comments
 (0)