Skip to content

Commit bdce8c5

Browse files
committed
rfc: Implement generators for XML text and attribute
1 parent 0caf4db commit bdce8c5

1 file changed

Lines changed: 175 additions & 0 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
---
2+
name: implement-generators-for-xml-text-and-attribute
3+
started: 2024-02-10
4+
pr: pact-foundation/roadmap#0000
5+
tracking_issue: pact-foundation/roadmap#0000
6+
---
7+
## Summary
8+
9+
This RFC proposes implementing generators for bodies of type `application/xml`.
10+
11+
## Motivation
12+
13+
Currently if we define generators for text or attribute of XML's body, mock server will return this error:
14+
15+
> Generators are not supported with XML
16+
17+
And there will be an error message in the log:
18+
19+
> UNIMPLEMENTED: Generators are not currently supported with XML
20+
21+
To fix this error, we need to implement generators for XML.
22+
23+
## Guide-level explanation
24+
25+
### Text
26+
27+
To define generator for XML element's text, we can use this JSON format:
28+
29+
```json
30+
{
31+
"name": "release-date",
32+
"children": [
33+
{
34+
"pact:generator:type": "Date",
35+
"matcher": {
36+
"format": "dd-MM-yyyy",
37+
"pact:matcher:type": "date"
38+
},
39+
"content": ""
40+
}
41+
],
42+
"attributes": []
43+
}
44+
```
45+
46+
Mock server should return XML response like this:
47+
48+
```xml
49+
<?xml version='1.0'?><movie><release-date>27-11-2012</release-date></movie>
50+
```
51+
52+
### Attribute
53+
54+
To define generator for XML element's attribute, we can use this JSON format:
55+
56+
57+
```json
58+
{
59+
"name": "specs",
60+
"children": [],
61+
"attributes": {
62+
"runtime": {
63+
"pact:generator:type": "Regex",
64+
"regex": "\\d+ hours [0-5]?[0-9] minutes",
65+
"pact:matcher:type": "regex",
66+
"value": ""
67+
},
68+
"aspect-ratio": {
69+
"pact:generator:type": "Regex",
70+
"regex": "([0-9]+[.])?[0-9]+:[0-9]+",
71+
"pact:matcher:type": "regex",
72+
"value": ""
73+
},
74+
"color": {
75+
"pact:generator:type": "Regex",
76+
"regex": "color|black&white",
77+
"pact:matcher:type": "regex",
78+
"value": ""
79+
}
80+
}
81+
}
82+
```
83+
84+
Mock server should return XML response like this:
85+
86+
```xml
87+
<?xml version='1.0'?><movie><specs runtime='1 hours 23 minutes' aspect-ratio='3:4' color='color'/></movie>
88+
```
89+
90+
## Reference-level explanation
91+
92+
### Implementation
93+
94+
- Begin at root element
95+
- Apply generator for each attribute
96+
- Apply generator for each child element (recursively)
97+
- Apply generator for each child text
98+
- If there are no text & there is generator for text, then generate text and append to the element
99+
100+
### Corner cases
101+
102+
#### Text
103+
104+
- Element has no text
105+
- Generator: `RandomInt(0, 999)`
106+
- Path: `$.a['#text']`
107+
- Before: `<?xml version='1.0'?><a></a>`
108+
- After: `<?xml version='1.0'?><a>123</a>`
109+
- Note: New child text is append to the element
110+
- Element has a child element
111+
- Generator: `RandomInt(0, 999)`
112+
- Path: `$.a['#text']`
113+
- Before: `<?xml version='1.0'?><a><b/></a>`
114+
- After: `<?xml version='1.0'?><a><b/>123</a>`
115+
- Note: New child text is append to the element
116+
- Element has mixed children
117+
- Generator: `RandomInt(0, 999)`
118+
- Path: `$.a['#text']`
119+
- Before: `<?xml version='1.0'?><a><b/>-1</a>`
120+
- After: `<?xml version='1.0'?><a><b/>123</a>`
121+
- Note: New child text is append to the element
122+
- Element has multiple texts
123+
- Generator: `RandomInt(0, 999)`
124+
- Path: `$.a['#text']`
125+
- Before: `<?xml version='1.0'?><a>-1<b/>-2</a>`
126+
- After: `<?xml version='1.0'?><a>123<b/>234</a>`
127+
- Note: We can't define index for the text (e.g. can't do this `$.a['#text'][0]` or this `$.a['#text'][1]`), the same generator is applied to every texts
128+
- Element has namespace
129+
- Generator: `RandomInt(0, 999)`
130+
- Path: `$.n:a['#text']`
131+
- Before: `<?xml version='1.0'?><n:a xmlns:n='http://example.com/namespace'>-1</n:a>`
132+
- After: `<?xml version='1.0'?><n:a xmlns:n='http://example.com/namespace'>123</n:a>`
133+
- Element has mixed namespace
134+
- Generator: `RandomInt(0, 999)`
135+
- Path: `$.root.n:a['#text']`
136+
- Before: `<?xml version='1.0'?><root><n:a xmlns:n='http://example.com/namespace'>-1</n:a><a>-2</a></root>`
137+
- After: `<?xml version='1.0'?><root><n:a xmlns:n='http://example.com/namespace'>123</n:a><a>-2</a></root>`
138+
139+
140+
#### Attribute
141+
142+
- Attribute has namespace
143+
- Generator: `RandomInt(0, 999)`
144+
- Path: `$.a['@n:attr']`
145+
- Before: `<?xml version='1.0'?><a n:attr='-1' xmlns:n='http://example.com/namespace'/>`
146+
- After: `<?xml version='1.0'?><a n:attr='123' xmlns:n='http://example.com/namespace'/>`
147+
- Attribute has mixed namespace
148+
- Generator: `RandomInt(0, 999)`
149+
- Path: `$.a['@n:attr']`
150+
- Before: `<?xml version='1.0'?><a n:attr='-1' attr='-2' xmlns:n='http://example.com/namespace'/>`
151+
- After: `<?xml version='1.0'?><a n:attr='123' attr='-2' xmlns:n='http://example.com/namespace'/>`
152+
153+
## Drawbacks
154+
155+
None
156+
157+
## Rationale and alternatives
158+
159+
None
160+
161+
## Unresolved questions
162+
163+
None
164+
165+
## Future possibilities
166+
167+
In the future, when we can define index for the text, then we can define different matcher/generator for each text, then we can apply different generator for each text:
168+
169+
- Generators:
170+
- Path: `$.a['#text'][0]`
171+
Generator: `RandomInt(0, 999)`
172+
- Path: `$.a['#text'][1]`
173+
Generator: `RandomString(3)`
174+
- Before: `<?xml version='1.0'?><a>-1<b/>-2</a>`
175+
- After: `<?xml version='1.0'?><a>123<b/>abc</a>`

0 commit comments

Comments
 (0)