OpenAPI-Specification
OpenAPI-Specification copied to clipboard
How to represent XML elements with attributes
Suppose I have the following XML:
<location>
<coordinate format="lat-lon">a-b</coordinate>
</location>
I this the correct way to represent this using Swagger Schema objects?
---
type: "object"
xml:
name: "location"
properties:
coordinate:
type: "string"
properties:
format:
type: "string"
xml:
attribute: true
It seems weird for the "coordinate" property ... which itself is of type "string" to contain a "properties" field. Coming from JSON-Schema-Draft-V4 background, you would not expect a "string" field to have properties, because there is no such thing in JSON.
But then again, this is a "Swagger Schema Object" ... not a JSON-Schema-Draft-V4. I just want confirmation whether or not this is the correct way to do it.
When it comes to pure json schema, that's actually not illegal, but the properties, when it comes to json, would be effectively ignored.
As for the answer to your actual question - there's pretty much no way to represent that currently with 2.0. The attributes can pretty much be applied only to objects.
Nice idea.
I guess Swagger/OpenAPI can not describe many types of XML, just those that have an obvious 1:1 mapping to JSON which can be described by OpenAPI itself. As there is no JSON equivalent to your XML fragment, it can't be described with Swagger either.
Thanks @webron and @ePaul for the clarifications.
That's correct, my sample XML has no way of being represented as JSON ... unless you adopt some convention like BadgerFish (http://www.sklar.com/badgerfish/)
where it would be represented like this:
{
"location": {
"coordinate": {
"@format": "lat-lon",
"$": "a-b",
}
}
}
(which itself could be described purely by JSON Schema without resorting to using the xml
field that Swagger came up with).
But, putting that aside ... since it's not illegal (as @webron pointed out) in JSON-Schema-Draft-V4 for a string to have properties ... OpenAPI could accept it as a valid schema to describe XML ... just a matter of convention.
This is primarily a problem when you are trying to use swagger to document an already existing API (that is, an API that you can't change). Which is a pretty big bummer!
This could be solved by adding the convention to OpenAPI 3.0 that the text node of an XML element is represented as a property whose name is the empty string:
type: "object"
xml:
name: "location"
properties:
coordinate:
type: "object"
properties:
format:
type: "string"
xml:
attribute: true
"":
type: "string"
Oh man! If that's the type of hacking we can expect in this spec for 3.0, then I'd consider it a failure. A property whose name is an empty string? Really? That's intentional / by design? I can hear the death knell for Swagger now!
Any reserved property name that cannot be mistaken for an XML attribute name would do the trick, the empty name is just the shortest possible choice.
Another obvious name would be text()
- also no risk of clashing with an XML attribute name in someone's API out there.
Ugh. The hacking shows the lack for forethought that went into this stuff. If Swagger / OpenAPI were designed from the get go to be suitably generic, these hacks wouldn't be needed. It's like the nasty "discriminator" hack to make things look hierarchical through some messed up definition. It's no wonder adoption for existing APIs is so low for this stuff....
I assume Swagger / OpenAPI was primarily invented for describing APIs that use the JSON format, and I think it does a great job in that area.
Unfortunately its JSON-Schema-based payload description syntax only supports a subset of XML, and the most prominent gap is XML elements with text content.
@AlskiOnTheWeb how would you address this gap?
I have seen many javascript webpages use _ prefix in json to denote an attribute and __ prefix to denote inner text. Also I found this on the web http://wiki.open311.org/JSON_and_XML_Conversion/
As we have the attribute
property on the xml
object already, perhaps it makes sense to add a text
property (also of type boolean) to indicate that the property represents the xml text node, where at most only one property of an object SHOULD be marked text: true
?
Thus
location:
type: "object"
properties:
coordinate:
type: "object"
properties:
format:
type: "string"
xml:
attribute: true
value:
type: "string"
xml:
text: true
would represent the xml
<location>
<coordinate format="lat-lon">a-b</coordinate>
</location>
I inadvertantly added another bug here: #2624
I would also like to suggest a similar solution as @MikeRalphson, with 1 possible tweek:
TypeName:
type: "object"
properties:
href:
type: "string"
example: "example.com"
xml:
attribute: true
value:
type: "string"
example: "SampleTypeName"
xml:
wrapped: "false"
xml:
name: "typeName"
Which would produce:
<typeName href="example.com">SampleTypeName</typeName>
Like wise, we're also using the (http://www.sklar.com/badgerfish/) convention for converting to json objects, per @micovery comment above.
Hi
With MikeRalphson and ronniedepriest‘s comments, I just got something like this:
I could not remove the value tag, is there any good ideas?
<typeName href="example.com"> <value>SampleTypeName</value> </typeName>
@andygaga2018 to make things clear, both of the examples above are proposals for future versions of the OpenAPI Specification. They won't work today in any existing tools.
Not sure if that made things completely clear. Let me add: the xml/attribute flag is available in OpenAPI Spec 3.0.0.
This schema:
components:
schemas:
Person:
type: object
xml:
namespace: http://example.com/schema/sample
properties:
id:
type: integer
format: int32
xml:
attribute: true
name:
type: string
xml:
namespace: http://example.com/schema/sample
required:
- name
- id
allows this XML
<Person xmlns="http://example.com/schema/sample" id="0">
<name>string</name>
</Person>
I stumbled upon this issue today. I guess the problem is not with the attributes - they work fine, the problem is with objects that have both attributes and a value. Maybe the title of the issue could be rephrased to indicate that?
Solution wise.. I'm +1 on text: true
or inline: true
.
How should we move this forward?
Describing non-object elements with attributes such as <coordinate format="lat-lon">a-b</coordinate>
will be possible with x-oas-draft-alternativeSchema
(#1532) if that proposal is implemented.
How to represent below xml in swagger 2.0?
<CID name="ClientId"> 123 </CID>
has this issue been resolved ?? I don't see any mention of it in 3.0.2 release notes
The issue is still open / unresolved. As per our development guide, it isn't the kind of thing which can be changed in a patch release.
This worked for me:
"geolocation": { "type": "object", "title": "geolocation", "properties": { "coordinates": { "name": "coordinates", "$ref": "./coordinates.json" } } }
And this is the contents of the referenced file:
{ "type": "object", "title": "coordinates", "required": [ "latitude", "longitude" ], "properties": { "latitude": { "type": "number", "format": "float" }, "longitude": { "type": "number", "format": "float" } } }
Is this going to be addressed in future OpenAPI specifications? eg 3.1 or 4.0?
With 3.1 being almost ready, it's unlikely to make it in. Based on work that has been done the last couple of years, I suspect it's more likely we'll see support for other schemas (such as XSD) rather than trying to resolve this issue, but time will tell.
It's sad to see how an issue has been neglected for 4 years and counting. :(
4 years and counting for sure...and it won't end either since the spec itself is fundamentally flawed. The hens have come to roost for this problem, what went around came around. Poor design / poor result. Garbage in / Garbage out.
Based on work that has been done the last couple of years, I suspect it's more likely we'll see support for other schemas (such as XSD)
That helps in the sense that we have well documented XSDs already. In JSON Schema I'm missing mixed node support, enum content description support, support for <xs:attributeGroup ref="..."/>, support for $ref + a tweak, like deprecating the calling property or supplying a new default (cannot use anything next to $ref according to the validators), and then some like comment().
The downside is having to maintain 2 schemas. The notion of one schema to rule them all was fun while it lasted I guess.
Just a note that JSON Schema draft 2020-12 (which will be referenced by OAS 3.1) does support some of these constructs, such as $ref
with siblings and $comment
. enum
s with description
s can also be expressed as oneOf
s with const
s in each branch - though tooling will have to recognise that pattern as equivalent to an enum
.
Depending on the appetite for alternative-schema support, there could be room for xmlObject
improvements in OAS 3.2.
I found this thread while trying to figure out how to add an XML attribute to what would be an array in the JSON definition. e.g. something like the count
attribute here:
<nodes count="1">
<node id="3fa85f64-5717-4562-b3fc-2c963f66afa6">
...stuff...
</node>
</nodes>
It does not look like that is currently possible, so i wanted to make sure this use-case is also on your radar.
Stuck with this issue too!
Is there any workaround to do it in dot net core ISchemaFilter. Inner text example value not showing in swager openAPI schema.
<periodStart>2021-08-06T17:06:29.918</periodStart> <periodStop>2021-08-06T17:06:29.918</periodStop> **<totalQuantity unit="Mwh"> </totalQuantity>
**
if (property.Key == "totalQuantity") { schema.Properties[property.Key].Type = "string";
schema.Properties[property.Key].Xml = new OpenApiXml() { Wrapped =false, Attribute = false, Name = ""};
schema.Properties[property.Key].Example = new Microsoft.OpenApi.Any.OpenApiString("25.0");
}