forked from MichaelClerx/cellml-validation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcellml_1_0.rnc
508 lines (444 loc) · 17.4 KB
/
cellml_1_0.rnc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
# RELAX NG schema for CellML 1.0
# Author: Jonathan Cooper
# Initial version created using Trang, and then modified
# for correctness and legibility.
# TODO:
# - Tidy metadata checking
# Core CellML namespaces
namespace cellml = "http://www.cellml.org/cellml/1.0#"
namespace mathml = "http://www.w3.org/1998/Math/MathML"
# Metadata-related namespaces
namespace cmeta = "http://www.cellml.org/metadata/1.0#"
namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
namespace dc = "http://purl.org/dc/elements/1.1/"
namespace dcterms = "http://purl.org/dc/terms/"
namespace bqs = "http://www.cellml.org/bqs/1.0#"
namespace vCard = "http://www.w3.org/2001/vcard-rdf/3.0#"
# Our extension namespaces (URIs will change)
namespace pe = "https://chaste.ediamond.ox.ac.uk/cellml/ns/partial-evaluation"
namespace lut = "https://chaste.ediamond.ox.ac.uk/cellml/ns/lookup-tables"
# The 'no namespace' namespace, which is what will get used for
# most CellML attributes. Note the spec is broken in rule 2.5.2.
namespace local = ""
# Some general notes:
# - rule 2.5.2 conflicts with the standard interpretation of XML namespaces. Oops
# - No CellML elements contain text content
# Valid CellML identifiers (rule 2.4.1)
# This is quite complex to get right. The natural choice might
# be xsd:ID, but the lexical space isn't that of NCName: identifiers
# may start with a digit (yuck) and may not contain '.'. Also
# identifiers are not always unique across a document (use the
# cmeta:id attribute for unique IDs).
ident = xsd:token { pattern = "_*[0-9a-zA-Z][_0-9a-zA-Z]*" }
oxygen-fix = [] empty # Work around oXygen's parser getting confused by the regexp above
# Extension namespaces are allowed (rule 2.4.3)
# Foreign elements should not contain CellML elements or attributes. We disallow this entirely,
# for technical reasons (id attribute conflicts).
foreign-nodes = ( foreign-attributes-non-local | foreign-elements)*
foreign-elements =
element * - (cellml:* | rdf:* | mathml:*) {
(foreign-elements* | foreign-attributes* | text) *
}*
foreign-attributes-non-local =
attribute * - (cellml:* | local:* | cmeta:id) { text }*
foreign-attributes =
attribute * - (cellml:* | cmeta:id) { text }*
# All CellML elements may take this attribute, so that they can be
# referred to by metadata.
cmeta.id = attribute cmeta:id { xsd:ID }?
# Nodes that are common to every CellML element.
# Wrap these in parens so they're easier to add in.
common-nodes =
(
foreign-nodes
& cmeta.id
& rdf.RDF*
)
start = cellml.model
cellml.model =
element cellml:model {
# Every model needs a name
attribute name { ident }
# Elements may appear in any order, although that given here
# is recommended for CellML elements (rule 3.4.1).
& cellml.units*
& cellml.component*
& cellml.group*
& cellml.connection*
& common-nodes
}
# CellML components (rule 3.4.2)
cellml.component =
element cellml:component {
# Every component needs a (unique) name
attribute name { ident }
# Again, order is not required, but is recommended.
& cellml.units*
& cellml.variable*
# The use of multiple reaction elements is allowed but
# discoraged (7.4.1.1).
& cellml.reaction*
& mathml.math*
& common-nodes
}
# CellML variables (rule 3.4.3)
cellml.variable =
element cellml:variable {
# Each variable needs a name, which is unique within
# the owning component (but not necessarily across a
# whole model). 3.4.3.2
attribute name { ident },
# Every variable must declare its units.
# This must be an identifier (5.4.2) corresponding to one
# of the standard units or a user-defined unit within the
# current model or component (3.4.3.3).
attribute units { ident },
# Interface values are optional, and can be one of
# "in", "out" or "none" (default) (3.4.3.4 & 3.4.3.5).
# They cannot both be "in" (4.3.4.6).
((
attribute private_interface { "in" },
attribute public_interface { "out" | "none" }?
) | (
attribute public_interface { "in" },
attribute private_interface { "out" | "none" }?
) | (
attribute private_interface { "out" | "none" }?,
attribute public_interface { "out" | "none" }?,
# An initial value must be a real number (3.4.3.7) and
# may not be defined on a variable which has either
# interface set to "in" (3.4.3.8)
attribute initial_value { xsd:double }?
)),
common-nodes
}
# The CellML connection element specifies maps between variables
# in different components.
# See rules 3.4.4, 3.4.5
cellml.connection =
element cellml:connection {
# Again order of elements is non-essential but recommended (3.4.4.1)
# There must be exactly one map_components element (3.4.4.1)
element cellml:map_components {
# Components to map between must be specified (3.4.5.1).
# They must refer to distinct (3.4.5.4) components within
# the current model (3.4.5.2 & 3.4.5.3).
# There must also be at most one connection between any 2 given
# components.
attribute component_1 { ident },
attribute component_2 { ident },
common-nodes
} &
# There must be at least one map_variables element (3.4.4.1)
element cellml:map_variables {
# Variables to map must be specified (3.4.6.1).
# The variable_1 attribute must equal the name of a variable
# defined within component_1 (3.4.6.2); similarly for
# variable_2 (3.4.6.3).
# Allowed mappings are determined by the encapsulation
# hierarchy (3.4.6.4), which is beyond the scope of RELAX NG.
attribute variable_1 { ident },
attribute variable_2 { ident },
common-nodes
}+ &
common-nodes
}
# User-defined units (see section 5 of the specification).
cellml.units =
element cellml:units {
# All units must be named (5.4.1.1).
# The name must not be equal one of the names defined in the
# standard dictionary of units. It must also be unique across
# all units within its parent element. (5.4.1.2)
attribute name { ident }
& common-nodes
& (
(
# If the base_units attribute has the value "yes" then only
# foreign or metadata content is allowed (5.4.1.1).
attribute base_units { "yes" }
) | (
# If base_units is defined as "no" or is unspecified (5.4.1.3)
# then the unit element must contain at least one units element
# (5.4.1.1).
attribute base_units { "no" }?
&
( # Complex units definition, or simple units without offset
element cellml:unit {
# All unit elements must define a units attribute (5.4.2.1),
# which must reference a valid units name (5.4.2.2).
# Circular definitions are not allowed.
attribute units { ident },
# The prefix, if present, must be an integer or a standard
# prefix name (e.g. centi, which is equivalent to -2). The
# default is 0. (5.4.2.3)
attribute prefix { xsd:integer | prefix-name }?,
# The exponent, if present, must be a real number, and
# defaults to 1.0. (5.4.2.4)
attribute exponent { xsd:double }?,
# The multiplier, if present, must be a real number, and
# defaults to 1.0. (5.4.2.5)
attribute multiplier { xsd:double }?,
# The offset, if present, must be a real number, and
# defaults to 0.0. (5.4.2.6)
# It must be omitted or zero except in a simple units
# definition (5.4.2.7).
attribute offset { xsd:decimal "0.0" }?,
common-nodes
}+
|
# Simple units definition with offset (5.4.2.7)
# These have a non-zero value for the offset attribute, and
# only a single unit element.
element cellml:unit {
# All unit elements must define a units attribute (5.4.2.1),
# which must reference a valid units name (5.4.2.2).
# Circular definitions are not allowed.
attribute units { ident },
# The prefix, if present, must be an integer or a standard
# prefix name (e.g. centi, which is equivalent to -2). The
# default is 0. (5.4.2.3)
attribute prefix { xsd:integer | prefix-name }?,
# The exponent, if present, must be a real number, and
# defaults to 1.0. (5.4.2.4)
# It must be 1.0 if offset is non-zero (5.4.2.7).
attribute exponent { xsd:double "1.0" }?,
# The multiplier, if present, must be a real number, and
# defaults to 1.0. (5.4.2.5)
attribute multiplier { xsd:double }?,
# The offset, if present, must be a real number, and
# defaults to 0.0. (5.4.2.6)
# It must be omitted or zero except in a simple units
# definition (5.4.2.7).
attribute offset { xsd:decimal - xsd:decimal "0.0" }?,
common-nodes
}
)
)
)
}
# The set of names that may be used in the prefix attribute on a
# unit element.
prefix-name =
"yotta" | "zetta" | "exa" | "peta" | "tera" |
"giga" | "mega" | "kilo" | "hecto" | "deka" |
"deci" | "centi" | "milli" | "micro" | "nano" |
"pico" | "femto" | "atto" | "zepto" | "yocto"
# Groups (see section 6 of the specification)
cellml.group =
element cellml:group {
# See 6.4.1.1
cellml.relationship_ref+ &
cellml.component_ref+ &
common-nodes
}
# 6.4.2: the relationship_ref element
cellml.relationship_ref =
element cellml:relationship_ref {
# There must be a relationship attribute, either in the 'CellML
# namespace' (meaning no NS) or a user namespace (6.4.2.1)
# I haven't figured out how to describe user-defined relationships
# yet. The best way may be to make the relationship attr optional,
# but this would then allow invalid models. TODO
# For the CellML namespace case, the value must be "containment" or
# "encapsulation" (6.4.2.2)
(
attribute relationship { "encapsulation" }
|
( # For a non-encapsulation relationship, a name attribute is also
# permitted (6.4.2.3) to name a hierarchy.
attribute relationship { "containment" },
attribute name { ident }?
)
) &
common-nodes
}
# 6.4.3: the component_ref element
cellml.component_ref =
element cellml:component_ref {
# The component attribute is mandatory; child elements are optional
# (6.4.3.1).
# The value of the component attribute should be the name of a
# component defined in the current model (6.4.3.3)
# The restrictions of 6.4.3.2 cannot be adequately expressed in
# RELAX NG.
attribute component { ident } &
cellml.component_ref* &
common-nodes
}
# Reactions (see section 7 of the specification)
cellml.reaction =
element cellml:reaction {
# There may be a reversible attribute, which can take the values
# "yes" or "no", and defaults to "yes" (7.4.1.2). It is recommended
# to always specify a value.
attribute reversible { "yes" | "no" }? &
# The recommended best practice is to define one variable_ref
# element for each variable representing a chemical species that
# participates in the reaction, and one variable_ref element for
# the variable representing the rate of the reaction (7.4.1.1)
cellml.variable_ref+ &
common-nodes
}
# 7.4.2: the variable_ref element
cellml.variable_ref =
element cellml:variable_ref {
# The variable attribute must have a value equal to the name of
# a variable defined in the current component (7.4.2.2). A
# variable must only be referenced once in a given reaction.
attribute variable { ident } &
# There must be at least one role element (7.4.2.1). The
# recommended best practice is to define one role element for
# each role assumed by the chemical species represented by the
# referenced variable.
(
element cellml:role {
(
# The role attribute must take one of 7 values (7.4.3.2)
attribute role {
"catalyst" | "activator" | "inhibitor" |
"modifier" # Some unspecified effect
},
# The direction attribute defaults to "forward" (7.4.3.4),
# indicating the role of this variable when the reaction
# is running in the favoured direction.
attribute direction { "forward" | "reverse" | "both" }?,
# Usually this will be an integer, but fractional values
# are allowed (7.4.3.6).
attribute stoichiometry { xsd:decimal }?,
(
mathml.math*
& common-nodes
)
) | (
# The role attribute must take one of 7 values (7.4.3.2)
attribute role { "reactant" | "product" } &
# Reactants and products must be described in the forward
# direction (7.4.3.5).
attribute direction { "forward" }? &
((
# This must refer to the name of a variable in the current
# component (7.4.3.7). It must be unique across all role
# elements within the current component.
# It can only occur if the role is "reactant" or "product"
# (7.4.3.8).
attribute delta_variable { ident } &
# When a delta_variable attribute is present, there must
# be either a stoichiometry attribute or at least one math
# element (7.4.3.8).
(
# Usually this will be an integer, but fractional values
# are allowed (7.4.3.6).
attribute stoichiometry { xsd:decimal }
| mathml.math+
)
) | (
attribute stoichiometry { xsd:decimal }?,
mathml.math*
)) &
common-nodes
)
}+
|
element cellml:role {
# The role attribute must take one of 7 values (7.4.3.2).
# If the value is "rate" then the reference variable
# represents the reaction rate, and no other roles can be
# assigned to it. Further, the delta_variable and
# stoichiometry attributes are disallowed (7.4.3.3).
attribute role { "rate" },
# Rates must be specified in the forward direction (7.4.3.5)
attribute direction { "forward" }?,
(
mathml.math*
& common-nodes
)
}
) &
common-nodes
}
######################################################################
# Mathematics (section 4 of the specification) #
######################################################################
# Almost any of MathML 2.0 is permitted.
# There is however a CellML subset,
# which is all that is required of conformant processing software.
# This part uses a schema generated from the MathML 2.0 DTD to
# define the contents of math elements.
include "mathml2.rnc" {
# Restrict the attribute list for math elements, since in a CellML
# document they're not top-level.
attlist-mathml.math = MATHML.Common.attrib
# Presentation markup is NOT allowed except within annotation-xml.
# However, that element may contain any XML, so we can just define
# the presentation elements to not exist :)
PresInCont = empty
# We don't want to allow empty expressions
ContentExpression = Content+
# Restrict what is allowable "any XML" so ID attrs don't conflict
any =
(element mathml:* {
attribute mathml:* { text }*,
any
}
| text)*
# We could restrict the content of ci to be a CellML identifier:
# mathml.ci = element mathml:ci {
# attlist-mathml.ci, ident
# }
# However, since later it will be checked that each ci element contains
# the name of an existing variable, there isn't much point.
# Check numbers of operands using co-occurrence constraints
mathml.apply =
element mathml:apply { attlist-mathml.apply, ApplyContentExpression }
# I think some operators are wrongly classified in the MathML schema
# Lets be more specific about the 'misc' operators
copmisc = empty
}
# Extra unary operators that were misc.
cop1ary |= mathml.root
| mathml.log
| mathml.minus
| cseqop
| cstatopmoment
| clogicopquant
# Be more specific for calculus operators
ccalcop1ary |= mathml.int
| mathml.diff
| mathml.partialdiff
| mathml.divergence
| mathml.grad
| mathml.curl
| mathml.laplacian
ccalcop2ary = mathml.partialdiff
# Extra binary operators that were misc.
cop2ary |= ccalcop2ary | mathml.minus
# Restrict number of operands depending on the operator
c_operand = ctoken | c0ary | cconstructor | cspecial | cother
c_not_oper = cquantifier | csemantics
ApplyContentExpression = (
(cop1ary, c_operand) & c_not_oper*
) | (
((crel2ary | cop2ary), c_operand, c_operand) & c_not_oper*
) | (
((crelnary | copnary), c_operand+) & c_not_oper*
)
# All cn elements must contain a cellml:units attribute
attlist-mathml.cn &= attribute cellml:units { ident }
# Allow binding time & lookup table annotations
MATHML.Common.attrib &=
attribute (pe:* | lut:*) {text}*
######################################################################
# Metadata #
######################################################################
# This Schema doesn't say anything about allowable metadata.
rdf-any = (
element * - (mathml:* | cellml:*) {
attribute * {text}*,
rdf-any*
} | text )
rdf.RDF =
element rdf:RDF {
attribute * { text }*,
rdf-any*
}