Skip to content
This repository was archived by the owner on Nov 11, 2025. It is now read-only.

Commit 46dbfbb

Browse files
Copilotbaywet
andcommitted
Add OpenApiXmlNodeType enum and update OpenApiXml for OAI 3.2.0
Co-authored-by: baywet <7905502+baywet@users.noreply.github.com>
1 parent 65fe644 commit 46dbfbb

10 files changed

Lines changed: 305 additions & 9 deletions

File tree

src/Microsoft.OpenApi/Models/OpenApiConstants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,11 @@ public static class OpenApiConstants
245245
/// </summary>
246246
public const string Wrapped = "wrapped";
247247

248+
/// <summary>
249+
/// Field: NodeType
250+
/// </summary>
251+
public const string NodeType = "nodeType";
252+
248253
/// <summary>
249254
/// Field: In
250255
/// </summary>

src/Microsoft.OpenApi/Models/OpenApiXml.cs

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ namespace Microsoft.OpenApi
1111
/// </summary>
1212
public class OpenApiXml : IOpenApiSerializable, IOpenApiExtensible
1313
{
14+
private OpenApiXmlNodeType? _nodeType;
15+
private bool _attribute;
16+
private bool _wrapped;
17+
1418
/// <summary>
1519
/// Replaces the name of the element/attribute used for the described schema property.
1620
/// </summary>
@@ -30,13 +34,56 @@ public class OpenApiXml : IOpenApiSerializable, IOpenApiExtensible
3034
/// Declares whether the property definition translates to an attribute instead of an element.
3135
/// Default value is false.
3236
/// </summary>
33-
public bool Attribute { get; set; }
37+
[Obsolete("Use NodeType property instead. This property will be removed in a future version.")]
38+
public bool Attribute
39+
{
40+
get
41+
{
42+
// If NodeType is explicitly set, use it; otherwise use the backing field
43+
if (_nodeType.HasValue)
44+
{
45+
return _nodeType == OpenApiXmlNodeType.Attribute;
46+
}
47+
return _attribute;
48+
}
49+
set
50+
{
51+
_attribute = value;
52+
_nodeType = value ? OpenApiXmlNodeType.Attribute : OpenApiXmlNodeType.None;
53+
}
54+
}
3455

3556
/// <summary>
3657
/// Signifies whether the array is wrapped.
3758
/// Default value is false.
3859
/// </summary>
39-
public bool Wrapped { get; set; }
60+
[Obsolete("Use NodeType property instead. This property will be removed in a future version.")]
61+
public bool Wrapped
62+
{
63+
get
64+
{
65+
// If NodeType is explicitly set, use it; otherwise use the backing field
66+
if (_nodeType.HasValue)
67+
{
68+
return _nodeType == OpenApiXmlNodeType.Element;
69+
}
70+
return _wrapped;
71+
}
72+
set
73+
{
74+
_wrapped = value;
75+
_nodeType = value ? OpenApiXmlNodeType.Element : OpenApiXmlNodeType.None;
76+
}
77+
}
78+
79+
/// <summary>
80+
/// The node type of the XML representation.
81+
/// </summary>
82+
public OpenApiXmlNodeType? NodeType
83+
{
84+
get => _nodeType;
85+
set => _nodeType = value;
86+
}
4087

4188
/// <summary>
4289
/// Specification Extensions.
@@ -56,8 +103,9 @@ public OpenApiXml(OpenApiXml xml)
56103
Name = xml?.Name ?? Name;
57104
Namespace = xml?.Namespace ?? Namespace;
58105
Prefix = xml?.Prefix ?? Prefix;
59-
Attribute = xml?.Attribute ?? Attribute;
60-
Wrapped = xml?.Wrapped ?? Wrapped;
106+
_nodeType = xml?._nodeType ?? _nodeType;
107+
_attribute = xml?._attribute ?? _attribute;
108+
_wrapped = xml?._wrapped ?? _wrapped;
61109
Extensions = xml?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(xml.Extensions) : null;
62110
}
63111

@@ -108,11 +156,32 @@ private void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
108156
// prefix
109157
writer.WriteProperty(OpenApiConstants.Prefix, Prefix);
110158

111-
// attribute
112-
writer.WriteProperty(OpenApiConstants.Attribute, Attribute, false);
113-
114-
// wrapped
115-
writer.WriteProperty(OpenApiConstants.Wrapped, Wrapped, false);
159+
// For OpenAPI 3.2.0 and above, serialize nodeType
160+
if (specVersion >= OpenApiSpecVersion.OpenApi3_2)
161+
{
162+
if (_nodeType.HasValue)
163+
{
164+
writer.WriteProperty(OpenApiConstants.NodeType, _nodeType.Value.GetDisplayName());
165+
}
166+
}
167+
else
168+
{
169+
// For OpenAPI 3.1.0 and below, serialize attribute and wrapped
170+
// Use backing fields if they were set via obsolete properties,
171+
// otherwise derive from NodeType if set
172+
bool attribute = _attribute;
173+
bool wrapped = _wrapped;
174+
175+
if (_nodeType.HasValue && !_attribute && !_wrapped)
176+
{
177+
// NodeType was set directly, not via obsolete properties
178+
attribute = _nodeType == OpenApiXmlNodeType.Attribute;
179+
wrapped = _nodeType == OpenApiXmlNodeType.Element;
180+
}
181+
182+
writer.WriteProperty(OpenApiConstants.Attribute, attribute, false);
183+
writer.WriteProperty(OpenApiConstants.Wrapped, wrapped, false);
184+
}
116185

117186
// extensions
118187
writer.WriteExtensions(Extensions, specVersion);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
namespace Microsoft.OpenApi
5+
{
6+
/// <summary>
7+
/// The type of the XML node
8+
/// </summary>
9+
public enum OpenApiXmlNodeType
10+
{
11+
/// <summary>
12+
/// Element node type
13+
/// </summary>
14+
[Display("element")] Element,
15+
16+
/// <summary>
17+
/// Attribute node type
18+
/// </summary>
19+
[Display("attribute")] Attribute,
20+
21+
/// <summary>
22+
/// Text node type
23+
/// </summary>
24+
[Display("text")] Text,
25+
26+
/// <summary>
27+
/// CDATA node type
28+
/// </summary>
29+
[Display("cdata")] Cdata,
30+
31+
/// <summary>
32+
/// None node type
33+
/// </summary>
34+
[Display("none")] None
35+
}
36+
}

src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ internal static partial class OpenApiV2Deserializer
4242
var attribute = n.GetScalarValue();
4343
if (attribute is not null)
4444
{
45+
#pragma warning disable CS0618 // Type or member is obsolete
4546
o.Attribute = bool.Parse(attribute);
47+
#pragma warning restore CS0618 // Type or member is obsolete
4648
}
4749
}
4850
},
@@ -53,7 +55,9 @@ internal static partial class OpenApiV2Deserializer
5355
var wrapped = n.GetScalarValue();
5456
if (wrapped is not null)
5557
{
58+
#pragma warning disable CS0618 // Type or member is obsolete
5659
o.Wrapped = bool.Parse(wrapped);
60+
#pragma warning restore CS0618 // Type or member is obsolete
5761
}
5862
}
5963
},

src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ internal static partial class OpenApiV3Deserializer
3939
var attribute = n.GetScalarValue();
4040
if (attribute is not null)
4141
{
42+
#pragma warning disable CS0618 // Type or member is obsolete
4243
o.Attribute = bool.Parse(attribute);
44+
#pragma warning restore CS0618 // Type or member is obsolete
4345
}
4446
}
4547
},
@@ -50,7 +52,9 @@ internal static partial class OpenApiV3Deserializer
5052
var wrapped = n.GetScalarValue();
5153
if (wrapped is not null)
5254
{
55+
#pragma warning disable CS0618 // Type or member is obsolete
5356
o.Wrapped = bool.Parse(wrapped);
57+
#pragma warning restore CS0618 // Type or member is obsolete
5458
}
5559
}
5660
},

src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ internal static partial class OpenApiV31Deserializer
4141
var attribute = n.GetScalarValue();
4242
if (attribute is not null)
4343
{
44+
#pragma warning disable CS0618 // Type or member is obsolete
4445
o.Attribute = bool.Parse(attribute);
46+
#pragma warning restore CS0618 // Type or member is obsolete
4547
}
4648
}
4749
},
@@ -52,7 +54,9 @@ internal static partial class OpenApiV31Deserializer
5254
var wrapped = n.GetScalarValue();
5355
if (wrapped is not null)
5456
{
57+
#pragma warning disable CS0618 // Type or member is obsolete
5558
o.Wrapped = bool.Parse(wrapped);
59+
#pragma warning restore CS0618 // Type or member is obsolete
5660
}
5761
}
5862
}

src/Microsoft.OpenApi/Reader/V32/OpenApiXmlDeserializer.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ internal static partial class OpenApiV32Deserializer
4141
var attribute = n.GetScalarValue();
4242
if (attribute is not null)
4343
{
44+
#pragma warning disable CS0618 // Type or member is obsolete
4445
o.Attribute = bool.Parse(attribute);
46+
#pragma warning restore CS0618 // Type or member is obsolete
4547
}
4648
}
4749
},
@@ -52,7 +54,28 @@ internal static partial class OpenApiV32Deserializer
5254
var wrapped = n.GetScalarValue();
5355
if (wrapped is not null)
5456
{
57+
#pragma warning disable CS0618 // Type or member is obsolete
5558
o.Wrapped = bool.Parse(wrapped);
59+
#pragma warning restore CS0618 // Type or member is obsolete
60+
}
61+
}
62+
},
63+
{
64+
"nodeType",
65+
(o, n, _) =>
66+
{
67+
var nodeType = n.GetScalarValue();
68+
if (nodeType is not null)
69+
{
70+
o.NodeType = nodeType.ToLowerInvariant() switch
71+
{
72+
"element" => OpenApiXmlNodeType.Element,
73+
"attribute" => OpenApiXmlNodeType.Attribute,
74+
"text" => OpenApiXmlNodeType.Text,
75+
"cdata" => OpenApiXmlNodeType.Cdata,
76+
"none" => OpenApiXmlNodeType.None,
77+
_ => null
78+
};
5679
}
5780
}
5881
}

test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public async Task ParseBasicXmlShouldSucceed()
2121
var xml = await OpenApiModelFactory.LoadAsync<OpenApiXml>(Resources.GetStream(Path.Combine(SampleFolderPath, "basicXml.yaml")), OpenApiSpecVersion.OpenApi3_0, new(), settings: SettingsFixture.ReaderSettings);
2222

2323
// Assert
24+
#pragma warning disable CS0618 // Type or member is obsolete
2425
Assert.Equivalent(
2526
new OpenApiXml
2627
{
@@ -29,6 +30,7 @@ public async Task ParseBasicXmlShouldSucceed()
2930
Prefix = "samplePrefix",
3031
Wrapped = true
3132
}, xml);
33+
#pragma warning restore CS0618 // Type or member is obsolete
3234
}
3335
}
3436
}

0 commit comments

Comments
 (0)