Package xmlschema_acue ::
Package validators ::
Module facets
1
2
3
4
5
6
7
8
9
10
11 """
12 This module contains declarations and classes for XML Schema constraint facets.
13 """
14 from __future__ import unicode_literals
15 import re
16 from elementpath import XPath2Parser, ElementPathSyntaxError, ElementPathTypeError, datatypes
17
18 from xmlschema_acue.compat import unicode_type, MutableSequence
19 from xmlschema_acue.qnames import XSD_LENGTH, XSD_MIN_LENGTH, XSD_MAX_LENGTH, XSD_ENUMERATION, XSD_WHITE_SPACE, \
20 XSD_PATTERN, XSD_MAX_INCLUSIVE, XSD_MAX_EXCLUSIVE, XSD_MIN_INCLUSIVE, XSD_MIN_EXCLUSIVE, \
21 XSD_TOTAL_DIGITS, XSD_FRACTION_DIGITS, XSD_ASSERTION, XSD_EXPLICIT_TIMEZONE, XSD_NOTATION_TYPE, \
22 XSD_BASE64_BINARY, XSD_HEX_BINARY
23 from xmlschema_acue.regex import get_python_regex
24
25 from xmlschema_acue.validators.exceptions import XMLSchemaValidationError, XMLSchemaDecodeError
26 from xmlschema_acue.validators.xsdbase import XsdComponent
30 """
31 XML Schema constraining facets base class.
32 """
33 - def __init__(self, elem, schema, parent, base_type):
36
38 return '%s(value=%r, fixed=%r)' % (self.__class__.__name__, self.value, self.fixed)
39
41 for error in self.validator(value):
42 yield error
43
60
62 self.value = elem.attrib['value']
63
64 @property
67
68 @property
74
75 @property
90
91 @staticmethod
94
97 """
98 XSD whiteSpace facet.
99
100 <whiteSpace
101 fixed = boolean : false
102 id = ID
103 value = (collapse | preserve | replace)
104 {any attributes with non-schema namespace . . .}>
105 Content: (annotation?)
106 </whiteSpace>
107 """
108 _admitted_tags = XSD_WHITE_SPACE,
109
111 self.value = value = elem.attrib['value']
112 if self.base_value == 'collapse' and value in ('preserve', 'replace'):
113 self.parse_error("facet value can be only 'collapse'")
114 elif self.base_value == 'replace' and value == 'preserve':
115 self.parse_error("facet value can be only 'replace' or 'collapse'")
116 elif value == 'replace':
117 self.validator = self.replace_white_space_validator
118 elif value == 'collapse':
119 self.validator = self.collapse_white_space_validator
120 elif value != 'preserve':
121 self.parse_error("attribute 'value' must be one of ('preserve', 'replace', 'collapse').")
122
126
130
133 """
134 XSD length facet.
135
136 <length
137 fixed = boolean : false
138 id = ID
139 value = nonNegativeInteger
140 {any attributes with non-schema namespace . . .}>
141 Content: (annotation?)
142 </length>
143 """
144 _admitted_tags = XSD_LENGTH,
145
160
164
166 if len(x) != self.value * 2:
167 yield XMLSchemaValidationError(self, x, "binary length has to be %r." % self.value)
168
170 x = x.replace(' ', '')
171 if (len(x) // 4 * 3 - (x[-1] == '=') - (x[-2] == '=')) != self.value:
172 yield XMLSchemaValidationError(self, x, "binary length has to be %r." % self.value)
173
176 """
177 XSD minLength facet.
178
179 <minLength
180 fixed = boolean : false
181 id = ID
182 value = nonNegativeInteger
183 {any attributes with non-schema namespace . . .}>
184 Content: (annotation?)
185 </minLength>
186 """
187 _admitted_tags = XSD_MIN_LENGTH,
188
203
205 if len(x) < self.value:
206 yield XMLSchemaValidationError(self, x, "length cannot be lesser than %r." % self.value)
207
209 if len(x) < self.value * 2:
210 yield XMLSchemaValidationError(self, x, "binary length cannot be lesser than %r." % self.value)
211
213 x = x.replace(' ', '')
214 if (len(x) // 4 * 3 - (x[-1] in ('=', 61)) - (x[-2] in ('=', 61))) < self.value:
215 yield XMLSchemaValidationError(self, x, "binary length cannot be lesser than %r." % self.value)
216
219 """
220 XSD maxLength facet.
221
222 <maxLength
223 fixed = boolean : false
224 id = ID
225 value = nonNegativeInteger
226 {any attributes with non-schema namespace . . .}>
227 Content: (annotation?)
228 </maxLength>
229 """
230 _admitted_tags = XSD_MAX_LENGTH,
231
246
248 if len(x) > self.value:
249 yield XMLSchemaValidationError(self, x, "length cannot be greater than %r." % self.value)
250
252 if len(x) > self.value * 2:
253 yield XMLSchemaValidationError(self, x, "binary length cannot be greater than %r." % self.value)
254
256 x = x.replace(' ', '')
257 if (len(x) // 4 * 3 - (x[-1] == '=') - (x[-2] == '=')) > self.value:
258 yield XMLSchemaValidationError(self, x, "binary length cannot be greater than %r." % self.value)
259
262 """
263 XSD minInclusive facet.
264
265 <minInclusive
266 fixed = boolean : false
267 id = ID
268 value = anySimpleType
269 {any attributes with non-schema namespace . . .}>
270 Content: (annotation?)
271 </minInclusive>
272 """
273 _admitted_tags = XSD_MIN_INCLUSIVE,
274
290
292 if x < self.value:
293 yield XMLSchemaValidationError(self, x, "value has to be greater or equal than %r." % self.value)
294
297 """
298 XSD minExclusive facet.
299
300 <minExclusive
301 fixed = boolean : false
302 id = ID
303 value = anySimpleType
304 {any attributes with non-schema namespace . . .}>
305 Content: (annotation?)
306 </minExclusive>
307 """
308 _admitted_tags = XSD_MIN_EXCLUSIVE,
309
325
329
332 """
333 XSD maxInclusive facet.
334
335 <maxInclusive
336 fixed = boolean : false
337 id = ID
338 value = anySimpleType
339 {any attributes with non-schema namespace . . .}>
340 Content: (annotation?)
341 </maxInclusive>
342 """
343 _admitted_tags = XSD_MAX_INCLUSIVE,
344
360
362 if x > self.value:
363 yield XMLSchemaValidationError(self, x, "value has to be lesser or equal than %r." % self.value)
364
367 """
368 XSD maxExclusive facet.
369
370 <maxExclusive
371 fixed = boolean : false
372 id = ID
373 value = anySimpleType
374 {any attributes with non-schema namespace . . .}>
375 Content: (annotation?)
376 </maxExclusive>
377 """
378 _admitted_tags = XSD_MAX_EXCLUSIVE,
379
395
399
402 """
403 XSD totalDigits facet.
404
405 <totalDigits
406 fixed = boolean : false
407 id = ID
408 value = positiveInteger
409 {any attributes with non-schema namespace . . .}>
410 Content: (annotation?)
411 </totalDigits>
412 """
413 _admitted_tags = XSD_TOTAL_DIGITS,
414
420
422 if len([d for d in str(x).strip('0') if d.isdigit()]) > self.value:
423 yield XMLSchemaValidationError(self, x, "the number of digits is greater than %r." % self.value)
424
427 """
428 XSD fractionDigits facet.
429
430 <fractionDigits
431 fixed = boolean : false
432 id = ID
433 value = nonNegativeInteger
434 {any attributes with non-schema namespace . . .}>
435 Content: (annotation?)
436 </fractionDigits>
437 """
438 _admitted_tags = XSD_FRACTION_DIGITS,
439
440 - def __init__(self, elem, schema, parent, base_type):
444
452
454 if len(str(x).strip('0').partition('.')[2]) > self.value:
455 yield XMLSchemaValidationError(self, x, "the number of fraction digits is greater than %r." % self.value)
456
459 """
460 XSD 1.1 explicitTimezone facet.
461
462 <explicitTimezone
463 fixed = boolean : false
464 id = ID
465 value = NCName
466 {any attributes with non-schema namespace . . .}>
467 Content: (annotation?)
468 </explicitTimezone>
469 """
470 _admitted_tags = XSD_EXPLICIT_TIMEZONE,
471
480
484
486 if x.tzinfo is not None:
487 yield XMLSchemaValidationError(self, x, "time zone prohibited for value %r." % self.value)
488
491 """
492 Sequence of XSD enumeration facets. Values are validates if match any of enumeration values.
493
494 <enumeration
495 id = ID
496 value = anySimpleType
497 {any attributes with non-schema namespace . . .}>
498 Content: (annotation?)
499 </enumeration>
500 """
501 _admitted_tags = {XSD_ENUMERATION}
502
503 - def __init__(self, elem, schema, parent, base_type):
505
507 super(XsdFacet, self)._parse()
508 self._elements = [self.elem]
509 self.enumeration = [self._parse_value(self.elem)]
510
529
530
532 return self._elements[i]
533
535 self._elements[i] = elem
536 self.enumeration[i] = self._parse_value(elem)
537
539 del self._elements[i]
540 del self.enumeration[i]
541
543 return len(self._elements)
544
546 self._elements.insert(i, elem)
547 self.enumeration.insert(i, self._parse_value(elem))
548
550 if len(self.enumeration) > 5:
551 return '%s(%r)' % (
552 self.__class__.__name__, '[%s, ...]' % ', '.join(map(repr, self.enumeration[:5]))
553 )
554 else:
555 return '%s(%r)' % (self.__class__.__name__, self.enumeration)
556
558 if value not in self.enumeration:
559 yield XMLSchemaValidationError(
560 self, value, reason="invalid value %r, it must be one of %r" % (value, self.enumeration)
561 )
562
565 """
566 Sequence of XSD pattern facets. Values are validates if match any of patterns.
567
568 <pattern
569 id = ID
570 value = string
571 {any attributes with non-schema namespace . . .}>
572 Content: (annotation?)
573 </pattern>
574 """
575 _admitted_tags = {XSD_PATTERN}
576
577 - def __init__(self, elem, schema, parent, base_type):
579
581 super(XsdFacet, self)._parse()
582 self._elements = [self.elem]
583 self.patterns = [self._parse_value(self.elem)]
584
594
595
597 return self._elements[i]
598
600 self._elements[i] = elem
601 self.patterns[i] = self._parse_value(elem)
602
604 del self._elements[i]
605 del self.patterns[i]
606
608 return len(self._elements)
609
613
615 s = repr(self.regexps)
616 if len(s) < 70:
617 return '%s(%s)' % (self.__class__.__name__, s)
618 else:
619 return '%s(%s...\'])' % (self.__class__.__name__, s[:70])
620
625
626 @property
628 return [e.get('value', '') for e in self._elements]
629
632 """
633 XSD 1.1 assertion facet for simpleType definitions.
634
635 <assertion
636 id = ID
637 test = an XPath expression
638 xpathDefaultNamespace = (anyURI | (##defaultNamespace | ##targetNamespace | ##local))
639 {any attributes with non-schema namespace . . .}>
640 Content: (annotation?)
641 </assertion>
642 """
643 _admitted_tags = {XSD_ASSERTION}
644
646 return '%s(test=%r)' % (self.__class__.__name__, self.path)
647
671
673 self.parser.variables['value'] = value
674 if not self.token.evaluate():
675 msg = "value is not true with test path %r."
676 yield XMLSchemaValidationError(self, value, reason=msg % self.path)
677
678
679 XSD_10_FACETS_BUILDERS = {
680 XSD_WHITE_SPACE: XsdWhiteSpaceFacet,
681 XSD_LENGTH: XsdLengthFacet,
682 XSD_MIN_LENGTH: XsdMinLengthFacet,
683 XSD_MAX_LENGTH: XsdMaxLengthFacet,
684 XSD_MIN_INCLUSIVE: XsdMinInclusiveFacet,
685 XSD_MIN_EXCLUSIVE: XsdMinExclusiveFacet,
686 XSD_MAX_INCLUSIVE: XsdMaxInclusiveFacet,
687 XSD_MAX_EXCLUSIVE: XsdMaxExclusiveFacet,
688 XSD_TOTAL_DIGITS: XsdTotalDigitsFacet,
689 XSD_FRACTION_DIGITS: XsdFractionDigitsFacet,
690 XSD_ENUMERATION: XsdEnumerationFacets,
691 XSD_PATTERN: XsdPatternFacets
692 }
693
694 XSD_11_FACETS_BUILDERS = XSD_10_FACETS_BUILDERS.copy()
695 XSD_11_FACETS_BUILDERS.update({
696 XSD_ASSERTION: XsdAssertionFacet,
697 XSD_EXPLICIT_TIMEZONE: XsdExplicitTimezoneFacet
698 })
699
700 XSD_10_FACETS = set(XSD_10_FACETS_BUILDERS)
701 XSD_11_FACETS = set(XSD_11_FACETS_BUILDERS)
702
703 XSD_10_LIST_FACETS = {XSD_LENGTH, XSD_MIN_LENGTH, XSD_MAX_LENGTH, XSD_PATTERN, XSD_ENUMERATION, XSD_WHITE_SPACE}
704 XSD_11_LIST_FACETS = XSD_10_LIST_FACETS | {XSD_ASSERTION}
705
706 XSD_10_UNION_FACETS = {XSD_PATTERN, XSD_ENUMERATION}
707 XSD_11_UNION_FACETS = MULTIPLE_FACETS = {XSD_PATTERN, XSD_ENUMERATION, XSD_ASSERTION}
708