kwalify 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +340 -0
- data/ChangeLog +62 -0
- data/README.txt +38 -0
- data/bin/kwalify +185 -0
- data/doc/docstyle.css +188 -0
- data/doc/users-guide.html +706 -0
- data/examples/address-book/Makefile +4 -0
- data/examples/address-book/address-book.schema.yaml +43 -0
- data/examples/address-book/address-book.yaml +36 -0
- data/examples/invoice/Makefile +3 -0
- data/examples/invoice/invoice.schema.yaml +59 -0
- data/examples/invoice/invoice.yaml +32 -0
- data/lib/kwalify.rb +10 -0
- data/lib/kwalify/error-msg.rb +41 -0
- data/lib/kwalify/errors.rb +112 -0
- data/lib/kwalify/meta-validator.rb +137 -0
- data/lib/kwalify/types.rb +70 -0
- data/lib/kwalify/util/assert-diff.rb +44 -0
- data/lib/kwalify/util/option-parser.rb +220 -0
- data/lib/kwalify/util/yaml-helper.rb +82 -0
- data/lib/kwalify/validator.rb +286 -0
- data/setup.rb +1331 -0
- data/test/test.rb +364 -0
- data/todo.txt +21 -0
- metadata +66 -0
data/doc/docstyle.css
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
body {
|
2
|
+
background-color:#FFFFFF;
|
3
|
+
}
|
4
|
+
|
5
|
+
.mainbody {
|
6
|
+
color:#333333;
|
7
|
+
line-height:150%;
|
8
|
+
margin: 5px 30px 5px 30px;
|
9
|
+
}
|
10
|
+
|
11
|
+
a:link, a:active, a:hover {
|
12
|
+
color:#CC6600;
|
13
|
+
}
|
14
|
+
|
15
|
+
a:visited {
|
16
|
+
color:#DD9900;
|
17
|
+
}
|
18
|
+
|
19
|
+
p {
|
20
|
+
color:#333333;
|
21
|
+
line-height:150%;
|
22
|
+
}
|
23
|
+
|
24
|
+
pre {
|
25
|
+
width: 100%;
|
26
|
+
line-height:130%;
|
27
|
+
white-space:pre;
|
28
|
+
}
|
29
|
+
|
30
|
+
.program {
|
31
|
+
border-style:solid;
|
32
|
+
border-width:1px;
|
33
|
+
border-color:#6699FF;
|
34
|
+
color:#333333;
|
35
|
+
background-color:#DDEEFF;
|
36
|
+
padding:8px 9px 8px 9px;
|
37
|
+
margin:0px;
|
38
|
+
word-break:break-all;
|
39
|
+
}
|
40
|
+
|
41
|
+
.terminal {
|
42
|
+
border-style:solid;
|
43
|
+
border-width:1;
|
44
|
+
border-color:#999999;
|
45
|
+
color:#333333;
|
46
|
+
background-color:#E0E0E0;
|
47
|
+
padding:9px 10px 9px 10px;
|
48
|
+
margin:0px;
|
49
|
+
word-break:break-all;
|
50
|
+
}
|
51
|
+
|
52
|
+
.output {
|
53
|
+
border-style:solid;
|
54
|
+
border-width:1px;
|
55
|
+
border-color:#CCCCCC;
|
56
|
+
color:#333333;
|
57
|
+
background-color:#FFFFFF;
|
58
|
+
padding:8px 9px 8px 9px;
|
59
|
+
margin:0px;
|
60
|
+
word-break:break-all;
|
61
|
+
}
|
62
|
+
|
63
|
+
|
64
|
+
.program_caption {
|
65
|
+
margin-top: 20px;
|
66
|
+
}
|
67
|
+
|
68
|
+
.terminal_caption {
|
69
|
+
margin-top: 20px;
|
70
|
+
}
|
71
|
+
|
72
|
+
.output_caption {
|
73
|
+
margin-top: 20px;
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
ul,ol,dl {
|
78
|
+
/* margin:0px; */
|
79
|
+
/* padding:0px; */
|
80
|
+
color:#333333;
|
81
|
+
line-height:140%;
|
82
|
+
}
|
83
|
+
|
84
|
+
.dt2, .dt3 {
|
85
|
+
font-weight:bold;
|
86
|
+
}
|
87
|
+
|
88
|
+
.table1 {
|
89
|
+
padding:2px;
|
90
|
+
color:#333333;
|
91
|
+
background-color:#DDDDCC;
|
92
|
+
line-height:130%;
|
93
|
+
/*
|
94
|
+
border-width:1px;
|
95
|
+
border-style:solid;
|
96
|
+
border-color:#FFFFFF;
|
97
|
+
*/
|
98
|
+
margin:5;
|
99
|
+
}
|
100
|
+
|
101
|
+
.th1, .th2 {
|
102
|
+
padding:1px;
|
103
|
+
color:#333333;
|
104
|
+
/* background-color:#DDDDCC; */
|
105
|
+
background-color:#CCCCBB;
|
106
|
+
line-height:130%;
|
107
|
+
}
|
108
|
+
|
109
|
+
.td1, .th2 {
|
110
|
+
padding:1px;
|
111
|
+
color:#333333;
|
112
|
+
background-color:#EEEEDD;
|
113
|
+
line-height:130%;
|
114
|
+
}
|
115
|
+
|
116
|
+
.caption1, .caption2 {
|
117
|
+
/* font-size:x-small; */
|
118
|
+
color:#333333;
|
119
|
+
}
|
120
|
+
|
121
|
+
.table2 {
|
122
|
+
padding:1px;
|
123
|
+
color:#333333;
|
124
|
+
background-color:#DDDDCC;
|
125
|
+
line-height:130%;
|
126
|
+
/*
|
127
|
+
border-width:1px;
|
128
|
+
border-style:solid;
|
129
|
+
border-color:#FFFFFF;
|
130
|
+
*/
|
131
|
+
margin:5;
|
132
|
+
}
|
133
|
+
|
134
|
+
h1, .chapter, .doctitle {
|
135
|
+
color:#333333;
|
136
|
+
font-weight:bold;
|
137
|
+
padding:30px 0px 10px 0px;
|
138
|
+
}
|
139
|
+
|
140
|
+
h2, .section {
|
141
|
+
color:#333333;
|
142
|
+
font-weight:bold;
|
143
|
+
border-style:solid;
|
144
|
+
border-color:#6699FF;
|
145
|
+
border-width:0px 0px 2px 30px;
|
146
|
+
padding:10px 20px 0px 5px;
|
147
|
+
}
|
148
|
+
|
149
|
+
h3, .subsection {
|
150
|
+
color:#333333;
|
151
|
+
font-weight:bold;
|
152
|
+
border-style:solid;
|
153
|
+
border-color:#6699FF;
|
154
|
+
border-width: 0px 0px 0px 15px;
|
155
|
+
padding: 10px 20px 0px 5px;
|
156
|
+
}
|
157
|
+
|
158
|
+
.em {
|
159
|
+
font-weight:bold;
|
160
|
+
}
|
161
|
+
|
162
|
+
.toc {
|
163
|
+
/* font-size:small; */
|
164
|
+
/* line-height:100%; */
|
165
|
+
}
|
166
|
+
|
167
|
+
.footnote {
|
168
|
+
font-size:small;
|
169
|
+
}
|
170
|
+
|
171
|
+
.note {
|
172
|
+
background-color:#FFFFDD;
|
173
|
+
border-style:solid;
|
174
|
+
border-width:0px 1px 0px 1px;
|
175
|
+
border-color:#DDDD66;
|
176
|
+
color:#333300;
|
177
|
+
/* font-size:small; */
|
178
|
+
line-height:120%;
|
179
|
+
padding: 5px 20px 5px 20px;
|
180
|
+
}
|
181
|
+
|
182
|
+
.figure {
|
183
|
+
/*
|
184
|
+
border-width:1px;
|
185
|
+
border-color:#DDDD66;
|
186
|
+
white-space:pre;
|
187
|
+
*/
|
188
|
+
}
|
@@ -0,0 +1,706 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-Type" content="text/html">
|
5
|
+
<title>Kwalify Users' Guide</title>
|
6
|
+
<meta name="author" content="makoto kuwata <kwa(at)kuwata-lab.com>">
|
7
|
+
<meta name="generator" content="kwaser">
|
8
|
+
<meta http-equiv="Content-Style-Type" content="text/css">
|
9
|
+
<link rel="stylesheet" href="docstyle.css" type="text/css">
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
|
13
|
+
<div class="mainbody">
|
14
|
+
|
15
|
+
<div align="left"><h1>Kwalify Users' Guide</h1></div>
|
16
|
+
<div align="left">
|
17
|
+
makoto kuwata <kwa(at)kuwata-lab.com><br>
|
18
|
+
last update: $Date: 2005-08-01 06:48:56 +0900 (Mon, 01 Aug 2005) $<br>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<a name="preface"></a>
|
22
|
+
<h2 class="section1">Preface</h2>
|
23
|
+
<p>Kwalify<sup>(<a href="#fnref:1" name="fnlink:1">*1</a>)</sup> is a tiny schema validator for YAML document.
|
24
|
+
</p>
|
25
|
+
<p>Kwalify is in fact very poor compared to Relax NG or DTD.
|
26
|
+
I hope you extend/customize Kwalify for your own way.
|
27
|
+
</p>
|
28
|
+
Table of Contents:
|
29
|
+
<div class="toc">
|
30
|
+
<ul>
|
31
|
+
<li><a href="#preface">Preface</a>
|
32
|
+
</li>
|
33
|
+
<li><a href="#usage">Usage of Kwalify</a>
|
34
|
+
<ul>
|
35
|
+
<li><a href="#usage1">Usage in Command-Line</a>
|
36
|
+
</li>
|
37
|
+
<li><a href="#usage2">Usage in Ruby Script</a>
|
38
|
+
</li>
|
39
|
+
</ul>
|
40
|
+
</li>
|
41
|
+
<li><a href="#schema">Schema Definition</a>
|
42
|
+
<ul>
|
43
|
+
<li><a href="#schema-seq">Sequence</a>
|
44
|
+
</li>
|
45
|
+
<li><a href="#schema-map">Mapping</a>
|
46
|
+
</li>
|
47
|
+
<li><a href="#schema-seq-of-map">Sequence of Mapping</a>
|
48
|
+
</li>
|
49
|
+
<li><a href="#schema-map-of-seq">Mapping of Sequence</a>
|
50
|
+
</li>
|
51
|
+
<li><a href="#schema-rules">Rules</a>
|
52
|
+
</li>
|
53
|
+
<li><a href="#schema-block">Validator with Block</a>
|
54
|
+
</li>
|
55
|
+
</ul>
|
56
|
+
</li>
|
57
|
+
<li><a href="#tips">Tips</a>
|
58
|
+
<ul>
|
59
|
+
<li><a href="#tips-quotes">Enclose Key Names in (Double) Quotes</a>
|
60
|
+
</li>
|
61
|
+
<li><a href="#tips-anchor">Anchor</a>
|
62
|
+
</li>
|
63
|
+
</ul>
|
64
|
+
</li>
|
65
|
+
</ul>
|
66
|
+
</div>
|
67
|
+
<div class="footnote">
|
68
|
+
<dl compact>
|
69
|
+
<dt>(<a name="fnref:1" href="#fnlink:1">*1</a>)</dt>
|
70
|
+
<dd>Pronounce as 'Qualify'.</dd>
|
71
|
+
</dl>
|
72
|
+
</div>
|
73
|
+
<br>
|
74
|
+
|
75
|
+
|
76
|
+
<a name="usage"></a>
|
77
|
+
<h2 class="section1">Usage of Kwalify</h2>
|
78
|
+
<a name="usage1"></a>
|
79
|
+
<h3 class="section2">Usage in Command-Line</h3>
|
80
|
+
<div class="terminal_caption">
|
81
|
+
usage1: validate YAML document in command-line</div>
|
82
|
+
<pre class="terminal">$ kwalify -f schema.yaml document.yaml [document2.yaml ...]
|
83
|
+
</pre>
|
84
|
+
<div class="terminal_caption">
|
85
|
+
usage2: validate schema definition in command-line</div>
|
86
|
+
<pre class="terminal">$ kwalify -m schema.yaml [schema2.yaml ...]
|
87
|
+
</pre>
|
88
|
+
<p>Command-line options:
|
89
|
+
</p>
|
90
|
+
<dl class="dl3">
|
91
|
+
<dt class="dt3"><strong>
|
92
|
+
<code>-h</code>, <code>--help</code></strong></dt>
|
93
|
+
<dd class="dd3">
|
94
|
+
Print help message.
|
95
|
+
</dd>
|
96
|
+
<dt class="dt3"><strong>
|
97
|
+
<code>-v</code> </strong></dt>
|
98
|
+
<dd class="dd3">
|
99
|
+
Print version.
|
100
|
+
</dd>
|
101
|
+
<dt class="dt3"><strong>
|
102
|
+
<code>-s</code> </strong></dt>
|
103
|
+
<dd class="dd3">
|
104
|
+
Silent mode.
|
105
|
+
</dd>
|
106
|
+
<dt class="dt3"><strong>
|
107
|
+
<code>-f <em>schema.yaml</em></code> </strong></dt>
|
108
|
+
<dd class="dd3">
|
109
|
+
Specify schema definition file.
|
110
|
+
</dd>
|
111
|
+
<dt class="dt3"><strong>
|
112
|
+
<code>-m</code> </strong></dt>
|
113
|
+
<dd class="dd3">
|
114
|
+
Meta-validation of schema definition.
|
115
|
+
</dd>
|
116
|
+
<dt class="dt3"><strong>
|
117
|
+
<code>-t</code> </strong></dt>
|
118
|
+
<dd class="dd3">
|
119
|
+
Expand tab characters to spaces automatically.
|
120
|
+
</dd>
|
121
|
+
</dl>
|
122
|
+
<br>
|
123
|
+
|
124
|
+
|
125
|
+
<a name="usage2"></a>
|
126
|
+
<h3 class="section2">Usage in Ruby Script</h3>
|
127
|
+
<div class="program_caption">
|
128
|
+
validate YAML document in Ruby script</div>
|
129
|
+
<pre class="program">require 'kwalify'
|
130
|
+
|
131
|
+
## parse schema definition and create validator
|
132
|
+
str = File.read('schema.yaml')
|
133
|
+
schema_def = YAML.load(str)
|
134
|
+
validator = Kwalify::Validator.new(schema_def) # raises Kwalify::SchemaError if wrong
|
135
|
+
|
136
|
+
## validate YAML document
|
137
|
+
str = File.read('document.yaml')
|
138
|
+
document = YAML.load(str)
|
139
|
+
error_list = validator.validate(document)
|
140
|
+
unless error_list.empty?
|
141
|
+
error_list.each do |error| # error is Kwalify::ValidationException
|
142
|
+
print error.message
|
143
|
+
end
|
144
|
+
end
|
145
|
+
</pre>
|
146
|
+
<br>
|
147
|
+
|
148
|
+
|
149
|
+
<br>
|
150
|
+
|
151
|
+
|
152
|
+
<a name="schema"></a>
|
153
|
+
<h2 class="section1">Schema Definition</h2>
|
154
|
+
<a name="schema-seq"></a>
|
155
|
+
<h3 class="section2">Sequence</h3>
|
156
|
+
<a name="schema01.yaml"></a>
|
157
|
+
<div class="program_caption">
|
158
|
+
<code>schema01.yaml</code> : sequence of string</div>
|
159
|
+
<pre class="program">type: seq
|
160
|
+
sequence:
|
161
|
+
- type: string
|
162
|
+
</pre>
|
163
|
+
<a name="document01a.yaml"></a>
|
164
|
+
<div class="program_caption">
|
165
|
+
<code>document01a.yaml</code> : valid document example</div>
|
166
|
+
<pre class="program">- foo
|
167
|
+
- bar
|
168
|
+
- baz
|
169
|
+
</pre>
|
170
|
+
<div class="terminal_caption">
|
171
|
+
validate</div>
|
172
|
+
<pre class="terminal">$ kwalify -f schema01.yaml document01a.yaml
|
173
|
+
document01a.yaml#1: valid.
|
174
|
+
</pre>
|
175
|
+
<a name="document01b.yaml"></a>
|
176
|
+
<div class="program_caption">
|
177
|
+
<code>document01b.yaml</code> : invalid document example</div>
|
178
|
+
<pre class="program">- foo
|
179
|
+
- 123
|
180
|
+
- baz
|
181
|
+
</pre>
|
182
|
+
<div class="terminal_caption">
|
183
|
+
validate</div>
|
184
|
+
<pre class="terminal">$ kwalify -f schema01.yaml document01b.yaml
|
185
|
+
document01b.yaml#1: INVALID
|
186
|
+
- [/2] string type expected but got Fixnum.
|
187
|
+
</pre>
|
188
|
+
<p>Default '<code>type:</code>' is <code>string</code> so you can omit '<code>type: string</code>'.
|
189
|
+
</p>
|
190
|
+
<br>
|
191
|
+
|
192
|
+
|
193
|
+
<a name="schema-map"></a>
|
194
|
+
<h3 class="section2">Mapping</h3>
|
195
|
+
<a name="schema02.yaml"></a>
|
196
|
+
<div class="program_caption">
|
197
|
+
<code>schema02.yaml</code> : mapping of scalar</div>
|
198
|
+
<pre class="program">type: map
|
199
|
+
mapping:
|
200
|
+
name:
|
201
|
+
type: string
|
202
|
+
required: yes
|
203
|
+
email:
|
204
|
+
type: string
|
205
|
+
pattern: /@/
|
206
|
+
age:
|
207
|
+
type: integer
|
208
|
+
birth:
|
209
|
+
type: date
|
210
|
+
</pre>
|
211
|
+
<a name="document02a.yaml"></a>
|
212
|
+
<div class="program_caption">
|
213
|
+
<code>document02a.yaml</code> : valid document example</div>
|
214
|
+
<pre class="program">name: foo
|
215
|
+
email: foo@mail.com
|
216
|
+
age: 20
|
217
|
+
birth: 1985-01-01
|
218
|
+
</pre>
|
219
|
+
<div class="terminal_caption">
|
220
|
+
validate</div>
|
221
|
+
<pre class="terminal">$ kwalify -f schema02.yaml document02a.yaml
|
222
|
+
document02a.yaml#1: valid.
|
223
|
+
</pre>
|
224
|
+
<a name="document02b.yaml"></a>
|
225
|
+
<div class="program_caption">
|
226
|
+
<code>document02b.yaml</code> : invalid document example</div>
|
227
|
+
<pre class="program">name: foo
|
228
|
+
email: foo(at)mail.com
|
229
|
+
age: twenty
|
230
|
+
birth: Jun 01, 1985
|
231
|
+
</pre>
|
232
|
+
<div class="terminal_caption">
|
233
|
+
validate</div>
|
234
|
+
<pre class="terminal">$ kwalify -f schema02.yaml document02b.yaml
|
235
|
+
document02b.yaml#1: INVALID
|
236
|
+
- [/birth] date type expected but got String.
|
237
|
+
- [/age] integer type expected but got String.
|
238
|
+
- [/email] 'foo(at)mail.com' is not matched to pattern /@/.
|
239
|
+
</pre>
|
240
|
+
<br>
|
241
|
+
|
242
|
+
|
243
|
+
<a name="schema-seq-of-map"></a>
|
244
|
+
<h3 class="section2">Sequence of Mapping</h3>
|
245
|
+
<a name="schema03.yaml"></a>
|
246
|
+
<div class="program_caption">
|
247
|
+
<code>schema03.yaml</code> : sequence of mapping</div>
|
248
|
+
<pre class="program">type: seq
|
249
|
+
sequence:
|
250
|
+
- type: map
|
251
|
+
mapping:
|
252
|
+
name:
|
253
|
+
type: string
|
254
|
+
required: true
|
255
|
+
email:
|
256
|
+
type: string
|
257
|
+
</pre>
|
258
|
+
<a name="document03a.yaml"></a>
|
259
|
+
<div class="program_caption">
|
260
|
+
<code>document03a.yaml</code> : valid document example</div>
|
261
|
+
<pre class="program">- name: foo
|
262
|
+
email: foo@mail.com
|
263
|
+
- name: bar
|
264
|
+
email: bar@mail.net
|
265
|
+
- name: baz
|
266
|
+
email: baz@mail.org
|
267
|
+
</pre>
|
268
|
+
<div class="terminal_caption">
|
269
|
+
validate</div>
|
270
|
+
<pre class="terminal">$ kwalify -f schema03.yaml document03a.yaml
|
271
|
+
document03a.yaml#1: valid.
|
272
|
+
</pre>
|
273
|
+
<a name="document03b.yaml"></a>
|
274
|
+
<div class="program_caption">
|
275
|
+
<code>document03b.yaml</code> : invalid document example</div>
|
276
|
+
<pre class="program">- name: foo
|
277
|
+
email: foo@mail.com
|
278
|
+
- naem: bar
|
279
|
+
email: bar@mail.net
|
280
|
+
- name: baz
|
281
|
+
mail: baz@mail.org
|
282
|
+
</pre>
|
283
|
+
<div class="terminal_caption">
|
284
|
+
validate</div>
|
285
|
+
<pre class="terminal">$ kwalify -f schema03.yaml document03b.yaml
|
286
|
+
document03b.yaml#1: INVALID
|
287
|
+
- [/2] key 'name' required but not found.
|
288
|
+
- [/2] key 'naem' is not expected.
|
289
|
+
- [/3] key 'mail' is not expected.
|
290
|
+
</pre>
|
291
|
+
<br>
|
292
|
+
|
293
|
+
|
294
|
+
<a name="schema-map-of-seq"></a>
|
295
|
+
<h3 class="section2">Mapping of Sequence</h3>
|
296
|
+
<a name="schema04.yaml"></a>
|
297
|
+
<div class="program_caption">
|
298
|
+
<code>schema04.yaml</code> : mapping of sequence of mapping</div>
|
299
|
+
<pre class="program">type: map
|
300
|
+
mapping:
|
301
|
+
company:
|
302
|
+
type: text
|
303
|
+
required: yes
|
304
|
+
email:
|
305
|
+
type: text
|
306
|
+
employees:
|
307
|
+
type: seq
|
308
|
+
sequence:
|
309
|
+
- type: map
|
310
|
+
mapping:
|
311
|
+
code:
|
312
|
+
type: integer
|
313
|
+
required: yes
|
314
|
+
name:
|
315
|
+
type: string
|
316
|
+
required: yes
|
317
|
+
email:
|
318
|
+
type: string
|
319
|
+
</pre>
|
320
|
+
<a name="document04a.yaml"></a>
|
321
|
+
<div class="program_caption">
|
322
|
+
<code>document04a.yaml</code> : valid document example</div>
|
323
|
+
<pre class="program">company: Kuwata lab.
|
324
|
+
email: webmaster@kuwata-lab.com
|
325
|
+
employees:
|
326
|
+
- code: 101
|
327
|
+
name: foo
|
328
|
+
email: foo@kuwata-lab.com
|
329
|
+
- code: 102
|
330
|
+
name: bar
|
331
|
+
email: bar@kuwata-lab.com
|
332
|
+
</pre>
|
333
|
+
<div class="terminal_caption">
|
334
|
+
validate</div>
|
335
|
+
<pre class="terminal">$ kwalify -f schema04.yaml document04a.yaml
|
336
|
+
document04a.yaml#1: valid.
|
337
|
+
</pre>
|
338
|
+
<a name="document04b.yaml"></a>
|
339
|
+
<div class="program_caption">
|
340
|
+
<code>document04b.yaml</code> : invalid document example</div>
|
341
|
+
<pre class="program">company: Kuwata Lab.
|
342
|
+
email: webmaster@kuwata-lab.com
|
343
|
+
employees:
|
344
|
+
- code: A101
|
345
|
+
name: foo
|
346
|
+
email: foo@kuwata-lab.com
|
347
|
+
- code: 102
|
348
|
+
name: bar
|
349
|
+
mail: bar@kuwata-lab.com
|
350
|
+
</pre>
|
351
|
+
<div class="terminal_caption">
|
352
|
+
validate</div>
|
353
|
+
<pre class="terminal">$ kwalify -f schema04.yaml document04b.yaml
|
354
|
+
document04b.yaml#1: INVALID
|
355
|
+
- [/employees/1/code] integer type expected but got String.
|
356
|
+
- [/employees/2] key 'mail' is not expected.
|
357
|
+
</pre>
|
358
|
+
<br>
|
359
|
+
|
360
|
+
|
361
|
+
<a name="schema-rules"></a>
|
362
|
+
<h3 class="section2">Rules</h3>
|
363
|
+
<dl class="dl3">
|
364
|
+
<dt class="dt3"><strong>
|
365
|
+
<code>required:</code> </strong></dt>
|
366
|
+
<dd class="dd3">
|
367
|
+
Value is required (default is false).
|
368
|
+
</dd>
|
369
|
+
<dt class="dt3"><strong>
|
370
|
+
<code>enum:</code> </strong></dt>
|
371
|
+
<dd class="dd3">
|
372
|
+
List of available values.
|
373
|
+
</dd>
|
374
|
+
<dt class="dt3"><strong>
|
375
|
+
<code>pattern:</code> </strong></dt>
|
376
|
+
<dd class="dd3">
|
377
|
+
Specifies regular expression pattern of value.
|
378
|
+
</dd>
|
379
|
+
<dt class="dt3"><strong>
|
380
|
+
<code>name:</code> </strong></dt>
|
381
|
+
<dd class="dd3">
|
382
|
+
Name of schema.
|
383
|
+
</dd>
|
384
|
+
<dt class="dt3"><strong>
|
385
|
+
<code>desc:</code> </strong></dt>
|
386
|
+
<dd class="dd3">
|
387
|
+
Description. This is not used for validation.
|
388
|
+
</dd>
|
389
|
+
<dt class="dt3"><strong>
|
390
|
+
<code>type:</code> </strong></dt>
|
391
|
+
<dd class="dd3">
|
392
|
+
Type of value. The followings are available:
|
393
|
+
<ul type="circle">
|
394
|
+
<li><code>string</code> (default)
|
395
|
+
</li>
|
396
|
+
<li><code>integer</code>
|
397
|
+
</li>
|
398
|
+
<li><code>float</code>
|
399
|
+
</li>
|
400
|
+
<li><code>number</code> (== integer or float)
|
401
|
+
</li>
|
402
|
+
<li><code>text</code> (== string or number)
|
403
|
+
</li>
|
404
|
+
<li><code>boolean</code>
|
405
|
+
</li>
|
406
|
+
<li><code>date</code>
|
407
|
+
</li>
|
408
|
+
<li><code>time</code>
|
409
|
+
</li>
|
410
|
+
<li><code>seq</code>
|
411
|
+
</li>
|
412
|
+
<li><code>map</code>
|
413
|
+
</li>
|
414
|
+
<li><code>object</code>
|
415
|
+
</li>
|
416
|
+
</ul>
|
417
|
+
</dd>
|
418
|
+
</dl>
|
419
|
+
<a name="schema05.yaml"></a>
|
420
|
+
<div class="program_caption">
|
421
|
+
<code>schema05.yaml</code> : rules examples</div>
|
422
|
+
<pre class="program">type: seq
|
423
|
+
sequence:
|
424
|
+
- type: map
|
425
|
+
mapping:
|
426
|
+
name:
|
427
|
+
#type: string # omittable
|
428
|
+
required: yes
|
429
|
+
email:
|
430
|
+
#type: string # omittable
|
431
|
+
required: yes
|
432
|
+
pattern: /@/
|
433
|
+
age:
|
434
|
+
type: integer
|
435
|
+
blood:
|
436
|
+
#type: string # omittable
|
437
|
+
enum:
|
438
|
+
- A
|
439
|
+
- B
|
440
|
+
- O
|
441
|
+
- AB
|
442
|
+
birth:
|
443
|
+
type: date
|
444
|
+
</pre>
|
445
|
+
<a name="document05a.yaml"></a>
|
446
|
+
<div class="program_caption">
|
447
|
+
<code>document05a.yaml</code> : valid document example</div>
|
448
|
+
<pre class="program">- name: foo
|
449
|
+
email: foo@mail.com
|
450
|
+
age: 20
|
451
|
+
blood: A
|
452
|
+
birth: 1985-01-01
|
453
|
+
- name: bar
|
454
|
+
email: bar@mail.net
|
455
|
+
age: 25
|
456
|
+
blood: AB
|
457
|
+
birth: 1980-01-01
|
458
|
+
</pre>
|
459
|
+
<div class="terminal_caption">
|
460
|
+
validate</div>
|
461
|
+
<pre class="terminal">$ kwalify -f schema05.yaml document05a.yaml
|
462
|
+
document05a.yaml#1: valid.
|
463
|
+
</pre>
|
464
|
+
<a name="document05b.yaml"></a>
|
465
|
+
<div class="program_caption">
|
466
|
+
<code>document05b.yaml</code> : invalid document example</div>
|
467
|
+
<pre class="program">- name: foo
|
468
|
+
email: foo(at)mail.com
|
469
|
+
age: twenty
|
470
|
+
blood: a
|
471
|
+
birth: 1985-01-01
|
472
|
+
- given-name: bar
|
473
|
+
family-name: Bar
|
474
|
+
email: bar@mail.net
|
475
|
+
age: 25
|
476
|
+
blood: AB
|
477
|
+
birth: 1980/01/01
|
478
|
+
</pre>
|
479
|
+
<div class="terminal_caption">
|
480
|
+
validate</div>
|
481
|
+
<pre class="terminal">$ kwalify -f schema05.yaml document05b.yaml
|
482
|
+
document05b.yaml#1: INVALID
|
483
|
+
- [/1/blood] 'a' is invalid enum value.
|
484
|
+
- [/1/age] integer type expected but got String.
|
485
|
+
- [/1/email] 'foo(at)mail.com' is not matched to pattern /@/.
|
486
|
+
- [/2] key 'name' required but not found.
|
487
|
+
- [/2] key 'family-name' is not expected.
|
488
|
+
- [/2] key 'given-name' is not expected.
|
489
|
+
- [/2/birth] date type expected but got String.
|
490
|
+
</pre>
|
491
|
+
<br>
|
492
|
+
|
493
|
+
|
494
|
+
<a name="schema-block"></a>
|
495
|
+
<h3 class="section2">Validator with Block</h3>
|
496
|
+
<p><strong>Notice: This is an experimental feature.</strong>
|
497
|
+
</p>
|
498
|
+
<p><code>Kwalify::Validator.new()</code> method can take a block which is invoked when validation.
|
499
|
+
</p>
|
500
|
+
<a name="validate06.rb"></a>
|
501
|
+
<div class="program_caption">
|
502
|
+
<code>validate06.rb</code> : validate script</div>
|
503
|
+
<pre class="program">#!/usr/bin/env ruby
|
504
|
+
|
505
|
+
require 'kwalify'
|
506
|
+
require 'yaml'
|
507
|
+
|
508
|
+
## load schema definition
|
509
|
+
schema_filename = 'schema06.yaml'
|
510
|
+
schema_str = File.read(schema_filename)
|
511
|
+
schema_hash = YAML.load(schema_str)
|
512
|
+
|
513
|
+
## create validator with a block
|
514
|
+
validator = Kwalify::Validator.new(schema_hash) <strong>{ |schema, data, errors, path|</strong>
|
515
|
+
case <strong>schema.name</strong> ## refer schema name
|
516
|
+
when <strong>"USERNAME"</strong>
|
517
|
+
username = data
|
518
|
+
if username.length > 16
|
519
|
+
errors << Kwalify::ValidationError.new("too long (>16).", path, schema)
|
520
|
+
end
|
521
|
+
when <strong>"AGE"</strong>
|
522
|
+
age = data
|
523
|
+
if age < 13
|
524
|
+
errors << Kwalify::ValidationError.new("too young (<13).", path, schema)
|
525
|
+
elsif age >= 60
|
526
|
+
errors << Kwalify::ValidationError.new("too old (>=60).", path, schema)
|
527
|
+
end
|
528
|
+
end
|
529
|
+
<strong>}</strong>
|
530
|
+
|
531
|
+
## load YAML document
|
532
|
+
input = ARGF.read()
|
533
|
+
document = YAML.load(input)
|
534
|
+
|
535
|
+
## validate
|
536
|
+
errors = validator.validate(document)
|
537
|
+
if errors.empty?
|
538
|
+
puts "Valid."
|
539
|
+
else
|
540
|
+
puts "*** INVALID!"
|
541
|
+
errors.each do |error|
|
542
|
+
# error.class == Kwalify::ValidationError
|
543
|
+
puts " - #{error.message}"
|
544
|
+
end
|
545
|
+
end
|
546
|
+
</pre>
|
547
|
+
<a name="schema06.yaml"></a>
|
548
|
+
<div class="program_caption">
|
549
|
+
<code>schema06.yaml</code> : 'name:' is important.</div>
|
550
|
+
<pre class="program">type: map
|
551
|
+
mapping:
|
552
|
+
members:
|
553
|
+
type: seq
|
554
|
+
sequence:
|
555
|
+
- type: map
|
556
|
+
mapping:
|
557
|
+
username:
|
558
|
+
required: yes
|
559
|
+
<strong>name:</strong> <strong>USERNAME</strong>
|
560
|
+
email:
|
561
|
+
required: yes
|
562
|
+
pattern: /@/
|
563
|
+
age:
|
564
|
+
type: integer
|
565
|
+
<strong>name:</strong> <strong>AGE</strong>
|
566
|
+
</pre>
|
567
|
+
<a name="document06a.yaml"></a>
|
568
|
+
<div class="program_caption">
|
569
|
+
<code>document06a.yaml</code> : valid document example</div>
|
570
|
+
<pre class="program">members:
|
571
|
+
- username: foo
|
572
|
+
email: foo@mail.com
|
573
|
+
age: 19
|
574
|
+
- username: bar
|
575
|
+
email: bar@mail.org
|
576
|
+
age: 21
|
577
|
+
</pre>
|
578
|
+
<div class="terminal_caption">
|
579
|
+
validate</div>
|
580
|
+
<pre class="terminal">$ ruby validate06.rb document06a.yaml
|
581
|
+
Valid.
|
582
|
+
</pre>
|
583
|
+
<a name="document06b.yaml"></a>
|
584
|
+
<div class="program_caption">
|
585
|
+
<code>document06b.yaml</code> : invalid document example</div>
|
586
|
+
<pre class="program">members:
|
587
|
+
- username: toooooooloooooong
|
588
|
+
email: foo@mail.com
|
589
|
+
age: 20
|
590
|
+
- username: bar
|
591
|
+
email: bar@mail.org
|
592
|
+
age: 12
|
593
|
+
</pre>
|
594
|
+
<div class="terminal_caption">
|
595
|
+
validate</div>
|
596
|
+
<pre class="terminal">$ ruby validate06.rb document06b.yaml
|
597
|
+
*** INVALID!
|
598
|
+
- [/members/1/username] too long (>16).
|
599
|
+
- [/members/2/age] too young (<13).
|
600
|
+
</pre>
|
601
|
+
<br>
|
602
|
+
|
603
|
+
|
604
|
+
<br>
|
605
|
+
|
606
|
+
|
607
|
+
<a name="tips"></a>
|
608
|
+
<h2 class="section1">Tips</h2>
|
609
|
+
<a name="tips-quotes"></a>
|
610
|
+
<h3 class="section2">Enclose Key Names in (Double) Quotes</h3>
|
611
|
+
<p>It is allowed to enclose key name in quotes (') or double-quotes (") in YAML.
|
612
|
+
This tip highlights user-defined key names.
|
613
|
+
</p>
|
614
|
+
<div class="program_caption">
|
615
|
+
<code>schema11a.yaml</code> : enclosing in double-quotes</div>
|
616
|
+
<pre class="program">type: map
|
617
|
+
mapping:
|
618
|
+
"name":
|
619
|
+
required: yes
|
620
|
+
"email":
|
621
|
+
pattern: /@/
|
622
|
+
"age":
|
623
|
+
type: integer
|
624
|
+
"birth":
|
625
|
+
type: date
|
626
|
+
</pre>
|
627
|
+
<p>You may prefer to indent with 1 space and 3 spaces.
|
628
|
+
</p>
|
629
|
+
<div class="program_caption">
|
630
|
+
<code>schema11b.yaml</code> : indent with 1 space and 3 spaces</div>
|
631
|
+
<pre class="program">type: map
|
632
|
+
mapping:
|
633
|
+
"name":
|
634
|
+
required: yes
|
635
|
+
"email":
|
636
|
+
pattern: /@/
|
637
|
+
"age":
|
638
|
+
type: integer
|
639
|
+
"birth":
|
640
|
+
type: date
|
641
|
+
</pre>
|
642
|
+
<br>
|
643
|
+
|
644
|
+
|
645
|
+
<a name="tips-anchor"></a>
|
646
|
+
<h3 class="section2">Anchor</h3>
|
647
|
+
<p>You can share schemas with YAML anchor.
|
648
|
+
</p>
|
649
|
+
<a name="schema12.yaml"></a>
|
650
|
+
<div class="program_caption">
|
651
|
+
<code>schema12.yaml</code> : anchor example</div>
|
652
|
+
<pre class="program">type: seq
|
653
|
+
sequence:
|
654
|
+
- <strong>&employee</strong>
|
655
|
+
type: map
|
656
|
+
mapping:
|
657
|
+
"given-name": <strong>&name</strong>
|
658
|
+
type: string
|
659
|
+
required: yes
|
660
|
+
"family-name": <strong>*name</strong>
|
661
|
+
"post":
|
662
|
+
enum:
|
663
|
+
- exective
|
664
|
+
- manager
|
665
|
+
- clerk
|
666
|
+
"supervisor": <strong>*employee</strong>
|
667
|
+
</pre>
|
668
|
+
<p>Anchor is also available in YAML document.
|
669
|
+
</p>
|
670
|
+
<a name="document12a.yaml"></a>
|
671
|
+
<div class="program_caption">
|
672
|
+
<code>document12a.yaml</code> : valid document example</div>
|
673
|
+
<pre class="program">- <strong>&foo</strong>
|
674
|
+
given-name: foo
|
675
|
+
family-name: Foo
|
676
|
+
post: exective
|
677
|
+
- <strong>&bar</strong>
|
678
|
+
given-name: bar
|
679
|
+
family-name: Bar
|
680
|
+
post: manager
|
681
|
+
supervisor: <strong>*foo</strong>
|
682
|
+
- given-name: baz
|
683
|
+
family-name: Baz
|
684
|
+
post: clerk
|
685
|
+
supervisor: <strong>*bar</strong>
|
686
|
+
- given-name: zak
|
687
|
+
family-name: Zak
|
688
|
+
post: clerk
|
689
|
+
supervisor: <strong>*bar</strong>
|
690
|
+
</pre>
|
691
|
+
<div class="terminal_caption">
|
692
|
+
validate</div>
|
693
|
+
<pre class="terminal">$ kwalify -f schema12.yaml document12a.yaml
|
694
|
+
document12a.yaml#1: valid.
|
695
|
+
</pre>
|
696
|
+
<br>
|
697
|
+
|
698
|
+
|
699
|
+
<br>
|
700
|
+
|
701
|
+
|
702
|
+
|
703
|
+
</div>
|
704
|
+
|
705
|
+
</body>
|
706
|
+
</html>
|