Skip to content

Commit 445487b

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 45e207a commit 445487b

2 files changed

Lines changed: 227 additions & 70 deletions

File tree

src/oas.md

Lines changed: 212 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,7 +2475,7 @@ JSON Schema implementations MAY choose to treat keywords defined by the OpenAPI
24752475
| Field Name | Type | Description |
24762476
| ---- | :----: | ---- |
24772477
| <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. |
2478-
| <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. |
2478+
| <a name="schema-xml"></a>xml | [XML Object](#xml-object) | Adds additional metadata to describe the XML representation of this schema. |
24792479
| <a name="schema-external-docs"></a>externalDocs | [External Documentation Object](#external-documentation-object) | Additional external documentation for this schema. |
24802480
| <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. |
24812481

@@ -3077,52 +3077,100 @@ will map to `#/components/schemas/Dog` because the `dog` entry in the `mapping`
30773077
#### XML Object
30783078

30793079
A metadata object that allows for more fine-tuned XML model definitions.
3080-
3081-
When using arrays, XML element names are _not_ inferred (for singular/plural forms) and the `name` field SHOULD be used to add that information.
3082-
See examples for expected behavior.
3080+
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.
30833081

30843082
##### Fixed Fields
30853083

30863084
| Field Name | Type | Description |
30873085
| ---- | :----: | ---- |
3088-
| <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. |
3086+
| <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. |
3087+
| <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`. |
30893088
| <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. |
30903089
| <a name="xml-prefix"></a>prefix | `string` | The prefix to be used for the [name](#xml-name). |
3091-
| <a name="xml-attribute"></a>attribute | `boolean` | Declares whether the property definition translates to an attribute instead of an element. Default value is `false`. |
3092-
| <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`). |
3090+
| <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` |
3091+
| <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` |
3092+
3093+
Note that when generating an XML document from object data, the order of the nodes is undefined.
3094+
Use `prefixItems` to control node ordering.
3095+
3096+
See [Appendix B](#appendix-b-data-type-conversion) for a discussion of converting values of various types to string representations.
30933097

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

3100+
##### XML Node Types
3101+
3102+
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.
3103+
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:
3104+
3105+
* `element` (1): The schema represents an element and describes its contents
3106+
* `attribute` (2): The schema represents an attribute and describes its value
3107+
* `text` (3): The schema represents a text node (parsed character data)
3108+
* `cdata` (4): The schema represents a CDATA section
3109+
* `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
3110+
3111+
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.
3112+
3113+
###### Modeling Element Lists
3114+
3115+
For historical compatibility, schemas of `type: array` default to `nodeType: none`, placing the nodes for each array item directly under the parent node.
3116+
This also aligns with the inferred naming behavior defined under [XML Node Names](#xml-node-names).
3117+
3118+
To produce an element wrapping the list, set an explicit `nodeType: element` on the `type: array` schema.
3119+
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.
3120+
See examples for expected behavior.
3121+
3122+
###### Implicit and Explicit `text` Nodes
3123+
3124+
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).
3125+
3126+
Explicit `text` nodes are necessary if an element has both attributes and content.
3127+
3128+
Note that placing two `text` nodes adjacent to each other is ambiguous for parsing, and the resulting behavior is implementation-defined.
3129+
3130+
##### XML Node Names
3131+
3132+
The `element` and `attribute` node types require a name, which MUST be inferred from the schema as follows, unless overridden by the `name` field:
3133+
3134+
* For schemas directly under the [Components Object's](#components-object) `schemas` field, the component name is the inferred name.
3135+
* For property schemas, and for array item schemas under a property schema, the property name is the inferred name
3136+
* 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
3137+
3138+
Note that when using arrays, singular vs plural forms are _not_ inferred, and must be set explicitly.
3139+
3140+
##### Namespace Limitations
3141+
30963142
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:
30973143

30983144
* 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.
30993145
* XML allows but discourages relative IRI-references, while this specification outright forbids them.
31003146

31013147
##### XML Object Examples
31023148

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

3106-
###### No XML Element
3152+
###### No XML Object
31073153

3108-
Basic string property:
3154+
Basic string property (`nodeType` is `element` by default):
31093155

31103156
```yaml
3111-
animals:
3112-
type: string
3157+
properties:
3158+
animals:
3159+
type: string
31133160
```
31143161

31153162
```xml
31163163
<animals>...</animals>
31173164
```
31183165

3119-
Basic string array property ([`wrapped`](#xml-wrapped) is `false` by default):
3166+
Basic string array property (`nodeType` is `none` by default):
31203167

31213168
```yaml
3122-
animals:
3123-
type: array
3124-
items:
3125-
type: string
3169+
properties:
3170+
animals:
3171+
type: array
3172+
items:
3173+
type: string
31263174
```
31273175

31283176
```xml
@@ -3134,10 +3182,11 @@ animals:
31343182
###### XML Name Replacement
31353183

31363184
```yaml
3137-
animals:
3138-
type: string
3139-
xml:
3140-
name: animal
3185+
properties:
3186+
animals:
3187+
type: string
3188+
xml:
3189+
name: animal
31413190
```
31423191

31433192
```xml
@@ -3146,7 +3195,6 @@ animals:
31463195

31473196
###### XML Attribute, Prefix and Namespace
31483197

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

31523200
```yaml
@@ -3178,46 +3226,49 @@ components:
31783226
Changing the element names:
31793227

31803228
```yaml
3181-
animals:
3182-
type: array
3183-
items:
3184-
type: string
3185-
xml:
3186-
name: animal
3229+
properties:
3230+
animals:
3231+
type: array
3232+
items:
3233+
type: string
3234+
xml:
3235+
name: animal
31873236
```
31883237

31893238
```xml
31903239
<animal>value</animal>
31913240
<animal>value</animal>
31923241
```
31933242

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

31963245
```yaml
3197-
animals:
3198-
type: array
3199-
items:
3200-
type: string
3246+
properties:
3247+
animals:
3248+
type: array
3249+
items:
3250+
type: string
3251+
xml:
3252+
name: animal
32013253
xml:
3202-
name: animal
3203-
xml:
3204-
name: aliens
3254+
name: aliens
32053255
```
32063256

32073257
```xml
32083258
<animal>value</animal>
32093259
<animal>value</animal>
32103260
```
32113261

3212-
Even when the array is wrapped, if a name is not explicitly defined, the same name will be used both internally and externally:
3262+
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:
32133263

32143264
```yaml
3215-
animals:
3216-
type: array
3217-
items:
3218-
type: string
3219-
xml:
3220-
wrapped: true
3265+
properties:
3266+
animals:
3267+
type: array
3268+
items:
3269+
type: string
3270+
xml:
3271+
nodeType: element
32213272
```
32223273

32233274
```xml
@@ -3230,14 +3281,15 @@ animals:
32303281
To overcome the naming problem in the example above, the following definition can be used:
32313282

32323283
```yaml
3233-
animals:
3234-
type: array
3235-
items:
3236-
type: string
3284+
properties:
3285+
animals:
3286+
type: array
3287+
items:
3288+
type: string
3289+
xml:
3290+
name: animal
32373291
xml:
3238-
name: animal
3239-
xml:
3240-
wrapped: true
3292+
nodeType: element
32413293
```
32423294

32433295
```xml
@@ -3247,18 +3299,19 @@ animals:
32473299
</animals>
32483300
```
32493301

3250-
Affecting both internal and external names:
3302+
Affecting both wrapping element and item element names:
32513303

32523304
```yaml
3253-
animals:
3254-
type: array
3255-
items:
3256-
type: string
3305+
properties:
3306+
animals:
3307+
type: array
3308+
items:
3309+
type: string
3310+
xml:
3311+
name: animal
32573312
xml:
3258-
name: animal
3259-
xml:
3260-
name: aliens
3261-
wrapped: true
3313+
name: aliens
3314+
nodeType: element
32623315
```
32633316

32643317
```xml
@@ -3268,16 +3321,17 @@ animals:
32683321
</aliens>
32693322
```
32703323

3271-
If we change the external element but not the internal ones:
3324+
If we change the wrapping element name but not the item element names:
32723325

32733326
```yaml
3274-
animals:
3275-
type: array
3276-
items:
3277-
type: string
3278-
xml:
3279-
name: aliens
3280-
wrapped: true
3327+
properties:
3328+
animals:
3329+
type: array
3330+
items:
3331+
type: string
3332+
xml:
3333+
name: aliens
3334+
nodeType: element
32813335
```
32823336

32833337
```xml
@@ -3287,6 +3341,96 @@ animals:
32873341
</aliens>
32883342
```
32893343

3344+
###### Elements With Attributes And Text
3345+
3346+
```yaml
3347+
properties:
3348+
animals:
3349+
type: array
3350+
xml:
3351+
nodeType: element
3352+
name: animals
3353+
items:
3354+
properties:
3355+
kind:
3356+
type: string
3357+
xml:
3358+
nodeType: attribute
3359+
name: animal
3360+
content:
3361+
type: string
3362+
xml:
3363+
nodeType: text
3364+
```
3365+
3366+
```xml
3367+
<animals>
3368+
<animal kind="Cat">Fluffy</animals>
3369+
<animal kind="Dog">Fido</animals>
3370+
<animals>
3371+
```
3372+
3373+
###### Referenced Element With CDATA
3374+
3375+
In this example, no element is created for the Schema Object that contains only the `$ref`, as its `nodeType` defaults to `none`.
3376+
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`.
3377+
3378+
```yaml
3379+
paths:
3380+
/docs:
3381+
get:
3382+
responses:
3383+
"200":
3384+
content:
3385+
application/xml:
3386+
$ref: "#/components/schemas/Documentation"
3387+
components:
3388+
schemas:
3389+
Documentation:
3390+
type: object
3391+
properties:
3392+
content:
3393+
type: string
3394+
contentMediaType: text/html
3395+
xml:
3396+
nodeType: cdata
3397+
```
3398+
3399+
```xml
3400+
<Documentation>
3401+
<![CDATA[<html><head><title>Awesome Docs</title></head><body></body><html>]]>
3402+
</Documentation>
3403+
```
3404+
3405+
###### Element With Text Before and After a Child Element
3406+
3407+
In this example, `prefixItems` is used to control the ordering.
3408+
Since `prefixItems` works with arrays, we need to explicitly set the `nodeType` to `element`.
3409+
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`:
3410+
3411+
```yaml
3412+
components:
3413+
schemas:
3414+
Report:
3415+
type: array
3416+
xml:
3417+
nodeType: element
3418+
prefixItems:
3419+
- type: string
3420+
xml:
3421+
nodeType: text
3422+
- type: number
3423+
xml:
3424+
name: data
3425+
- type: string
3426+
xml:
3427+
nodeType: text
3428+
```
3429+
3430+
```xml
3431+
<Report>Some preamble text.<data>42</data>Some postamble text.</Report>
3432+
```
3433+
32903434
#### Security Scheme Object
32913435

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

0 commit comments

Comments
 (0)