Skip to content

Commit 6850e16

Browse files
committed
Support all common XML node types
This change adds a nodeType field to support the four most commonly used XML node types: element, attribute, text, and cdata. A fifth nodetype, none, is used to prevent a Schema Object from producing a node. This also removes the restriction on where the xml field and XML Object can appear, as the nodeType system is more flexible than the old system. This deprecates two existing fields: * attribute, replaced by nodeType: attribute * wrapped, replaced by nodeType: none
1 parent 00fe2ed commit 6850e16

File tree

2 files changed

+227
-70
lines changed

2 files changed

+227
-70
lines changed

src/oas.md

Lines changed: 212 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,7 +2582,7 @@ JSON Schema implementations MAY choose to treat keywords defined by the OpenAPI
25822582
| Field Name | Type | Description |
25832583
| ---- | :----: | ---- |
25842584
| <a name="schema-discriminator"></a>discriminator | [Discriminator Object](#discriminator-object) | The discriminator provides a "hint" for which of a set of schemas a payload is expected to satisfy. See [Composition and Inheritance](#composition-and-inheritance-polymorphism) for more details. |
2585-
| <a name="schema-xml"></a>xml | [XML Object](#xml-object) | This MAY be used only on property schemas. It has no effect on root schemas. Adds additional metadata to describe the XML representation of this property. |
2585+
| <a name="schema-xml"></a>xml | [XML Object](#xml-object) | Adds additional metadata to describe the XML representation of this schema. |
25862586
| <a name="schema-external-docs"></a>externalDocs | [External Documentation Object](#external-documentation-object) | Additional external documentation for this schema. |
25872587
| <a name="schema-example"></a>example | Any | A free-form field to include an example of an instance for this schema. To represent examples that cannot be naturally represented in JSON or YAML, a string value can be used to contain the example with escaping where necessary.<br><br>**Deprecated:** The `example` field has been deprecated in favor of the JSON Schema `examples` keyword. Use of `example` is discouraged, and later versions of this specification may remove it. |
25882588

@@ -3184,52 +3184,100 @@ will map to `#/components/schemas/Dog` because the `dog` entry in the `mapping`
31843184
#### XML Object
31853185

31863186
A metadata object that allows for more fine-tuned XML model definitions.
3187-
3188-
When using arrays, XML element names are _not_ inferred (for singular/plural forms) and the `name` field SHOULD be used to add that information.
3189-
See examples for expected behavior.
3187+
When using a Schema Object with XML, if no XML Object is present, the behavior is determined by the XML Object's default field values.
31903188

31913189
##### Fixed Fields
31923190

31933191
| Field Name | Type | Description |
31943192
| ---- | :----: | ---- |
3195-
| <a name="xml-name"></a>name | `string` | Replaces the inferred name of the element/attribute used for the described schema property. For the root schema object of a [schema component](#components-schemas), the inferred name is the name of the component; for other schemas the name is inferred from the parent property name. When defined within `items`, it will affect the name of the individual XML elements within the list. When defined alongside `type` being `"array"` (outside the `items`), it will affect the wrapping element if and only if `wrapped` is `true`. If `wrapped` is `false`, it will be ignored. |
3193+
| <a name="xml-node-type"></a>nodeType | `string` | One of `element`, `attribute`, `text`, `cdata`, or `none`, as explained under [XML Node Types](#xml-node-types). The default value is `none` if `$ref`, `$dynamicRef`, or `type: array` is present in the [Schema Object](#schema-object) containing the XML Object, and `element` otherwise. |
3194+
| <a name="xml-name"></a>name | `string` | Sets the name of the element/attribute used for the described schema property, replacing name that was inferred as described under [XML Node Names](#xml-node-names). This field SHALL be ignored if the `nodeType` is `text`, `cdata`, or `none`. |
31963195
| <a name="xml-namespace"></a>namespace | `string` | The IRI ([[RFC3987]]) of the namespace definition. Value MUST be in the form of a non-relative IRI. |
31973196
| <a name="xml-prefix"></a>prefix | `string` | The prefix to be used for the [name](#xml-name). |
3198-
| <a name="xml-attribute"></a>attribute | `boolean` | Declares whether the property definition translates to an attribute instead of an element. Default value is `false`. |
3199-
| <a name="xml-wrapped"></a>wrapped | `boolean` | MAY be used only for an array definition. Signifies whether the array is wrapped (for example, `<books><book/><book/></books>`) or unwrapped (`<book/><book/>`). Default value is `false`. The definition takes effect only when defined alongside `type` being `"array"` (outside the `items`). |
3197+
| <a name="xml-attribute"></a>attribute | `boolean` | Declares whether the property definition translates to an attribute instead of an element. Default value is `false`. If `nodeType` is present, this field MUST NOT be present.<br /><br />**Deprecated:** Use `nodeType: attribute` in place of `attribute: true` |
3198+
| <a name="xml-wrapped"></a>wrapped | `boolean` | MAY be used only for an array definition. Signifies whether the array is wrapped (for example, `<books><book/><book/></books>`) or unwrapped (`<book/><book/>`). Default value is `false`. The definition takes effect only when defined alongside `type` being `"array"` (outside the `items`). If `nodeType` is present, this field MUST NOT be present.<br /><br />**Deprecated:** Set `nodeType: element` explicitly in place of `wrapped: true` |
3199+
3200+
Note that when generating an XML document from object data, the order of the nodes is undefined.
3201+
Use `prefixItems` to control node ordering.
3202+
3203+
See [Appendix B](#appendix-b-data-type-conversion) for a discussion of converting values of various types to string representations.
32003204

32013205
This object MAY be extended with [Specification Extensions](#specification-extensions).
32023206

3207+
##### XML Node Types
3208+
3209+
Each Schema Object describes a particular type of XML [node](https://dom.spec.whatwg.org/#interface-node) which is specified by the `nodeType` field, which has the following possible values.
3210+
Except for the special value `none`, these values have numeric equivalents in the DOM [specification](https://dom.spec.whatwg.org/#interface-node) which are given in parentheses after the name:
3211+
3212+
* `element` (1): The schema represents an element and describes its contents
3213+
* `attribute` (2): The schema represents an attribute and describes its value
3214+
* `text` (3): The schema represents a text node (parsed character data)
3215+
* `cdata` (4): The schema represents a CDATA section
3216+
* `none`: The schema does not correspond to any node in the XML document, and its contents are included directly under the parent schema's node
3217+
3218+
The `none` type is useful for JSON Schema constructs that require more Schema Objects than XML nodes, such as a schema containing only `$ref` that exists to facilitate re-use rather than imply any structure.
3219+
3220+
###### Modeling Element Lists
3221+
3222+
For historical compatibility, schemas of `type: array` default to `nodeType: none`, placing the nodes for each array item directly under the parent node.
3223+
This also aligns with the inferred naming behavior defined under [XML Node Names](#xml-node-names).
3224+
3225+
To produce an element wrapping the list, set an explicit `nodeType: element` on the `type: array` schema.
3226+
When doing so, it is advisable to set an explicit name on either the wrapping element or the item elements to avoid them having the same inferred name.
3227+
See examples for expected behavior.
3228+
3229+
###### Implicit and Explicit `text` Nodes
3230+
3231+
If an `element` node has a primitive type, then the schema also produces an implicit `text` node described by the schema for the contents of the `element` node named by the property name (or `name` field).
3232+
3233+
Explicit `text` nodes are necessary if an element has both attributes and content.
3234+
3235+
Note that placing two `text` nodes adjacent to each other is ambiguous for parsing, and the resulting behavior is implementation-defined.
3236+
3237+
##### XML Node Names
3238+
3239+
The `element` and `attribute` node types require a name, which MUST be inferred from the schema as follows, unless overridden by the `name` field:
3240+
3241+
* For schemas directly under the [Components Object's](#components-object) `schemas` field, the component name is the inferred name.
3242+
* For property schemas, and for array item schemas under a property schema, the property name is the inferred name
3243+
* In all other cases, such as an inline schema under a [Media Type Object's](#media-type-object) `schema` field, no name can be inferred and an XML Object with a `name` field MUST be present
3244+
3245+
Note that when using arrays, singular vs plural forms are _not_ inferred, and must be set explicitly.
3246+
3247+
##### Namespace Limitations
3248+
32033249
The `namespace` field is intended to match the syntax of [XML namespaces](https://www.w3.org/TR/xml-names11/), although there are a few caveats:
32043250

32053251
* Versions 3.1.0, 3.0.3, and earlier of this specification erroneously used the term "absolute URI" instead of "non-relative URI" ("non-relative IRI" as of OAS v3.2.0), so authors using namespaces that include a fragment should check tooling support carefully.
32063252
* XML allows but discourages relative IRI-references, while this specification outright forbids them.
32073253

32083254
##### XML Object Examples
32093255

3210-
Each of the following examples represent the value of the `properties` keyword in a [Schema Object](#schema-object) that is omitted for brevity.
3211-
The JSON and YAML representations of the `properties` value are followed by an example XML representation produced for the single property shown.
3256+
The Schema Objects are followed by an example XML representation produced for the schema shown.
3257+
For examples using `attribute` or `wrapped`, please see version 3.1 of the OpenAPI Specification.
32123258

3213-
###### No XML Element
3259+
###### No XML Object
32143260

3215-
Basic string property:
3261+
Basic string property (`nodeType` is `element` by default):
32163262

32173263
```yaml
3218-
animals:
3219-
type: string
3264+
properties:
3265+
animals:
3266+
type: string
32203267
```
32213268

32223269
```xml
32233270
<animals>...</animals>
32243271
```
32253272

3226-
Basic string array property ([`wrapped`](#xml-wrapped) is `false` by default):
3273+
Basic string array property (`nodeType` is `none` by default):
32273274

32283275
```yaml
3229-
animals:
3230-
type: array
3231-
items:
3232-
type: string
3276+
properties:
3277+
animals:
3278+
type: array
3279+
items:
3280+
type: string
32333281
```
32343282

32353283
```xml
@@ -3241,10 +3289,11 @@ animals:
32413289
###### XML Name Replacement
32423290

32433291
```yaml
3244-
animals:
3245-
type: string
3246-
xml:
3247-
name: animal
3292+
properties:
3293+
animals:
3294+
type: string
3295+
xml:
3296+
name: animal
32483297
```
32493298

32503299
```xml
@@ -3253,7 +3302,6 @@ animals:
32533302

32543303
###### XML Attribute, Prefix and Namespace
32553304

3256-
In this example, a full [schema component](#components-schemas) definition is shown.
32573305
Note that the name of the root XML element comes from the component name.
32583306

32593307
```yaml
@@ -3285,46 +3333,49 @@ components:
32853333
Changing the element names:
32863334

32873335
```yaml
3288-
animals:
3289-
type: array
3290-
items:
3291-
type: string
3292-
xml:
3293-
name: animal
3336+
properties:
3337+
animals:
3338+
type: array
3339+
items:
3340+
type: string
3341+
xml:
3342+
name: animal
32943343
```
32953344

32963345
```xml
32973346
<animal>value</animal>
32983347
<animal>value</animal>
32993348
```
33003349

3301-
The external `name` field has no effect on the XML:
3350+
The `name` field for the `type: array` schema has no effect because the default `nodeType` for that object is `none`:
33023351

33033352
```yaml
3304-
animals:
3305-
type: array
3306-
items:
3307-
type: string
3353+
properties:
3354+
animals:
3355+
type: array
3356+
items:
3357+
type: string
3358+
xml:
3359+
name: animal
33083360
xml:
3309-
name: animal
3310-
xml:
3311-
name: aliens
3361+
name: aliens
33123362
```
33133363

33143364
```xml
33153365
<animal>value</animal>
33163366
<animal>value</animal>
33173367
```
33183368

3319-
Even when the array is wrapped, if a name is not explicitly defined, the same name will be used both internally and externally:
3369+
Even when a wrapping element is explicitly created by setting `nodeType` to `element`, if a name is not explicitly defined, the same name will be used for both the wrapping element and the list item elements:
33203370

33213371
```yaml
3322-
animals:
3323-
type: array
3324-
items:
3325-
type: string
3326-
xml:
3327-
wrapped: true
3372+
properties:
3373+
animals:
3374+
type: array
3375+
items:
3376+
type: string
3377+
xml:
3378+
nodeType: element
33283379
```
33293380

33303381
```xml
@@ -3337,14 +3388,15 @@ animals:
33373388
To overcome the naming problem in the example above, the following definition can be used:
33383389

33393390
```yaml
3340-
animals:
3341-
type: array
3342-
items:
3343-
type: string
3391+
properties:
3392+
animals:
3393+
type: array
3394+
items:
3395+
type: string
3396+
xml:
3397+
name: animal
33443398
xml:
3345-
name: animal
3346-
xml:
3347-
wrapped: true
3399+
nodeType: element
33483400
```
33493401

33503402
```xml
@@ -3354,18 +3406,19 @@ animals:
33543406
</animals>
33553407
```
33563408

3357-
Affecting both internal and external names:
3409+
Affecting both wrapping element and item element names:
33583410

33593411
```yaml
3360-
animals:
3361-
type: array
3362-
items:
3363-
type: string
3412+
properties:
3413+
animals:
3414+
type: array
3415+
items:
3416+
type: string
3417+
xml:
3418+
name: animal
33643419
xml:
3365-
name: animal
3366-
xml:
3367-
name: aliens
3368-
wrapped: true
3420+
name: aliens
3421+
nodeType: element
33693422
```
33703423

33713424
```xml
@@ -3375,16 +3428,17 @@ animals:
33753428
</aliens>
33763429
```
33773430

3378-
If we change the external element but not the internal ones:
3431+
If we change the wrapping element name but not the item element names:
33793432

33803433
```yaml
3381-
animals:
3382-
type: array
3383-
items:
3384-
type: string
3385-
xml:
3386-
name: aliens
3387-
wrapped: true
3434+
properties:
3435+
animals:
3436+
type: array
3437+
items:
3438+
type: string
3439+
xml:
3440+
name: aliens
3441+
nodeType: element
33883442
```
33893443

33903444
```xml
@@ -3394,6 +3448,96 @@ animals:
33943448
</aliens>
33953449
```
33963450

3451+
###### Elements With Attributes And Text
3452+
3453+
```yaml
3454+
properties:
3455+
animals:
3456+
type: array
3457+
xml:
3458+
nodeType: element
3459+
name: animals
3460+
items:
3461+
properties:
3462+
kind:
3463+
type: string
3464+
xml:
3465+
nodeType: attribute
3466+
name: animal
3467+
content:
3468+
type: string
3469+
xml:
3470+
nodeType: text
3471+
```
3472+
3473+
```xml
3474+
<animals>
3475+
<animal kind="Cat">Fluffy</animals>
3476+
<animal kind="Dog">Fido</animals>
3477+
<animals>
3478+
```
3479+
3480+
###### Referenced Element With CDATA
3481+
3482+
In this example, no element is created for the Schema Object that contains only the `$ref`, as its `nodeType` defaults to `none`.
3483+
It is necessary to create a subschema for the CDATA section as otherwise the content would be treated as an implicit node of type `text`.
3484+
3485+
```yaml
3486+
paths:
3487+
/docs:
3488+
get:
3489+
responses:
3490+
"200":
3491+
content:
3492+
application/xml:
3493+
$ref: "#/components/schemas/Documentation"
3494+
components:
3495+
schemas:
3496+
Documentation:
3497+
type: object
3498+
properties:
3499+
content:
3500+
type: string
3501+
contentMediaType: text/html
3502+
xml:
3503+
nodeType: cdata
3504+
```
3505+
3506+
```xml
3507+
<Documentation>
3508+
<![CDATA[<html><head><title>Awesome Docs</title></head><body></body><html>]]>
3509+
</Documentation>
3510+
```
3511+
3512+
###### Element With Text Before and After a Child Element
3513+
3514+
In this example, `prefixItems` is used to control the ordering.
3515+
Since `prefixItems` works with arrays, we need to explicitly set the `nodeType` to `element`.
3516+
Within `prefixItems`, we need to explicitly set the `nodeType` of the `text` nodes, but do not need a name, while the data node's default `nodeType` of `element` is correct, but it needs an explicit `name`:
3517+
3518+
```yaml
3519+
components:
3520+
schemas:
3521+
Report:
3522+
type: array
3523+
xml:
3524+
nodeType: element
3525+
prefixItems:
3526+
- type: string
3527+
xml:
3528+
nodeType: text
3529+
- type: number
3530+
xml:
3531+
name: data
3532+
- type: string
3533+
xml:
3534+
nodeType: text
3535+
```
3536+
3537+
```xml
3538+
<Report>Some preamble text.<data>42</data>Some postamble text.</Report>
3539+
```
3540+
33973541
#### Security Scheme Object
33983542

33993543
Defines a security scheme that can be used by the operations.

0 commit comments

Comments
 (0)