You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

3291 lines
110 KiB

  1. #!/usr/bin/env python
  2. # Copyright (c) 2003, The Regents of the University of California,
  3. # through Lawrence Berkeley National Laboratory (subject to receipt of
  4. # any required approvals from the U.S. Dept. of Energy). All rights
  5. # reserved.
  6. #
  7. # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
  8. #
  9. # This software is subject to the provisions of the Zope Public License,
  10. # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
  11. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  12. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  13. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  14. # FOR A PARTICULAR PURPOSE.
  15. ident = "$Id$"
  16. import logging
  17. import sys
  18. import types
  19. import warnings
  20. import weakref
  21. from six import string_types
  22. from .Namespaces import APACHE
  23. from .Namespaces import SCHEMA
  24. from .Namespaces import SOAP
  25. from .Namespaces import XMLNS
  26. from .Utility import DOM
  27. from .Utility import Collection
  28. from .Utility import DOMException
  29. from .Utility import SplitQName
  30. from .Utility import basejoin
  31. try:
  32. from io import StringIO
  33. except ImportError:
  34. # from io import StringIO
  35. from io import BytesIO as StringIO
  36. # If we have no threading, this should be a no-op
  37. try:
  38. from threading import RLock
  39. except ImportError:
  40. class RLock(object):
  41. def acquire():
  42. pass
  43. def release():
  44. pass
  45. #
  46. # Collections in XMLSchema class
  47. #
  48. TYPES = 'types'
  49. ATTRIBUTE_GROUPS = 'attr_groups'
  50. ATTRIBUTES = 'attr_decl'
  51. ELEMENTS = 'elements'
  52. MODEL_GROUPS = 'model_groups'
  53. BUILT_IN_NAMESPACES = [SOAP.ENC, ] + SCHEMA.XSD_LIST + [APACHE.AXIS_NS]
  54. def GetSchema(component):
  55. """convience function for finding the parent XMLSchema instance.
  56. """
  57. parent = component
  58. while not isinstance(parent, XMLSchema):
  59. parent = parent._parent()
  60. return parent
  61. class SchemaReader(object):
  62. """A SchemaReader creates XMLSchema objects from urls and xml data.
  63. """
  64. namespaceToSchema = {}
  65. def __init__(self, domReader=None, base_url=None):
  66. """domReader -- class must implement DOMAdapterInterface
  67. base_url -- base url string
  68. """
  69. self.__base_url = base_url
  70. self.__readerClass = domReader
  71. if not self.__readerClass:
  72. self.__readerClass = DOMAdapter
  73. self._includes = {}
  74. self._imports = {}
  75. def __setImports(self, schema):
  76. """Add dictionary of imports to schema instance.
  77. schema -- XMLSchema instance
  78. """
  79. for ns, val in list(schema.imports.items()):
  80. if ns in self._imports:
  81. schema.addImportSchema(self._imports[ns])
  82. def __setIncludes(self, schema):
  83. """Add dictionary of includes to schema instance.
  84. schema -- XMLSchema instance
  85. """
  86. for schemaLocation, val in list(schema.includes.items()):
  87. if schemaLocation in self._includes:
  88. schema.addIncludeSchema(
  89. schemaLocation, self._imports[schemaLocation])
  90. def addSchemaByLocation(self, location, schema):
  91. """provide reader with schema document for a location.
  92. """
  93. self._includes[location] = schema
  94. def addSchemaByNamespace(self, schema):
  95. """provide reader with schema document for a targetNamespace.
  96. """
  97. self._imports[schema.targetNamespace] = schema
  98. def loadFromNode(self, parent, element):
  99. """element -- DOM node or document
  100. parent -- WSDLAdapter instance
  101. """
  102. reader = self.__readerClass(element)
  103. schema = XMLSchema(parent)
  104. # HACK to keep a reference
  105. schema.wsdl = parent
  106. schema.setBaseUrl(self.__base_url)
  107. schema.load(reader)
  108. return schema
  109. def loadFromStream(self, file, url=None):
  110. """Return an XMLSchema instance loaded from a file object.
  111. file -- file object
  112. url -- base location for resolving imports/includes.
  113. """
  114. reader = self.__readerClass()
  115. reader.loadDocument(file)
  116. schema = XMLSchema()
  117. if url is not None:
  118. schema.setBaseUrl(url)
  119. schema.load(reader)
  120. self.__setIncludes(schema)
  121. self.__setImports(schema)
  122. return schema
  123. def loadFromString(self, data):
  124. """Return an XMLSchema instance loaded from an XML string.
  125. data -- XML string
  126. """
  127. return self.loadFromStream(StringIO(data))
  128. def loadFromURL(self, url, schema=None):
  129. """Return an XMLSchema instance loaded from the given url.
  130. url -- URL to dereference
  131. schema -- Optional XMLSchema instance.
  132. """
  133. reader = self.__readerClass()
  134. if self.__base_url:
  135. url = basejoin(self.__base_url, url)
  136. reader.loadFromURL(url)
  137. schema = schema or XMLSchema()
  138. schema.setBaseUrl(url)
  139. schema.load(reader)
  140. self.__setIncludes(schema)
  141. self.__setImports(schema)
  142. return schema
  143. def loadFromFile(self, filename):
  144. """Return an XMLSchema instance loaded from the given file.
  145. filename -- name of file to open
  146. """
  147. if self.__base_url:
  148. filename = basejoin(self.__base_url, filename)
  149. file = open(filename, 'rb')
  150. try:
  151. schema = self.loadFromStream(file, filename)
  152. finally:
  153. file.close()
  154. return schema
  155. class SchemaError(Exception):
  156. pass
  157. class NoSchemaLocationWarning(Exception):
  158. pass
  159. ###########################
  160. # DOM Utility Adapters
  161. ##########################
  162. class DOMAdapterInterface(object):
  163. def hasattr(self, attr, ns=None):
  164. """return true if node has attribute
  165. attr -- attribute to check for
  166. ns -- namespace of attribute, by default None
  167. """
  168. raise NotImplementedError('adapter method not implemented')
  169. def getContentList(self, *contents):
  170. """returns an ordered list of child nodes
  171. *contents -- list of node names to return
  172. """
  173. raise NotImplementedError('adapter method not implemented')
  174. def setAttributeDictionary(self, attributes):
  175. """set attribute dictionary
  176. """
  177. raise NotImplementedError('adapter method not implemented')
  178. def getAttributeDictionary(self):
  179. """returns a dict of node's attributes
  180. """
  181. raise NotImplementedError('adapter method not implemented')
  182. def getNamespace(self, prefix):
  183. """returns namespace referenced by prefix.
  184. """
  185. raise NotImplementedError('adapter method not implemented')
  186. def getTagName(self):
  187. """returns tagName of node
  188. """
  189. raise NotImplementedError('adapter method not implemented')
  190. def getParentNode(self):
  191. """returns parent element in DOMAdapter or None
  192. """
  193. raise NotImplementedError('adapter method not implemented')
  194. def loadDocument(self, file):
  195. """load a Document from a file object
  196. file --
  197. """
  198. raise NotImplementedError('adapter method not implemented')
  199. def loadFromURL(self, url):
  200. """load a Document from an url
  201. url -- URL to dereference
  202. """
  203. raise NotImplementedError('adapter method not implemented')
  204. class DOMAdapter(DOMAdapterInterface):
  205. """Adapter for ZSI.Utility.DOM
  206. """
  207. def __init__(self, node=None):
  208. """Reset all instance variables.
  209. element -- DOM document, node, or None
  210. """
  211. if hasattr(node, 'documentElement'):
  212. self.__node = node.documentElement
  213. else:
  214. self.__node = node
  215. self.__attributes = None
  216. def getNode(self):
  217. return self.__node
  218. def hasattr(self, attr, ns=None):
  219. """attr -- attribute
  220. ns -- optional namespace, None means unprefixed attribute.
  221. """
  222. if not self.__attributes:
  223. self.setAttributeDictionary()
  224. if ns:
  225. return attr in self.__attributes.get(ns, {})
  226. return attr in self.__attributes
  227. def getContentList(self, *contents):
  228. nodes = []
  229. ELEMENT_NODE = self.__node.ELEMENT_NODE
  230. for child in DOM.getElements(self.__node, None):
  231. if child.nodeType == ELEMENT_NODE and\
  232. SplitQName(child.tagName)[1] in contents:
  233. nodes.append(child)
  234. return list(map(self.__class__, nodes))
  235. def setAttributeDictionary(self):
  236. self.__attributes = {}
  237. if self.__node._attrs:
  238. for v in list(self.__node._attrs.values()):
  239. self.__attributes[v.nodeName] = v.nodeValue
  240. def getAttributeDictionary(self):
  241. if not self.__attributes:
  242. self.setAttributeDictionary()
  243. return self.__attributes
  244. def getTagName(self):
  245. return self.__node.tagName
  246. def getParentNode(self):
  247. if self.__node.parentNode.nodeType == self.__node.ELEMENT_NODE:
  248. return DOMAdapter(self.__node.parentNode)
  249. return None
  250. def getNamespace(self, prefix):
  251. """prefix -- deference namespace prefix in node's context.
  252. Ascends parent nodes until found.
  253. """
  254. namespace = None
  255. if prefix == 'xmlns':
  256. namespace = DOM.findDefaultNS(prefix, self.__node)
  257. else:
  258. try:
  259. namespace = DOM.findNamespaceURI(prefix, self.__node)
  260. except DOMException:
  261. if prefix != 'xml':
  262. raise SchemaError('%s namespace not declared for %s' % (
  263. prefix, self.__node._get_tagName()))
  264. namespace = XMLNS.XML
  265. return namespace
  266. def loadDocument(self, file):
  267. self.__node = DOM.loadDocument(file)
  268. if hasattr(self.__node, 'documentElement'):
  269. self.__node = self.__node.documentElement
  270. def loadFromURL(self, url):
  271. self.__node = DOM.loadFromURL(url)
  272. if hasattr(self.__node, 'documentElement'):
  273. self.__node = self.__node.documentElement
  274. class XMLBase:
  275. """ These class variables are for string indentation.
  276. """
  277. tag = None
  278. __indent = 0
  279. __rlock = RLock()
  280. def __str__(self):
  281. XMLBase.__rlock.acquire()
  282. XMLBase.__indent += 1
  283. tmp = "<" + str(self.__class__) + '>\n'
  284. for k, v in list(self.__dict__.items()):
  285. tmp += "%s* %s = %s\n" % (XMLBase.__indent * ' ', k, v)
  286. XMLBase.__indent -= 1
  287. XMLBase.__rlock.release()
  288. return tmp
  289. """Marker Interface: can determine something about an instances properties by using
  290. the provided convenience functions.
  291. """
  292. class DefinitionMarker:
  293. """marker for definitions
  294. """
  295. pass
  296. class DeclarationMarker:
  297. """marker for declarations
  298. """
  299. pass
  300. class AttributeMarker:
  301. """marker for attributes
  302. """
  303. pass
  304. class AttributeGroupMarker:
  305. """marker for attribute groups
  306. """
  307. pass
  308. class WildCardMarker:
  309. """marker for wildcards
  310. """
  311. pass
  312. class ElementMarker:
  313. """marker for wildcards
  314. """
  315. pass
  316. class ReferenceMarker:
  317. """marker for references
  318. """
  319. pass
  320. class ModelGroupMarker:
  321. """marker for model groups
  322. """
  323. pass
  324. class AllMarker(ModelGroupMarker):
  325. """marker for all model group
  326. """
  327. pass
  328. class ChoiceMarker(ModelGroupMarker):
  329. """marker for choice model group
  330. """
  331. pass
  332. class SequenceMarker(ModelGroupMarker):
  333. """marker for sequence model group
  334. """
  335. pass
  336. class ExtensionMarker:
  337. """marker for extensions
  338. """
  339. pass
  340. class RestrictionMarker:
  341. """marker for restrictions
  342. """
  343. facets = ['enumeration', 'length', 'maxExclusive', 'maxInclusive',
  344. 'maxLength', 'minExclusive', 'minInclusive', 'minLength',
  345. 'pattern', 'fractionDigits', 'totalDigits', 'whiteSpace']
  346. class SimpleMarker:
  347. """marker for simple type information
  348. """
  349. pass
  350. class ListMarker:
  351. """marker for simple type list
  352. """
  353. pass
  354. class UnionMarker:
  355. """marker for simple type Union
  356. """
  357. pass
  358. class ComplexMarker:
  359. """marker for complex type information
  360. """
  361. pass
  362. class LocalMarker:
  363. """marker for complex type information
  364. """
  365. pass
  366. class MarkerInterface:
  367. def isDefinition(self):
  368. return isinstance(self, DefinitionMarker)
  369. def isDeclaration(self):
  370. return isinstance(self, DeclarationMarker)
  371. def isAttribute(self):
  372. return isinstance(self, AttributeMarker)
  373. def isAttributeGroup(self):
  374. return isinstance(self, AttributeGroupMarker)
  375. def isElement(self):
  376. return isinstance(self, ElementMarker)
  377. def isReference(self):
  378. return isinstance(self, ReferenceMarker)
  379. def isWildCard(self):
  380. return isinstance(self, WildCardMarker)
  381. def isModelGroup(self):
  382. return isinstance(self, ModelGroupMarker)
  383. def isAll(self):
  384. return isinstance(self, AllMarker)
  385. def isChoice(self):
  386. return isinstance(self, ChoiceMarker)
  387. def isSequence(self):
  388. return isinstance(self, SequenceMarker)
  389. def isExtension(self):
  390. return isinstance(self, ExtensionMarker)
  391. def isRestriction(self):
  392. return isinstance(self, RestrictionMarker)
  393. def isSimple(self):
  394. return isinstance(self, SimpleMarker)
  395. def isComplex(self):
  396. return isinstance(self, ComplexMarker)
  397. def isLocal(self):
  398. return isinstance(self, LocalMarker)
  399. def isList(self):
  400. return isinstance(self, ListMarker)
  401. def isUnion(self):
  402. return isinstance(self, UnionMarker)
  403. ##########################################################
  404. # Schema Components
  405. #########################################################
  406. class XMLSchemaComponent(XMLBase, MarkerInterface):
  407. """
  408. class variables:
  409. required -- list of required attributes
  410. attributes -- dict of default attribute values, including None.
  411. Value can be a function for runtime dependencies.
  412. contents -- dict of namespace keyed content lists.
  413. 'xsd' content of xsd namespace.
  414. xmlns_key -- key for declared xmlns namespace.
  415. xmlns -- xmlns is special prefix for namespace dictionary
  416. xml -- special xml prefix for xml namespace.
  417. """
  418. required = []
  419. attributes = {}
  420. contents = {}
  421. xmlns_key = ''
  422. xmlns = 'xmlns'
  423. xml = 'xml'
  424. def __init__(self, parent=None):
  425. """parent -- parent instance
  426. instance variables:
  427. attributes -- dictionary of node's attributes
  428. """
  429. self.attributes = None
  430. self._parent = parent
  431. if self._parent:
  432. self._parent = weakref.ref(parent)
  433. if not self.__class__ == XMLSchemaComponent\
  434. and not (isinstance(self.__class__.required, type(XMLSchemaComponent.required))
  435. and isinstance(self.__class__.attributes, type(XMLSchemaComponent.attributes))
  436. and isinstance(self.__class__.contents, type(XMLSchemaComponent.contents))):
  437. raise RuntimeError(
  438. 'Bad type for a class variable in %s' % self.__class__)
  439. def getItemTrace(self):
  440. """Returns a node trace up to the <schema> item.
  441. """
  442. item, path, name, ref = self, [], 'name', 'ref'
  443. while not isinstance(item, XMLSchema) and not isinstance(item, WSDLToolsAdapter):
  444. attr = item.getAttribute(name)
  445. if not attr:
  446. attr = item.getAttribute(ref)
  447. if not attr:
  448. path.append('<%s>' % (item.tag))
  449. else:
  450. path.append('<%s ref="%s">' % (item.tag, attr))
  451. else:
  452. path.append('<%s name="%s">' % (item.tag, attr))
  453. item = item._parent()
  454. try:
  455. tns = item.getTargetNamespace()
  456. except:
  457. tns = ''
  458. path.append('<%s targetNamespace="%s">' % (item.tag, tns))
  459. path.reverse()
  460. return ''.join(path)
  461. def getTargetNamespace(self):
  462. """return targetNamespace
  463. """
  464. parent = self
  465. targetNamespace = 'targetNamespace'
  466. tns = self.attributes.get(targetNamespace)
  467. while not tns and parent and parent._parent is not None:
  468. parent = parent._parent()
  469. tns = parent.attributes.get(targetNamespace)
  470. return tns or ''
  471. def getAttributeDeclaration(self, attribute):
  472. """attribute -- attribute with a QName value (eg. type).
  473. collection -- check types collection in parent Schema instance
  474. """
  475. return self.getQNameAttribute(ATTRIBUTES, attribute)
  476. def getAttributeGroup(self, attribute):
  477. """attribute -- attribute with a QName value (eg. type).
  478. collection -- check types collection in parent Schema instance
  479. """
  480. return self.getQNameAttribute(ATTRIBUTE_GROUPS, attribute)
  481. def getTypeDefinition(self, attribute):
  482. """attribute -- attribute with a QName value (eg. type).
  483. collection -- check types collection in parent Schema instance
  484. """
  485. return self.getQNameAttribute(TYPES, attribute)
  486. def getElementDeclaration(self, attribute):
  487. """attribute -- attribute with a QName value (eg. element).
  488. collection -- check elements collection in parent Schema instance.
  489. """
  490. return self.getQNameAttribute(ELEMENTS, attribute)
  491. def getModelGroup(self, attribute):
  492. """attribute -- attribute with a QName value (eg. ref).
  493. collection -- check model_group collection in parent Schema instance.
  494. """
  495. return self.getQNameAttribute(MODEL_GROUPS, attribute)
  496. def getQNameAttribute(self, collection, attribute):
  497. """returns object instance representing QName --> (namespace,name),
  498. or if does not exist return None.
  499. attribute -- an information item attribute, with a QName value.
  500. collection -- collection in parent Schema instance to search.
  501. """
  502. tdc = self.getAttributeQName(attribute)
  503. if not tdc:
  504. return
  505. obj = self.getSchemaItem(
  506. collection, tdc.getTargetNamespace(), tdc.getName())
  507. if obj:
  508. return obj
  509. # raise SchemaError, 'No schema item "%s" in collection %s' %(tdc,
  510. # collection)
  511. return
  512. def getSchemaItem(self, collection, namespace, name):
  513. """returns object instance representing namespace, name,
  514. or if does not exist return None if built-in, else
  515. raise SchemaError.
  516. namespace -- namespace item defined in.
  517. name -- name of item.
  518. collection -- collection in parent Schema instance to search.
  519. """
  520. parent = GetSchema(self)
  521. if parent.targetNamespace == namespace:
  522. try:
  523. obj = getattr(parent, collection)[name]
  524. except KeyError:
  525. raise KeyError('targetNamespace(%s) collection(%s) has no item(%s)' % (
  526. namespace, collection, name))
  527. return obj
  528. if namespace not in parent.imports:
  529. if namespace in BUILT_IN_NAMESPACES:
  530. # built-in just return
  531. # WARNING: expecting import if "redefine" or add to built-in
  532. # namespace.
  533. return
  534. raise SchemaError('schema "%s" does not import namespace "%s"' % (
  535. parent.targetNamespace, namespace))
  536. # Lazy Eval
  537. schema = parent.imports[namespace]
  538. if not isinstance(schema, XMLSchema):
  539. schema = schema.getSchema()
  540. if schema is not None:
  541. parent.imports[namespace] = schema
  542. if schema is None:
  543. if namespace in BUILT_IN_NAMESPACES:
  544. # built-in just return
  545. return
  546. raise SchemaError(
  547. 'no schema instance for imported namespace (%s).' % (namespace))
  548. if not isinstance(schema, XMLSchema):
  549. raise TypeError('expecting XMLSchema instance not "%r"' % schema)
  550. try:
  551. obj = getattr(schema, collection)[name]
  552. except KeyError:
  553. raise KeyError('targetNamespace(%s) collection(%s) has no item(%s)' % (
  554. namespace, collection, name))
  555. return obj
  556. def getXMLNS(self, prefix=None):
  557. """deference prefix or by default xmlns, returns namespace.
  558. """
  559. if prefix == XMLSchemaComponent.xml:
  560. return XMLNS.XML
  561. parent = self
  562. ns = self.attributes[XMLSchemaComponent.xmlns].get(prefix or
  563. XMLSchemaComponent.xmlns_key)
  564. while not ns:
  565. parent = parent._parent()
  566. ns = parent.attributes[XMLSchemaComponent.xmlns].get(prefix or
  567. XMLSchemaComponent.xmlns_key)
  568. if not ns and isinstance(parent, WSDLToolsAdapter):
  569. if prefix is None:
  570. return ''
  571. raise SchemaError('unknown prefix %s' % prefix)
  572. return ns
  573. def getAttribute(self, attribute):
  574. """return requested attribute value or None
  575. """
  576. if type(attribute) in (list, tuple):
  577. if len(attribute) != 2:
  578. raise LookupError(
  579. 'To access attributes must use name or (namespace,name)')
  580. ns_dict = self.attributes.get(attribute[0])
  581. if ns_dict is None:
  582. return None
  583. return ns_dict.get(attribute[1])
  584. return self.attributes.get(attribute)
  585. def getAttributeQName(self, attribute):
  586. """return requested attribute value as (namespace,name) or None
  587. """
  588. qname = self.getAttribute(attribute)
  589. if isinstance(qname, TypeDescriptionComponent) is True:
  590. return qname
  591. if qname is None:
  592. return None
  593. prefix, ncname = SplitQName(qname)
  594. namespace = self.getXMLNS(prefix)
  595. return TypeDescriptionComponent((namespace, ncname))
  596. def getAttributeName(self):
  597. """return attribute name or None
  598. """
  599. return self.getAttribute('name')
  600. def setAttributes(self, node):
  601. """Sets up attribute dictionary, checks for required attributes and
  602. sets default attribute values. attr is for default attribute values
  603. determined at runtime.
  604. structure of attributes dictionary
  605. ['xmlns'][xmlns_key] -- xmlns namespace
  606. ['xmlns'][prefix] -- declared namespace prefix
  607. [namespace][prefix] -- attributes declared in a namespace
  608. [attribute] -- attributes w/o prefix, default namespaces do
  609. not directly apply to attributes, ie Name can't collide
  610. with QName.
  611. """
  612. self.attributes = {XMLSchemaComponent.xmlns: {}}
  613. for k, v in list(node.getAttributeDictionary().items()):
  614. prefix, value = SplitQName(k)
  615. if value == XMLSchemaComponent.xmlns:
  616. self.attributes[value][
  617. prefix or XMLSchemaComponent.xmlns_key] = v
  618. elif prefix:
  619. ns = node.getNamespace(prefix)
  620. if not ns:
  621. raise SchemaError(
  622. 'no namespace for attribute prefix %s' % prefix)
  623. if ns not in self.attributes:
  624. self.attributes[ns] = {}
  625. elif value in self.attributes[ns]:
  626. raise SchemaError(
  627. 'attribute %s declared multiple times in %s' % (value, ns))
  628. self.attributes[ns][value] = v
  629. elif value not in self.attributes:
  630. self.attributes[value] = v
  631. else:
  632. raise SchemaError(
  633. 'attribute %s declared multiple times' % value)
  634. if not isinstance(self, WSDLToolsAdapter):
  635. self.__checkAttributes()
  636. self.__setAttributeDefaults()
  637. # set QNames
  638. for k in ['type', 'element', 'base', 'ref', 'substitutionGroup', 'itemType']:
  639. if k in self.attributes:
  640. prefix, value = SplitQName(self.attributes.get(k))
  641. self.attributes[k] = \
  642. TypeDescriptionComponent((self.getXMLNS(prefix), value))
  643. # Union, memberTypes is a whitespace separated list of QNames
  644. for k in ['memberTypes']:
  645. if k in self.attributes:
  646. qnames = self.attributes[k]
  647. self.attributes[k] = []
  648. for qname in qnames.split():
  649. prefix, value = SplitQName(qname)
  650. self.attributes['memberTypes'].append(
  651. TypeDescriptionComponent(
  652. (self.getXMLNS(prefix), value)))
  653. def getContents(self, node):
  654. """retrieve xsd contents
  655. """
  656. return node.getContentList(*self.__class__.contents['xsd'])
  657. def __setAttributeDefaults(self):
  658. """Looks for default values for unset attributes. If
  659. class variable representing attribute is None, then
  660. it must be defined as an instance variable.
  661. """
  662. for k, v in list(self.__class__.attributes.items()):
  663. if v is not None and k in self.attributes is False:
  664. if isinstance(v, types.FunctionType):
  665. self.attributes[k] = v(self)
  666. else:
  667. self.attributes[k] = v
  668. def __checkAttributes(self):
  669. """Checks that required attributes have been defined,
  670. attributes w/default cannot be required. Checks
  671. all defined attributes are legal, attribute
  672. references are not subject to this test.
  673. """
  674. for a in self.__class__.required:
  675. if a not in self.attributes:
  676. raise SchemaError(
  677. 'class instance %s, missing required attribute %s' % (self.__class__, a))
  678. for a, v in list(self.attributes.items()):
  679. # attribute #other, ie. not in empty namespace
  680. if type(v) is dict:
  681. continue
  682. # predefined prefixes xmlns, xml
  683. if a in (XMLSchemaComponent.xmlns, XMLNS.XML):
  684. continue
  685. if (a not in list(self.__class__.attributes.keys())) and not\
  686. (self.isAttribute() and self.isReference()):
  687. raise SchemaError('%s, unknown attribute(%s, %s)' % (
  688. self.getItemTrace(), a, self.attributes[a]))
  689. class WSDLToolsAdapter(XMLSchemaComponent):
  690. """WSDL Adapter to grab the attributes from the wsdl document node.
  691. """
  692. attributes = {'name': None, 'targetNamespace': None}
  693. tag = 'definitions'
  694. def __init__(self, wsdl):
  695. XMLSchemaComponent.__init__(self, parent=wsdl)
  696. self.setAttributes(DOMAdapter(wsdl.document))
  697. def getImportSchemas(self):
  698. """returns WSDLTools.WSDL types Collection
  699. """
  700. return self._parent().types
  701. class Notation(XMLSchemaComponent):
  702. """<notation>
  703. parent:
  704. schema
  705. attributes:
  706. id -- ID
  707. name -- NCName, Required
  708. public -- token, Required
  709. system -- anyURI
  710. contents:
  711. annotation?
  712. """
  713. required = ['name', 'public']
  714. attributes = {'id': None, 'name': None, 'public': None, 'system': None}
  715. contents = {'xsd': ('annotation')}
  716. tag = 'notation'
  717. def __init__(self, parent):
  718. XMLSchemaComponent.__init__(self, parent)
  719. self.annotation = None
  720. def fromDom(self, node):
  721. self.setAttributes(node)
  722. contents = self.getContents(node)
  723. for i in contents:
  724. component = SplitQName(i.getTagName())[1]
  725. if component == 'annotation' and not self.annotation:
  726. self.annotation = Annotation(self)
  727. self.annotation.fromDom(i)
  728. else:
  729. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  730. class Annotation(XMLSchemaComponent):
  731. """<annotation>
  732. parent:
  733. all,any,anyAttribute,attribute,attributeGroup,choice,complexContent,
  734. complexType,element,extension,field,group,import,include,key,keyref,
  735. list,notation,redefine,restriction,schema,selector,simpleContent,
  736. simpleType,union,unique
  737. attributes:
  738. id -- ID
  739. contents:
  740. (documentation | appinfo)*
  741. """
  742. attributes = {'id': None}
  743. contents = {'xsd': ('documentation', 'appinfo')}
  744. tag = 'annotation'
  745. def __init__(self, parent):
  746. XMLSchemaComponent.__init__(self, parent)
  747. self.content = None
  748. def fromDom(self, node):
  749. self.setAttributes(node)
  750. contents = self.getContents(node)
  751. content = []
  752. for i in contents:
  753. component = SplitQName(i.getTagName())[1]
  754. if component == 'documentation':
  755. # print_debug('class %s, documentation skipped' %self.__class__, 5)
  756. continue
  757. elif component == 'appinfo':
  758. # print_debug('class %s, appinfo skipped' %self.__class__, 5)
  759. continue
  760. else:
  761. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  762. self.content = tuple(content)
  763. class Documentation(XMLSchemaComponent):
  764. """<documentation>
  765. parent:
  766. annotation
  767. attributes:
  768. source, anyURI
  769. xml:lang, language
  770. contents:
  771. mixed, any
  772. """
  773. attributes = {'source': None, 'xml: lang': None}
  774. contents = {'xsd': ('mixed', 'any')}
  775. tag = 'documentation'
  776. def __init__(self, parent):
  777. XMLSchemaComponent.__init__(self, parent)
  778. self.content = None
  779. def fromDom(self, node):
  780. self.setAttributes(node)
  781. contents = self.getContents(node)
  782. content = []
  783. for i in contents:
  784. component = SplitQName(i.getTagName())[1]
  785. if component == 'mixed':
  786. # print_debug('class %s, mixed skipped' %self.__class__, 5)
  787. continue
  788. elif component == 'any':
  789. # print_debug('class %s, any skipped' %self.__class__, 5)
  790. continue
  791. else:
  792. raise SchemaError('Unknown component (%s)' %
  793. (i.getTagName()))
  794. self.content = tuple(content)
  795. class Appinfo(XMLSchemaComponent):
  796. """<appinfo>
  797. parent:
  798. annotation
  799. attributes:
  800. source, anyURI
  801. contents:
  802. mixed, any
  803. """
  804. attributes = {'source': None, 'anyURI': None}
  805. contents = {'xsd': ('mixed', 'any')}
  806. tag = 'appinfo'
  807. def __init__(self, parent):
  808. XMLSchemaComponent.__init__(self, parent)
  809. self.content = None
  810. def fromDom(self, node):
  811. self.setAttributes(node)
  812. contents = self.getContents(node)
  813. content = []
  814. for i in contents:
  815. component = SplitQName(i.getTagName())[1]
  816. if component == 'mixed':
  817. # print_debug('class %s, mixed skipped' %self.__class__, 5)
  818. continue
  819. elif component == 'any':
  820. # print_debug('class %s, any skipped' %self.__class__, 5)
  821. continue
  822. else:
  823. raise SchemaError('Unknown component (%s)' %
  824. (i.getTagName()))
  825. self.content = tuple(content)
  826. class XMLSchemaFake:
  827. # This is temporary, for the benefit of WSDL until the real thing works.
  828. def __init__(self, element):
  829. self.targetNamespace = DOM.getAttr(element, 'targetNamespace')
  830. self.element = element
  831. class XMLSchema(XMLSchemaComponent):
  832. """A schema is a collection of schema components derived from one
  833. or more schema documents, that is, one or more <schema> element
  834. information items. It represents the abstract notion of a schema
  835. rather than a single schema document (or other representation).
  836. <schema>
  837. parent:
  838. ROOT
  839. attributes:
  840. id -- ID
  841. version -- token
  842. xml:lang -- language
  843. targetNamespace -- anyURI
  844. attributeFormDefault -- 'qualified' | 'unqualified', 'unqualified'
  845. elementFormDefault -- 'qualified' | 'unqualified', 'unqualified'
  846. blockDefault -- '#all' | list of
  847. ('substitution | 'extension' | 'restriction')
  848. finalDefault -- '#all' | list of
  849. ('extension' | 'restriction' | 'list' | 'union')
  850. contents:
  851. ((include | import | redefine | annotation)*,
  852. (attribute, attributeGroup, complexType, element, group,
  853. notation, simpleType)*, annotation*)*
  854. attributes -- schema attributes
  855. imports -- import statements
  856. includes -- include statements
  857. redefines --
  858. types -- global simpleType, complexType definitions
  859. elements -- global element declarations
  860. attr_decl -- global attribute declarations
  861. attr_groups -- attribute Groups
  862. model_groups -- model Groups
  863. notations -- global notations
  864. """
  865. attributes = {'id': None,
  866. 'version': None,
  867. 'xml: lang': None,
  868. 'targetNamespace': None,
  869. 'attributeFormDefault': 'unqualified',
  870. 'elementFormDefault': 'unqualified',
  871. 'blockDefault': None,
  872. 'finalDefault': None}
  873. contents = {'xsd': ('include', 'import', 'redefine', 'annotation',
  874. 'attribute', 'attributeGroup', 'complexType',
  875. 'element', 'group', 'notation', 'simpleType',
  876. 'annotation')}
  877. empty_namespace = ''
  878. tag = 'schema'
  879. def __init__(self, parent=None, logger=None):
  880. """parent --
  881. instance variables:
  882. targetNamespace -- schema's declared targetNamespace, or empty string.
  883. _imported_schemas -- namespace keyed dict of schema dependencies, if
  884. a schema is provided instance will not resolve import statement.
  885. _included_schemas -- schemaLocation keyed dict of component schemas,
  886. if schema is provided instance will not resolve include statement.
  887. _base_url -- needed for relative URLs support, only works with URLs
  888. relative to initial document.
  889. includes -- collection of include statements
  890. imports -- collection of import statements
  891. elements -- collection of global element declarations
  892. types -- collection of global type definitions
  893. attr_decl -- collection of global attribute declarations
  894. attr_groups -- collection of global attribute group definitions
  895. model_groups -- collection of model group definitions
  896. notations -- collection of notations
  897. """
  898. self.__node = None
  899. self.targetNamespace = None
  900. XMLSchemaComponent.__init__(self, parent)
  901. f = lambda k: k.attributes['name']
  902. ns = lambda k: k.attributes['namespace']
  903. sl = lambda k: k.attributes['schemaLocation']
  904. self.includes = Collection(self, key=sl)
  905. self.imports = Collection(self, key=ns)
  906. self.elements = Collection(self, key=f)
  907. self.types = Collection(self, key=f)
  908. self.attr_decl = Collection(self, key=f)
  909. self.attr_groups = Collection(self, key=f)
  910. self.model_groups = Collection(self, key=f)
  911. self.notations = Collection(self, key=f)
  912. self._imported_schemas = {}
  913. self._included_schemas = {}
  914. self._base_url = None
  915. self.logger = logger or logging.getLogger(__name__)
  916. def getNode(self):
  917. """
  918. Interacting with the underlying DOM tree.
  919. """
  920. return self.__node
  921. def addImportSchema(self, schema):
  922. """for resolving import statements in Schema instance
  923. schema -- schema instance
  924. _imported_schemas
  925. """
  926. if not isinstance(schema, XMLSchema):
  927. raise TypeError('expecting a Schema instance')
  928. if schema.targetNamespace != self.targetNamespace:
  929. self._imported_schemas[schema.targetNamespace] = schema
  930. else:
  931. raise SchemaError('import schema bad targetNamespace')
  932. def addIncludeSchema(self, schemaLocation, schema):
  933. """for resolving include statements in Schema instance
  934. schemaLocation -- schema location
  935. schema -- schema instance
  936. _included_schemas
  937. """
  938. if not isinstance(schema, XMLSchema):
  939. raise TypeError('expecting a Schema instance')
  940. if not schema.targetNamespace or\
  941. schema.targetNamespace == self.targetNamespace:
  942. self._included_schemas[schemaLocation] = schema
  943. else:
  944. raise SchemaError('include schema bad targetNamespace')
  945. def setImportSchemas(self, schema_dict):
  946. """set the import schema dictionary, which is used to
  947. reference depedent schemas.
  948. """
  949. self._imported_schemas = schema_dict
  950. def getImportSchemas(self):
  951. """get the import schema dictionary, which is used to
  952. reference depedent schemas.
  953. """
  954. return self._imported_schemas
  955. def getSchemaNamespacesToImport(self):
  956. """returns tuple of namespaces the schema instance has declared
  957. itself to be depedent upon.
  958. """
  959. return tuple(self.includes.keys())
  960. def setIncludeSchemas(self, schema_dict):
  961. """set the include schema dictionary, which is keyed with
  962. schemaLocation (uri).
  963. This is a means of providing
  964. schemas to the current schema for content inclusion.
  965. """
  966. self._included_schemas = schema_dict
  967. def getIncludeSchemas(self):
  968. """get the include schema dictionary, which is keyed with
  969. schemaLocation (uri).
  970. """
  971. return self._included_schemas
  972. def getBaseUrl(self):
  973. """get base url, used for normalizing all relative uri's
  974. """
  975. return self._base_url
  976. def setBaseUrl(self, url):
  977. """set base url, used for normalizing all relative uri's
  978. """
  979. self._base_url = url
  980. def getElementFormDefault(self):
  981. """return elementFormDefault attribute
  982. """
  983. return self.attributes.get('elementFormDefault')
  984. def isElementFormDefaultQualified(self):
  985. return self.attributes.get('elementFormDefault') == 'qualified'
  986. def getAttributeFormDefault(self):
  987. """return attributeFormDefault attribute
  988. """
  989. return self.attributes.get('attributeFormDefault')
  990. def getBlockDefault(self):
  991. """return blockDefault attribute
  992. """
  993. return self.attributes.get('blockDefault')
  994. def getFinalDefault(self):
  995. """return finalDefault attribute
  996. """
  997. return self.attributes.get('finalDefault')
  998. def load(self, node, location=None):
  999. self.__node = node
  1000. pnode = node.getParentNode()
  1001. if pnode:
  1002. pname = SplitQName(pnode.getTagName())[1]
  1003. if pname == 'types':
  1004. attributes = {}
  1005. self.setAttributes(pnode)
  1006. attributes.update(self.attributes)
  1007. self.setAttributes(node)
  1008. for k, v in list(attributes['xmlns'].items()):
  1009. if k not in self.attributes['xmlns']:
  1010. self.attributes['xmlns'][k] = v
  1011. else:
  1012. self.setAttributes(node)
  1013. else:
  1014. self.setAttributes(node)
  1015. self.targetNamespace = self.getTargetNamespace()
  1016. for childNode in self.getContents(node):
  1017. component = SplitQName(childNode.getTagName())[1]
  1018. if component == 'include':
  1019. tp = self.__class__.Include(self)
  1020. tp.fromDom(childNode)
  1021. sl = tp.attributes['schemaLocation']
  1022. schema = tp.getSchema()
  1023. if sl not in self.getIncludeSchemas():
  1024. self.addIncludeSchema(sl, schema)
  1025. self.includes[sl] = tp
  1026. pn = childNode.getParentNode().getNode()
  1027. pn.removeChild(childNode.getNode())
  1028. for child in schema.getNode().getNode().childNodes:
  1029. pn.appendChild(child.cloneNode(1))
  1030. for collection in ['imports', 'elements', 'types',
  1031. 'attr_decl', 'attr_groups', 'model_groups',
  1032. 'notations']:
  1033. for k, v in list(getattr(schema, collection).items()):
  1034. if k not in getattr(self, collection):
  1035. v._parent = weakref.ref(self)
  1036. getattr(self, collection)[k] = v
  1037. else:
  1038. warnings.warn("Not keeping schema component.")
  1039. elif component == 'import':
  1040. slocd = SchemaReader.namespaceToSchema
  1041. tp = self.__class__.Import(self)
  1042. tp.fromDom(childNode)
  1043. import_ns = tp.getAttribute('namespace') or\
  1044. self.__class__.empty_namespace
  1045. schema = slocd.get(import_ns)
  1046. if schema is None:
  1047. schema = XMLSchema()
  1048. slocd[import_ns] = schema
  1049. try:
  1050. tp.loadSchema(schema)
  1051. except NoSchemaLocationWarning as ex:
  1052. # Dependency declaration, hopefully implementation
  1053. # is aware of this namespace (eg. SOAP,WSDL,?)
  1054. self.logger.debug("IMPORT: %s : %s" % (import_ns, ex))
  1055. del slocd[import_ns]
  1056. continue
  1057. except SchemaError as ex:
  1058. # warnings.warn(\
  1059. # '<import namespace="%s" schemaLocation=?>, %s'\
  1060. # %(import_ns, 'failed to load schema instance')
  1061. # )
  1062. self.logger.debug(ex)
  1063. del slocd[import_ns]
  1064. class _LazyEvalImport(str):
  1065. '''Lazy evaluation of import, replace entry in self.imports.'''
  1066. # attributes = dict(namespace=import_ns)
  1067. def getSchema(namespace):
  1068. schema = slocd.get(namespace)
  1069. if schema is None:
  1070. parent = self._parent()
  1071. wstypes = parent
  1072. if isinstance(parent, WSDLToolsAdapter):
  1073. wstypes = parent.getImportSchemas()
  1074. schema = wstypes.get(namespace)
  1075. if isinstance(schema, XMLSchema):
  1076. self.imports[namespace] = schema
  1077. return schema
  1078. return None
  1079. self.imports[import_ns] = _LazyEvalImport(import_ns)
  1080. continue
  1081. else:
  1082. tp._schema = schema
  1083. if import_ns in self.getImportSchemas():
  1084. warnings.warn(
  1085. 'Detected multiple imports of the namespace "%s" '
  1086. % import_ns)
  1087. self.addImportSchema(schema)
  1088. # spec says can have multiple imports of same namespace
  1089. # but purpose of import is just dependency declaration.
  1090. self.imports[import_ns] = tp
  1091. elif component == 'redefine':
  1092. warnings.warn('redefine is ignored')
  1093. elif component == 'annotation':
  1094. warnings.warn('annotation is ignored')
  1095. elif component == 'attribute':
  1096. tp = AttributeDeclaration(self)
  1097. tp.fromDom(childNode)
  1098. self.attr_decl[tp.getAttribute('name')] = tp
  1099. elif component == 'attributeGroup':
  1100. tp = AttributeGroupDefinition(self)
  1101. tp.fromDom(childNode)
  1102. self.attr_groups[tp.getAttribute('name')] = tp
  1103. elif component == 'element':
  1104. tp = ElementDeclaration(self)
  1105. tp.fromDom(childNode)
  1106. self.elements[tp.getAttribute('name')] = tp
  1107. elif component == 'group':
  1108. tp = ModelGroupDefinition(self)
  1109. tp.fromDom(childNode)
  1110. self.model_groups[tp.getAttribute('name')] = tp
  1111. elif component == 'notation':
  1112. tp = Notation(self)
  1113. tp.fromDom(childNode)
  1114. self.notations[tp.getAttribute('name')] = tp
  1115. elif component == 'complexType':
  1116. tp = ComplexType(self)
  1117. tp.fromDom(childNode)
  1118. self.types[tp.getAttribute('name')] = tp
  1119. elif component == 'simpleType':
  1120. tp = SimpleType(self)
  1121. tp.fromDom(childNode)
  1122. self.types[tp.getAttribute('name')] = tp
  1123. else:
  1124. break
  1125. class Import(XMLSchemaComponent):
  1126. """<import>
  1127. parent:
  1128. schema
  1129. attributes:
  1130. id -- ID
  1131. namespace -- anyURI
  1132. schemaLocation -- anyURI
  1133. contents:
  1134. annotation?
  1135. """
  1136. attributes = {'id': None,
  1137. 'namespace': None,
  1138. 'schemaLocation': None}
  1139. contents = {'xsd': ['annotation']}
  1140. tag = 'import'
  1141. def __init__(self, parent):
  1142. XMLSchemaComponent.__init__(self, parent)
  1143. self.annotation = None
  1144. self._schema = None
  1145. def fromDom(self, node):
  1146. self.setAttributes(node)
  1147. contents = self.getContents(node)
  1148. if self.attributes['namespace'] == self.getTargetNamespace():
  1149. raise SchemaError('namespace of schema and import match')
  1150. for i in contents:
  1151. component = SplitQName(i.getTagName())[1]
  1152. if component == 'annotation' and not self.annotation:
  1153. self.annotation = Annotation(self)
  1154. self.annotation.fromDom(i)
  1155. else:
  1156. raise SchemaError('Unknown component (%s)' %
  1157. (i.getTagName()))
  1158. def getSchema(self):
  1159. """if schema is not defined, first look for a Schema class instance
  1160. in parent Schema. Else if not defined resolve schemaLocation
  1161. and create a new Schema class instance, and keep a hard reference.
  1162. """
  1163. if not self._schema:
  1164. ns = self.attributes['namespace']
  1165. schema = self._parent().getImportSchemas().get(ns)
  1166. if not schema and self._parent()._parent:
  1167. schema = self._parent()._parent().getImportSchemas().get(ns)
  1168. if not schema:
  1169. url = self.attributes.get('schemaLocation')
  1170. if not url:
  1171. raise SchemaError('namespace(%s) is unknown' % ns)
  1172. base_url = self._parent().getBaseUrl()
  1173. reader = SchemaReader(base_url=base_url)
  1174. reader._imports = self._parent().getImportSchemas()
  1175. reader._includes = self._parent().getIncludeSchemas()
  1176. self._schema = reader.loadFromURL(url)
  1177. return self._schema or schema
  1178. def loadSchema(self, schema):
  1179. """
  1180. """
  1181. base_url = self._parent().getBaseUrl()
  1182. reader = SchemaReader(base_url=base_url)
  1183. reader._imports = self._parent().getImportSchemas()
  1184. reader._includes = self._parent().getIncludeSchemas()
  1185. self._schema = schema
  1186. if 'schemaLocation' not in self.attributes:
  1187. raise NoSchemaLocationWarning(
  1188. 'no schemaLocation attribute in import')
  1189. reader.loadFromURL(self.attributes.get('schemaLocation'), schema)
  1190. class Include(XMLSchemaComponent):
  1191. """<include schemaLocation>
  1192. parent:
  1193. schema
  1194. attributes:
  1195. id -- ID
  1196. schemaLocation -- anyURI, required
  1197. contents:
  1198. annotation?
  1199. """
  1200. required = ['schemaLocation']
  1201. attributes = {'id': None,
  1202. 'schemaLocation': None}
  1203. contents = {'xsd': ['annotation']}
  1204. tag = 'include'
  1205. def __init__(self, parent):
  1206. XMLSchemaComponent.__init__(self, parent)
  1207. self.annotation = None
  1208. self._schema = None
  1209. def fromDom(self, node):
  1210. self.setAttributes(node)
  1211. contents = self.getContents(node)
  1212. for i in contents:
  1213. component = SplitQName(i.getTagName())[1]
  1214. if component == 'annotation' and not self.annotation:
  1215. self.annotation = Annotation(self)
  1216. self.annotation.fromDom(i)
  1217. else:
  1218. raise SchemaError('Unknown component (%s)' %
  1219. (i.getTagName()))
  1220. def getSchema(self):
  1221. """if schema is not defined, first look for a Schema class instance
  1222. in parent Schema. Else if not defined resolve schemaLocation
  1223. and create a new Schema class instance.
  1224. """
  1225. if not self._schema:
  1226. schema = self._parent()
  1227. self._schema = schema.getIncludeSchemas().get(
  1228. self.attributes['schemaLocation'])
  1229. if not self._schema:
  1230. url = self.attributes['schemaLocation']
  1231. reader = SchemaReader(base_url=schema.getBaseUrl())
  1232. reader._imports = schema.getImportSchemas()
  1233. reader._includes = schema.getIncludeSchemas()
  1234. # create schema before loading so chameleon include
  1235. # will evalute targetNamespace correctly.
  1236. self._schema = XMLSchema(schema)
  1237. reader.loadFromURL(url, self._schema)
  1238. return self._schema
  1239. class AttributeDeclaration(XMLSchemaComponent,
  1240. AttributeMarker,
  1241. DeclarationMarker):
  1242. """<attribute name>
  1243. parent:
  1244. schema
  1245. attributes:
  1246. id -- ID
  1247. name -- NCName, required
  1248. type -- QName
  1249. default -- string
  1250. fixed -- string
  1251. contents:
  1252. annotation?, simpleType?
  1253. """
  1254. required = ['name']
  1255. attributes = {'id': None,
  1256. 'name': None,
  1257. 'type': None,
  1258. 'default': None,
  1259. 'fixed': None}
  1260. contents = {'xsd': ['annotation', 'simpleType']}
  1261. tag = 'attribute'
  1262. def __init__(self, parent):
  1263. XMLSchemaComponent.__init__(self, parent)
  1264. self.annotation = None
  1265. self.content = None
  1266. def fromDom(self, node):
  1267. """ No list or union support
  1268. """
  1269. self.setAttributes(node)
  1270. contents = self.getContents(node)
  1271. for i in contents:
  1272. component = SplitQName(i.getTagName())[1]
  1273. if component == 'annotation' and not self.annotation:
  1274. self.annotation = Annotation(self)
  1275. self.annotation.fromDom(i)
  1276. elif component == 'simpleType':
  1277. self.content = AnonymousSimpleType(self)
  1278. self.content.fromDom(i)
  1279. else:
  1280. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  1281. class LocalAttributeDeclaration(AttributeDeclaration,
  1282. AttributeMarker,
  1283. LocalMarker,
  1284. DeclarationMarker):
  1285. """<attribute name>
  1286. parent:
  1287. complexType, restriction, extension, attributeGroup
  1288. attributes:
  1289. id -- ID
  1290. name -- NCName, required
  1291. type -- QName
  1292. form -- ('qualified' | 'unqualified'), schema.attributeFormDefault
  1293. use -- ('optional' | 'prohibited' | 'required'), optional
  1294. default -- string
  1295. fixed -- string
  1296. contents:
  1297. annotation?, simpleType?
  1298. """
  1299. required = ['name']
  1300. attributes = {'id': None,
  1301. 'name': None,
  1302. 'type': None,
  1303. 'form': lambda self: GetSchema(self).getAttributeFormDefault(),
  1304. 'use': 'optional',
  1305. 'default': None,
  1306. 'fixed': None}
  1307. contents = {'xsd': ['annotation', 'simpleType']}
  1308. def __init__(self, parent):
  1309. AttributeDeclaration.__init__(self, parent)
  1310. self.annotation = None
  1311. self.content = None
  1312. def fromDom(self, node):
  1313. self.setAttributes(node)
  1314. contents = self.getContents(node)
  1315. for i in contents:
  1316. component = SplitQName(i.getTagName())[1]
  1317. if component == 'annotation' and not self.annotation:
  1318. self.annotation = Annotation(self)
  1319. self.annotation.fromDom(i)
  1320. elif component == 'simpleType':
  1321. self.content = AnonymousSimpleType(self)
  1322. self.content.fromDom(i)
  1323. else:
  1324. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  1325. class AttributeWildCard(XMLSchemaComponent,
  1326. AttributeMarker,
  1327. DeclarationMarker,
  1328. WildCardMarker):
  1329. """<anyAttribute>
  1330. parents:
  1331. complexType, restriction, extension, attributeGroup
  1332. attributes:
  1333. id -- ID
  1334. namespace -- '##any' | '##other' |
  1335. (anyURI* | '##targetNamespace' | '##local'), ##any
  1336. processContents -- 'lax' | 'skip' | 'strict', strict
  1337. contents:
  1338. annotation?
  1339. """
  1340. attributes = {'id': None,
  1341. 'namespace': '##any',
  1342. 'processContents': 'strict'}
  1343. contents = {'xsd': ['annotation']}
  1344. tag = 'anyAttribute'
  1345. def __init__(self, parent):
  1346. XMLSchemaComponent.__init__(self, parent)
  1347. self.annotation = None
  1348. def fromDom(self, node):
  1349. self.setAttributes(node)
  1350. contents = self.getContents(node)
  1351. for i in contents:
  1352. component = SplitQName(i.getTagName())[1]
  1353. if component == 'annotation' and not self.annotation:
  1354. self.annotation = Annotation(self)
  1355. self.annotation.fromDom(i)
  1356. else:
  1357. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  1358. class AttributeReference(XMLSchemaComponent,
  1359. AttributeMarker,
  1360. ReferenceMarker):
  1361. """<attribute ref>
  1362. parents:
  1363. complexType, restriction, extension, attributeGroup
  1364. attributes:
  1365. id -- ID
  1366. ref -- QName, required
  1367. use -- ('optional' | 'prohibited' | 'required'), optional
  1368. default -- string
  1369. fixed -- string
  1370. contents:
  1371. annotation?
  1372. """
  1373. required = ['ref']
  1374. attributes = {'id': None,
  1375. 'ref': None,
  1376. 'use': 'optional',
  1377. 'default': None,
  1378. 'fixed': None}
  1379. contents = {'xsd': ['annotation']}
  1380. tag = 'attribute'
  1381. def __init__(self, parent):
  1382. XMLSchemaComponent.__init__(self, parent)
  1383. self.annotation = None
  1384. def getAttributeDeclaration(self, attribute='ref'):
  1385. return XMLSchemaComponent.getAttributeDeclaration(self, attribute)
  1386. def fromDom(self, node):
  1387. self.setAttributes(node)
  1388. contents = self.getContents(node)
  1389. for i in contents:
  1390. component = SplitQName(i.getTagName())[1]
  1391. if component == 'annotation' and not self.annotation:
  1392. self.annotation = Annotation(self)
  1393. self.annotation.fromDom(i)
  1394. else:
  1395. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  1396. class AttributeGroupDefinition(XMLSchemaComponent,
  1397. AttributeGroupMarker,
  1398. DefinitionMarker):
  1399. """<attributeGroup name>
  1400. parents:
  1401. schema, redefine
  1402. attributes:
  1403. id -- ID
  1404. name -- NCName, required
  1405. contents:
  1406. annotation?, (attribute | attributeGroup)*, anyAttribute?
  1407. """
  1408. required = ['name']
  1409. attributes = {'id': None,
  1410. 'name': None}
  1411. contents = {'xsd': ['annotation', 'attribute',
  1412. 'attributeGroup', 'anyAttribute']}
  1413. tag = 'attributeGroup'
  1414. def __init__(self, parent):
  1415. XMLSchemaComponent.__init__(self, parent)
  1416. self.annotation = None
  1417. self.attr_content = None
  1418. def getAttributeContent(self):
  1419. return self.attr_content
  1420. def fromDom(self, node):
  1421. self.setAttributes(node)
  1422. contents = self.getContents(node)
  1423. content = []
  1424. for indx in range(len(contents)):
  1425. component = SplitQName(contents[indx].getTagName())[1]
  1426. if (component == 'annotation') and (not indx):
  1427. self.annotation = Annotation(self)
  1428. self.annotation.fromDom(contents[indx])
  1429. elif component == 'attribute':
  1430. if contents[indx].hasattr('name'):
  1431. content.append(LocalAttributeDeclaration(self))
  1432. elif contents[indx].hasattr('ref'):
  1433. content.append(AttributeReference(self))
  1434. else:
  1435. raise SchemaError('Unknown attribute type')
  1436. content[-1].fromDom(contents[indx])
  1437. elif component == 'attributeGroup':
  1438. content.append(AttributeGroupReference(self))
  1439. content[-1].fromDom(contents[indx])
  1440. elif component == 'anyAttribute':
  1441. if len(contents) != indx + 1:
  1442. raise SchemaError(
  1443. 'anyAttribute is out of order in %s' % self.getItemTrace())
  1444. content.append(AttributeWildCard(self))
  1445. content[-1].fromDom(contents[indx])
  1446. else:
  1447. raise SchemaError('Unknown component (%s)' %
  1448. (contents[indx].getTagName()))
  1449. self.attr_content = tuple(content)
  1450. class AttributeGroupReference(XMLSchemaComponent,
  1451. AttributeGroupMarker,
  1452. ReferenceMarker):
  1453. """<attributeGroup ref>
  1454. parents:
  1455. complexType, restriction, extension, attributeGroup
  1456. attributes:
  1457. id -- ID
  1458. ref -- QName, required
  1459. contents:
  1460. annotation?
  1461. """
  1462. required = ['ref']
  1463. attributes = {'id': None,
  1464. 'ref': None}
  1465. contents = {'xsd': ['annotation']}
  1466. tag = 'attributeGroup'
  1467. def __init__(self, parent):
  1468. XMLSchemaComponent.__init__(self, parent)
  1469. self.annotation = None
  1470. def getAttributeGroup(self, attribute='ref'):
  1471. """attribute -- attribute with a QName value (eg. type).
  1472. collection -- check types collection in parent Schema instance
  1473. """
  1474. return XMLSchemaComponent.getAttributeGroup(self, attribute)
  1475. def fromDom(self, node):
  1476. self.setAttributes(node)
  1477. contents = self.getContents(node)
  1478. for i in contents:
  1479. component = SplitQName(i.getTagName())[1]
  1480. if component == 'annotation' and not self.annotation:
  1481. self.annotation = Annotation(self)
  1482. self.annotation.fromDom(i)
  1483. else:
  1484. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  1485. ######################################################
  1486. # Elements
  1487. #####################################################
  1488. class IdentityConstrants(XMLSchemaComponent):
  1489. """Allow one to uniquely identify nodes in a document and ensure the
  1490. integrity of references between them.
  1491. attributes -- dictionary of attributes
  1492. selector -- XPath to selected nodes
  1493. fields -- list of XPath to key field
  1494. """
  1495. def __init__(self, parent):
  1496. XMLSchemaComponent.__init__(self, parent)
  1497. self.selector = None
  1498. self.fields = None
  1499. self.annotation = None
  1500. def fromDom(self, node):
  1501. self.setAttributes(node)
  1502. contents = self.getContents(node)
  1503. fields = []
  1504. for i in contents:
  1505. component = SplitQName(i.getTagName())[1]
  1506. if component in self.__class__.contents['xsd']:
  1507. if component == 'annotation' and not self.annotation:
  1508. self.annotation = Annotation(self)
  1509. self.annotation.fromDom(i)
  1510. elif component == 'selector':
  1511. self.selector = self.Selector(self)
  1512. self.selector.fromDom(i)
  1513. continue
  1514. elif component == 'field':
  1515. fields.append(self.Field(self))
  1516. fields[-1].fromDom(i)
  1517. continue
  1518. else:
  1519. raise SchemaError('Unknown component (%s)' %
  1520. (i.getTagName()))
  1521. else:
  1522. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  1523. self.fields = tuple(fields)
  1524. class Constraint(XMLSchemaComponent):
  1525. def __init__(self, parent):
  1526. XMLSchemaComponent.__init__(self, parent)
  1527. self.annotation = None
  1528. def fromDom(self, node):
  1529. self.setAttributes(node)
  1530. contents = self.getContents(node)
  1531. for i in contents:
  1532. component = SplitQName(i.getTagName())[1]
  1533. if component in self.__class__.contents['xsd']:
  1534. if component == 'annotation' and not self.annotation:
  1535. self.annotation = Annotation(self)
  1536. self.annotation.fromDom(i)
  1537. else:
  1538. raise SchemaError(
  1539. 'Unknown component (%s)' % (i.getTagName()))
  1540. else:
  1541. raise SchemaError('Unknown component (%s)' %
  1542. (i.getTagName()))
  1543. class Selector(Constraint):
  1544. """<selector xpath>
  1545. parent:
  1546. unique, key, keyref
  1547. attributes:
  1548. id -- ID
  1549. xpath -- XPath subset, required
  1550. contents:
  1551. annotation?
  1552. """
  1553. required = ['xpath']
  1554. attributes = {'id': None,
  1555. 'xpath': None}
  1556. contents = {'xsd': ['annotation']}
  1557. tag = 'selector'
  1558. class Field(Constraint):
  1559. """<field xpath>
  1560. parent:
  1561. unique, key, keyref
  1562. attributes:
  1563. id -- ID
  1564. xpath -- XPath subset, required
  1565. contents:
  1566. annotation?
  1567. """
  1568. required = ['xpath']
  1569. attributes = {'id': None,
  1570. 'xpath': None}
  1571. contents = {'xsd': ['annotation']}
  1572. tag = 'field'
  1573. class Unique(IdentityConstrants):
  1574. """<unique name> Enforce fields are unique w/i a specified scope.
  1575. parent:
  1576. element
  1577. attributes:
  1578. id -- ID
  1579. name -- NCName, required
  1580. contents:
  1581. annotation?, selector, field+
  1582. """
  1583. required = ['name']
  1584. attributes = {'id': None,
  1585. 'name': None}
  1586. contents = {'xsd': ['annotation', 'selector', 'field']}
  1587. tag = 'unique'
  1588. class Key(IdentityConstrants):
  1589. """<key name> Enforce fields are unique w/i a specified scope, and all
  1590. field values are present w/i document. Fields cannot
  1591. be nillable.
  1592. parent:
  1593. element
  1594. attributes:
  1595. id -- ID
  1596. name -- NCName, required
  1597. contents:
  1598. annotation?, selector, field+
  1599. """
  1600. required = ['name']
  1601. attributes = {'id': None,
  1602. 'name': None}
  1603. contents = {'xsd': ['annotation', 'selector', 'field']}
  1604. tag = 'key'
  1605. class KeyRef(IdentityConstrants):
  1606. """<keyref name refer> Ensure a match between two sets of values in an
  1607. instance.
  1608. parent:
  1609. element
  1610. attributes:
  1611. id -- ID
  1612. name -- NCName, required
  1613. refer -- QName, required
  1614. contents:
  1615. annotation?, selector, field+
  1616. """
  1617. required = ['name', 'refer']
  1618. attributes = {'id': None,
  1619. 'name': None,
  1620. 'refer': None}
  1621. contents = {'xsd': ['annotation', 'selector', 'field']}
  1622. tag = 'keyref'
  1623. class ElementDeclaration(XMLSchemaComponent,
  1624. ElementMarker,
  1625. DeclarationMarker):
  1626. """<element name>
  1627. parents:
  1628. schema
  1629. attributes:
  1630. id -- ID
  1631. name -- NCName, required
  1632. type -- QName
  1633. default -- string
  1634. fixed -- string
  1635. nillable -- boolean, false
  1636. abstract -- boolean, false
  1637. substitutionGroup -- QName
  1638. block -- ('#all' | ('substition' | 'extension' | 'restriction')*),
  1639. schema.blockDefault
  1640. final -- ('#all' | ('extension' | 'restriction')*),
  1641. schema.finalDefault
  1642. contents:
  1643. annotation?, (simpleType,complexType)?, (key | keyref | unique)*
  1644. """
  1645. required = ['name']
  1646. attributes = {'id': None,
  1647. 'name': None,
  1648. 'type': None,
  1649. 'default': None,
  1650. 'fixed': None,
  1651. 'nillable': 0,
  1652. 'abstract': 0,
  1653. 'substitutionGroup': None,
  1654. 'block': lambda self: self._parent().getBlockDefault(),
  1655. 'final': lambda self: self._parent().getFinalDefault()}
  1656. contents = {'xsd': ['annotation', 'simpleType', 'complexType', 'key',
  1657. 'keyref', 'unique']}
  1658. tag = 'element'
  1659. def __init__(self, parent):
  1660. XMLSchemaComponent.__init__(self, parent)
  1661. self.annotation = None
  1662. self.content = None
  1663. self.constraints = ()
  1664. def isQualified(self):
  1665. """Global elements are always qualified.
  1666. """
  1667. return True
  1668. def getAttribute(self, attribute):
  1669. """return attribute.
  1670. If attribute is type and it's None, and no simple or complex content,
  1671. return the default type "xsd:anyType"
  1672. """
  1673. value = XMLSchemaComponent.getAttribute(self, attribute)
  1674. if attribute != 'type' or value is not None:
  1675. return value
  1676. if self.content is not None:
  1677. return None
  1678. parent = self
  1679. while 1:
  1680. nsdict = parent.attributes[XMLSchemaComponent.xmlns]
  1681. for k, v in list(nsdict.items()):
  1682. if v not in SCHEMA.XSD_LIST:
  1683. continue
  1684. return TypeDescriptionComponent((v, 'anyType'))
  1685. if isinstance(parent, WSDLToolsAdapter)\
  1686. or not hasattr(parent, '_parent'):
  1687. break
  1688. parent = parent._parent()
  1689. raise SchemaError('failed to locate the XSD namespace')
  1690. def getElementDeclaration(self, attribute):
  1691. raise Warning('invalid operation for <%s>' % self.tag)
  1692. def getTypeDefinition(self, attribute=None):
  1693. """If attribute is None, "type" is assumed, return the corresponding
  1694. representation of the global type definition (TypeDefinition),
  1695. or the local definition if don't find "type". To maintain backwards
  1696. compat, if attribute is provided call base class method.
  1697. """
  1698. if attribute:
  1699. return XMLSchemaComponent.getTypeDefinition(self, attribute)
  1700. gt = XMLSchemaComponent.getTypeDefinition(self, 'type')
  1701. if gt:
  1702. return gt
  1703. return self.content
  1704. def getConstraints(self):
  1705. return self._constraints
  1706. def setConstraints(self, constraints):
  1707. self._constraints = tuple(constraints)
  1708. constraints = property(getConstraints, setConstraints,
  1709. None, "tuple of key, keyref, unique constraints")
  1710. def fromDom(self, node):
  1711. self.setAttributes(node)
  1712. contents = self.getContents(node)
  1713. constraints = []
  1714. for i in contents:
  1715. component = SplitQName(i.getTagName())[1]
  1716. if component in self.__class__.contents['xsd']:
  1717. if component == 'annotation' and not self.annotation:
  1718. self.annotation = Annotation(self)
  1719. self.annotation.fromDom(i)
  1720. elif component == 'simpleType' and not self.content:
  1721. self.content = AnonymousSimpleType(self)
  1722. self.content.fromDom(i)
  1723. elif component == 'complexType' and not self.content:
  1724. self.content = LocalComplexType(self)
  1725. self.content.fromDom(i)
  1726. elif component == 'key':
  1727. constraints.append(Key(self))
  1728. constraints[-1].fromDom(i)
  1729. elif component == 'keyref':
  1730. constraints.append(KeyRef(self))
  1731. constraints[-1].fromDom(i)
  1732. elif component == 'unique':
  1733. constraints.append(Unique(self))
  1734. constraints[-1].fromDom(i)
  1735. else:
  1736. raise SchemaError('Unknown component (%s)' %
  1737. (i.getTagName()))
  1738. else:
  1739. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  1740. self.constraints = constraints
  1741. class LocalElementDeclaration(ElementDeclaration,
  1742. LocalMarker):
  1743. """<element>
  1744. parents:
  1745. all, choice, sequence
  1746. attributes:
  1747. id -- ID
  1748. name -- NCName, required
  1749. form -- ('qualified' | 'unqualified'), schema.elementFormDefault
  1750. type -- QName
  1751. minOccurs -- Whole Number, 1
  1752. maxOccurs -- (Whole Number | 'unbounded'), 1
  1753. default -- string
  1754. fixed -- string
  1755. nillable -- boolean, false
  1756. block -- ('#all' | ('extension' | 'restriction')*), schema.blockDefault
  1757. contents:
  1758. annotation?, (simpleType,complexType)?, (key | keyref | unique)*
  1759. """
  1760. required = ['name']
  1761. attributes = {'id': None,
  1762. 'name': None,
  1763. 'form': lambda self: GetSchema(self).getElementFormDefault(),
  1764. 'type': None,
  1765. 'minOccurs': '1',
  1766. 'maxOccurs': '1',
  1767. 'default': None,
  1768. 'fixed': None,
  1769. 'nillable': 0,
  1770. 'abstract': 0,
  1771. 'block': lambda self: GetSchema(self).getBlockDefault()}
  1772. contents = {'xsd': ['annotation', 'simpleType', 'complexType', 'key',
  1773. 'keyref', 'unique']}
  1774. def isQualified(self):
  1775. """
  1776. Local elements can be qualified or unqualifed according
  1777. to the attribute form, or the elementFormDefault. By default
  1778. local elements are unqualified.
  1779. """
  1780. form = self.getAttribute('form')
  1781. if form == 'qualified':
  1782. return True
  1783. if form == 'unqualified':
  1784. return False
  1785. raise SchemaError('Bad form (%s) for element: %s' %
  1786. (form, self.getItemTrace()))
  1787. class ElementReference(XMLSchemaComponent,
  1788. ElementMarker,
  1789. ReferenceMarker):
  1790. """<element ref>
  1791. parents:
  1792. all, choice, sequence
  1793. attributes:
  1794. id -- ID
  1795. ref -- QName, required
  1796. minOccurs -- Whole Number, 1
  1797. maxOccurs -- (Whole Number | 'unbounded'), 1
  1798. contents:
  1799. annotation?
  1800. """
  1801. required = ['ref']
  1802. attributes = {'id': None,
  1803. 'ref': None,
  1804. 'minOccurs': '1',
  1805. 'maxOccurs': '1'}
  1806. contents = {'xsd': ['annotation']}
  1807. tag = 'element'
  1808. def __init__(self, parent):
  1809. XMLSchemaComponent.__init__(self, parent)
  1810. self.annotation = None
  1811. def getElementDeclaration(self, attribute=None):
  1812. """If attribute is None, "ref" is assumed, return the corresponding
  1813. representation of the global element declaration (ElementDeclaration),
  1814. To maintain backwards compat, if attribute is provided call base class method.
  1815. """
  1816. if attribute:
  1817. return XMLSchemaComponent.getElementDeclaration(self, attribute)
  1818. return XMLSchemaComponent.getElementDeclaration(self, 'ref')
  1819. def fromDom(self, node):
  1820. self.annotation = None
  1821. self.setAttributes(node)
  1822. for i in self.getContents(node):
  1823. component = SplitQName(i.getTagName())[1]
  1824. if component in self.__class__.contents['xsd']:
  1825. if component == 'annotation' and not self.annotation:
  1826. self.annotation = Annotation(self)
  1827. self.annotation.fromDom(i)
  1828. else:
  1829. raise SchemaError('Unknown component (%s)' %
  1830. (i.getTagName()))
  1831. class ElementWildCard(LocalElementDeclaration, WildCardMarker):
  1832. """<any>
  1833. parents:
  1834. choice, sequence
  1835. attributes:
  1836. id -- ID
  1837. minOccurs -- Whole Number, 1
  1838. maxOccurs -- (Whole Number | 'unbounded'), 1
  1839. namespace -- '##any' | '##other' |
  1840. (anyURI* | '##targetNamespace' | '##local'), ##any
  1841. processContents -- 'lax' | 'skip' | 'strict', strict
  1842. contents:
  1843. annotation?
  1844. """
  1845. required = []
  1846. attributes = {'id': None,
  1847. 'minOccurs': '1',
  1848. 'maxOccurs': '1',
  1849. 'namespace': '##any',
  1850. 'processContents': 'strict'}
  1851. contents = {'xsd': ['annotation']}
  1852. tag = 'any'
  1853. def __init__(self, parent):
  1854. XMLSchemaComponent.__init__(self, parent)
  1855. self.annotation = None
  1856. def isQualified(self):
  1857. """
  1858. Global elements are always qualified, but if processContents
  1859. are not strict could have dynamically generated local elements.
  1860. """
  1861. return GetSchema(self).isElementFormDefaultQualified()
  1862. def getAttribute(self, attribute):
  1863. """return attribute.
  1864. """
  1865. return XMLSchemaComponent.getAttribute(self, attribute)
  1866. def getTypeDefinition(self, attribute):
  1867. raise Warning('invalid operation for <%s>' % self.tag)
  1868. def fromDom(self, node):
  1869. self.annotation = None
  1870. self.setAttributes(node)
  1871. for i in self.getContents(node):
  1872. component = SplitQName(i.getTagName())[1]
  1873. if component in self.__class__.contents['xsd']:
  1874. if component == 'annotation' and not self.annotation:
  1875. self.annotation = Annotation(self)
  1876. self.annotation.fromDom(i)
  1877. else:
  1878. raise SchemaError('Unknown component (%s)' %
  1879. (i.getTagName()))
  1880. ######################################################
  1881. # Model Groups
  1882. #####################################################
  1883. class Sequence(XMLSchemaComponent,
  1884. SequenceMarker):
  1885. """<sequence>
  1886. parents:
  1887. complexType, extension, restriction, group, choice, sequence
  1888. attributes:
  1889. id -- ID
  1890. minOccurs -- Whole Number, 1
  1891. maxOccurs -- (Whole Number | 'unbounded'), 1
  1892. contents:
  1893. annotation?, (element | group | choice | sequence | any)*
  1894. """
  1895. attributes = {'id': None,
  1896. 'minOccurs': '1',
  1897. 'maxOccurs': '1'}
  1898. contents = {'xsd': ['annotation', 'element', 'group', 'choice', 'sequence',
  1899. 'any']}
  1900. tag = 'sequence'
  1901. def __init__(self, parent):
  1902. XMLSchemaComponent.__init__(self, parent)
  1903. self.annotation = None
  1904. self.content = None
  1905. def fromDom(self, node):
  1906. self.setAttributes(node)
  1907. contents = self.getContents(node)
  1908. content = []
  1909. for i in contents:
  1910. component = SplitQName(i.getTagName())[1]
  1911. if component in self.__class__.contents['xsd']:
  1912. if component == 'annotation' and not self.annotation:
  1913. self.annotation = Annotation(self)
  1914. self.annotation.fromDom(i)
  1915. continue
  1916. elif component == 'element':
  1917. if i.hasattr('ref'):
  1918. content.append(ElementReference(self))
  1919. else:
  1920. content.append(LocalElementDeclaration(self))
  1921. elif component == 'group':
  1922. content.append(ModelGroupReference(self))
  1923. elif component == 'choice':
  1924. content.append(Choice(self))
  1925. elif component == 'sequence':
  1926. content.append(Sequence(self))
  1927. elif component == 'any':
  1928. content.append(ElementWildCard(self))
  1929. else:
  1930. raise SchemaError('Unknown component (%s)' %
  1931. (i.getTagName()))
  1932. content[-1].fromDom(i)
  1933. else:
  1934. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  1935. self.content = tuple(content)
  1936. class All(XMLSchemaComponent,
  1937. AllMarker):
  1938. """<all>
  1939. parents:
  1940. complexType, extension, restriction, group
  1941. attributes:
  1942. id -- ID
  1943. minOccurs -- '0' | '1', 1
  1944. maxOccurs -- '1', 1
  1945. contents:
  1946. annotation?, element*
  1947. """
  1948. attributes = {'id': None,
  1949. 'minOccurs': '1',
  1950. 'maxOccurs': '1'}
  1951. contents = {'xsd': ['annotation', 'element']}
  1952. tag = 'all'
  1953. def __init__(self, parent):
  1954. XMLSchemaComponent.__init__(self, parent)
  1955. self.annotation = None
  1956. self.content = None
  1957. def fromDom(self, node):
  1958. self.setAttributes(node)
  1959. contents = self.getContents(node)
  1960. content = []
  1961. for i in contents:
  1962. component = SplitQName(i.getTagName())[1]
  1963. if component in self.__class__.contents['xsd']:
  1964. if component == 'annotation' and not self.annotation:
  1965. self.annotation = Annotation(self)
  1966. self.annotation.fromDom(i)
  1967. continue
  1968. elif component == 'element':
  1969. if i.hasattr('ref'):
  1970. content.append(ElementReference(self))
  1971. else:
  1972. content.append(LocalElementDeclaration(self))
  1973. else:
  1974. raise SchemaError('Unknown component (%s)' %
  1975. (i.getTagName()))
  1976. content[-1].fromDom(i)
  1977. else:
  1978. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  1979. self.content = tuple(content)
  1980. class Choice(XMLSchemaComponent,
  1981. ChoiceMarker):
  1982. """<choice>
  1983. parents:
  1984. complexType, extension, restriction, group, choice, sequence
  1985. attributes:
  1986. id -- ID
  1987. minOccurs -- Whole Number, 1
  1988. maxOccurs -- (Whole Number | 'unbounded'), 1
  1989. contents:
  1990. annotation?, (element | group | choice | sequence | any)*
  1991. """
  1992. attributes = {'id': None,
  1993. 'minOccurs': '1',
  1994. 'maxOccurs': '1'}
  1995. contents = {'xsd': ['annotation', 'element', 'group', 'choice', 'sequence',
  1996. 'any']}
  1997. tag = 'choice'
  1998. def __init__(self, parent):
  1999. XMLSchemaComponent.__init__(self, parent)
  2000. self.annotation = None
  2001. self.content = None
  2002. def fromDom(self, node):
  2003. self.setAttributes(node)
  2004. contents = self.getContents(node)
  2005. content = []
  2006. for i in contents:
  2007. component = SplitQName(i.getTagName())[1]
  2008. if component in self.__class__.contents['xsd']:
  2009. if component == 'annotation' and not self.annotation:
  2010. self.annotation = Annotation(self)
  2011. self.annotation.fromDom(i)
  2012. continue
  2013. elif component == 'element':
  2014. if i.hasattr('ref'):
  2015. content.append(ElementReference(self))
  2016. else:
  2017. content.append(LocalElementDeclaration(self))
  2018. elif component == 'group':
  2019. content.append(ModelGroupReference(self))
  2020. elif component == 'choice':
  2021. content.append(Choice(self))
  2022. elif component == 'sequence':
  2023. content.append(Sequence(self))
  2024. elif component == 'any':
  2025. content.append(ElementWildCard(self))
  2026. else:
  2027. raise SchemaError('Unknown component (%s)' %
  2028. (i.getTagName()))
  2029. content[-1].fromDom(i)
  2030. else:
  2031. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  2032. self.content = tuple(content)
  2033. class ModelGroupDefinition(XMLSchemaComponent,
  2034. ModelGroupMarker,
  2035. DefinitionMarker):
  2036. """<group name>
  2037. parents:
  2038. redefine, schema
  2039. attributes:
  2040. id -- ID
  2041. name -- NCName, required
  2042. contents:
  2043. annotation?, (all | choice | sequence)?
  2044. """
  2045. required = ['name']
  2046. attributes = {'id': None,
  2047. 'name': None}
  2048. contents = {'xsd': ['annotation', 'all', 'choice', 'sequence']}
  2049. tag = 'group'
  2050. def __init__(self, parent):
  2051. XMLSchemaComponent.__init__(self, parent)
  2052. self.annotation = None
  2053. self.content = None
  2054. def fromDom(self, node):
  2055. self.setAttributes(node)
  2056. contents = self.getContents(node)
  2057. for i in contents:
  2058. component = SplitQName(i.getTagName())[1]
  2059. if component in self.__class__.contents['xsd']:
  2060. if component == 'annotation' and not self.annotation:
  2061. self.annotation = Annotation(self)
  2062. self.annotation.fromDom(i)
  2063. continue
  2064. elif component == 'all' and not self.content:
  2065. self.content = All(self)
  2066. elif component == 'choice' and not self.content:
  2067. self.content = Choice(self)
  2068. elif component == 'sequence' and not self.content:
  2069. self.content = Sequence(self)
  2070. else:
  2071. raise SchemaError('Unknown component (%s)' %
  2072. (i.getTagName()))
  2073. self.content.fromDom(i)
  2074. else:
  2075. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  2076. class ModelGroupReference(XMLSchemaComponent,
  2077. ModelGroupMarker,
  2078. ReferenceMarker):
  2079. """<group ref>
  2080. parents:
  2081. choice, complexType, extension, restriction, sequence
  2082. attributes:
  2083. id -- ID
  2084. ref -- NCName, required
  2085. minOccurs -- Whole Number, 1
  2086. maxOccurs -- (Whole Number | 'unbounded'), 1
  2087. contents:
  2088. annotation?
  2089. """
  2090. required = ['ref']
  2091. attributes = {'id': None,
  2092. 'ref': None,
  2093. 'minOccurs': '1',
  2094. 'maxOccurs': '1'}
  2095. contents = {'xsd': ['annotation']}
  2096. tag = 'group'
  2097. def __init__(self, parent):
  2098. XMLSchemaComponent.__init__(self, parent)
  2099. self.annotation = None
  2100. def getModelGroupReference(self):
  2101. return self.getModelGroup('ref')
  2102. def fromDom(self, node):
  2103. self.setAttributes(node)
  2104. contents = self.getContents(node)
  2105. for i in contents:
  2106. component = SplitQName(i.getTagName())[1]
  2107. if component in self.__class__.contents['xsd']:
  2108. if component == 'annotation' and not self.annotation:
  2109. self.annotation = Annotation(self)
  2110. self.annotation.fromDom(i)
  2111. else:
  2112. raise SchemaError('Unknown component (%s)' %
  2113. (i.getTagName()))
  2114. else:
  2115. raise SchemaError('Unknown component (%s)' % (i.getTagName()))
  2116. class ComplexType(XMLSchemaComponent,
  2117. DefinitionMarker,
  2118. ComplexMarker):
  2119. """<complexType name>
  2120. parents:
  2121. redefine, schema
  2122. attributes:
  2123. id -- ID
  2124. name -- NCName, required
  2125. mixed -- boolean, false
  2126. abstract -- boolean, false
  2127. block -- ('#all' | ('extension' | 'restriction')*), schema.blockDefault
  2128. final -- ('#all' | ('extension' | 'restriction')*), schema.finalDefault
  2129. contents:
  2130. annotation?, (simpleContent | complexContent |
  2131. ((group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?))
  2132. """
  2133. required = ['name']
  2134. attributes = {'id': None,
  2135. 'name': None,
  2136. 'mixed': 0,
  2137. 'abstract': 0,
  2138. 'block': lambda self: self._parent().getBlockDefault(),
  2139. 'final': lambda self: self._parent().getFinalDefault()}
  2140. contents = {'xsd': ['annotation', 'simpleContent', 'complexContent',
  2141. 'group', 'all', 'choice', 'sequence', 'attribute', 'attributeGroup',
  2142. 'anyAttribute', 'any']}
  2143. tag = 'complexType'
  2144. def __init__(self, parent):
  2145. XMLSchemaComponent.__init__(self, parent)
  2146. self.annotation = None
  2147. self.content = None
  2148. self.attr_content = None
  2149. def isMixed(self):
  2150. m = self.getAttribute('mixed')
  2151. if not m:
  2152. return False
  2153. if isinstance(m, string_types):
  2154. if m in ('false', '0'):
  2155. return False
  2156. if m in ('true', '1'):
  2157. return True
  2158. raise SchemaError(
  2159. 'invalid value for attribute mixed(%s): %s' % (m, self.getItemTrace()))
  2160. def getAttributeContent(self):
  2161. return self.attr_content
  2162. def getElementDeclaration(self, attribute):
  2163. raise Warning('invalid operation for <%s>' % self.tag)
  2164. def getTypeDefinition(self, attribute):
  2165. raise Warning('invalid operation for <%s>' % self.tag)
  2166. def fromDom(self, node):
  2167. self.setAttributes(node)
  2168. contents = list(self.getContents(node))
  2169. indx = 0
  2170. num = len(contents)
  2171. if not num:
  2172. return
  2173. component = SplitQName(contents[indx].getTagName())[1]
  2174. if component == 'annotation':
  2175. self.annotation = Annotation(self)
  2176. self.annotation.fromDom(contents[indx])
  2177. indx += 1
  2178. if indx < num:
  2179. component = SplitQName(contents[indx].getTagName())[1]
  2180. self.content = None
  2181. if component == 'simpleContent':
  2182. self.content = self.__class__.SimpleContent(self)
  2183. self.content.fromDom(contents[indx])
  2184. elif component == 'complexContent':
  2185. self.content = self.__class__.ComplexContent(self)
  2186. self.content.fromDom(contents[indx])
  2187. else:
  2188. if component == 'all':
  2189. self.content = All(self)
  2190. elif component == 'choice':
  2191. self.content = Choice(self)
  2192. elif component == 'sequence':
  2193. self.content = Sequence(self)
  2194. elif component == 'group':
  2195. self.content = ModelGroupReference(self)
  2196. if self.content:
  2197. self.content.fromDom(contents[indx])
  2198. indx += 1
  2199. self.attr_content = []
  2200. while indx < num:
  2201. component = SplitQName(contents[indx].getTagName())[1]
  2202. if component == 'attribute':
  2203. if contents[indx].hasattr('ref'):
  2204. self.attr_content.append(AttributeReference(self))
  2205. else:
  2206. self.attr_content.append(
  2207. LocalAttributeDeclaration(self))
  2208. elif component == 'attributeGroup':
  2209. self.attr_content.append(AttributeGroupReference(self))
  2210. elif component == 'anyAttribute':
  2211. self.attr_content.append(AttributeWildCard(self))
  2212. else:
  2213. raise SchemaError('Unknown component (%s): %s' % (
  2214. contents[indx].getTagName(), self.getItemTrace()))
  2215. self.attr_content[-1].fromDom(contents[indx])
  2216. indx += 1
  2217. class _DerivedType(XMLSchemaComponent):
  2218. def __init__(self, parent):
  2219. XMLSchemaComponent.__init__(self, parent)
  2220. self.annotation = None
  2221. # XXX remove attribute derivation, inconsistent
  2222. self.derivation = None
  2223. self.content = None
  2224. def fromDom(self, node):
  2225. self.setAttributes(node)
  2226. contents = self.getContents(node)
  2227. for i in contents:
  2228. component = SplitQName(i.getTagName())[1]
  2229. if component in self.__class__.contents['xsd']:
  2230. if component == 'annotation' and not self.annotation:
  2231. self.annotation = Annotation(self)
  2232. self.annotation.fromDom(i)
  2233. continue
  2234. elif component == 'restriction' and not self.derivation:
  2235. self.derivation = self.__class__.Restriction(self)
  2236. elif component == 'extension' and not self.derivation:
  2237. self.derivation = self.__class__.Extension(self)
  2238. else:
  2239. raise SchemaError(
  2240. 'Unknown component (%s)' % (i.getTagName()))
  2241. else:
  2242. raise SchemaError('Unknown component (%s)' %
  2243. (i.getTagName()))
  2244. self.derivation.fromDom(i)
  2245. self.content = self.derivation
  2246. class ComplexContent(_DerivedType,
  2247. ComplexMarker):
  2248. """<complexContent>
  2249. parents:
  2250. complexType
  2251. attributes:
  2252. id -- ID
  2253. mixed -- boolean, false
  2254. contents:
  2255. annotation?, (restriction | extension)
  2256. """
  2257. attributes = {'id': None,
  2258. 'mixed': 0}
  2259. contents = {'xsd': ['annotation', 'restriction', 'extension']}
  2260. tag = 'complexContent'
  2261. def isMixed(self):
  2262. m = self.getAttribute('mixed')
  2263. if not m:
  2264. return False
  2265. if isinstance(m, string_types) is True:
  2266. if m in ('false', '0'):
  2267. return False
  2268. if m in ('true', '1'):
  2269. return True
  2270. raise SchemaError(
  2271. 'invalid value for attribute mixed(%s): %s' % (m, self.getItemTrace()))
  2272. class _DerivationBase(XMLSchemaComponent):
  2273. """<extension>,<restriction>
  2274. parents:
  2275. complexContent
  2276. attributes:
  2277. id -- ID
  2278. base -- QName, required
  2279. contents:
  2280. annotation?, (group | all | choice | sequence)?,
  2281. (attribute | attributeGroup)*, anyAttribute?
  2282. """
  2283. required = ['base']
  2284. attributes = {'id': None,
  2285. 'base': None}
  2286. contents = {'xsd': ['annotation', 'group', 'all', 'choice',
  2287. 'sequence', 'attribute', 'attributeGroup', 'anyAttribute']}
  2288. def __init__(self, parent):
  2289. XMLSchemaComponent.__init__(self, parent)
  2290. self.annotation = None
  2291. self.content = None
  2292. self.attr_content = None
  2293. def getAttributeContent(self):
  2294. return self.attr_content
  2295. def fromDom(self, node):
  2296. self.setAttributes(node)
  2297. contents = self.getContents(node)
  2298. indx = 0
  2299. num = len(contents)
  2300. # XXX ugly
  2301. if not num:
  2302. return
  2303. component = SplitQName(contents[indx].getTagName())[1]
  2304. if component == 'annotation':
  2305. self.annotation = Annotation(self)
  2306. self.annotation.fromDom(contents[indx])
  2307. indx += 1
  2308. component = SplitQName(contents[indx].getTagName())[1]
  2309. if component == 'all':
  2310. self.content = All(self)
  2311. self.content.fromDom(contents[indx])
  2312. indx += 1
  2313. elif component == 'choice':
  2314. self.content = Choice(self)
  2315. self.content.fromDom(contents[indx])
  2316. indx += 1
  2317. elif component == 'sequence':
  2318. self.content = Sequence(self)
  2319. self.content.fromDom(contents[indx])
  2320. indx += 1
  2321. elif component == 'group':
  2322. self.content = ModelGroupReference(self)
  2323. self.content.fromDom(contents[indx])
  2324. indx += 1
  2325. else:
  2326. self.content = None
  2327. self.attr_content = []
  2328. while indx < num:
  2329. component = SplitQName(contents[indx].getTagName())[1]
  2330. if component == 'attribute':
  2331. if contents[indx].hasattr('ref'):
  2332. self.attr_content.append(AttributeReference(self))
  2333. else:
  2334. self.attr_content.append(
  2335. LocalAttributeDeclaration(self))
  2336. elif component == 'attributeGroup':
  2337. if contents[indx].hasattr('ref'):
  2338. self.attr_content.append(
  2339. AttributeGroupReference(self))
  2340. else:
  2341. self.attr_content.append(
  2342. AttributeGroupDefinition(self))
  2343. elif component == 'anyAttribute':
  2344. self.attr_content.append(AttributeWildCard(self))
  2345. else:
  2346. raise SchemaError('Unknown component (%s)' %
  2347. (contents[indx].getTagName()))
  2348. self.attr_content[-1].fromDom(contents[indx])
  2349. indx += 1
  2350. class Extension(_DerivationBase,
  2351. ExtensionMarker):
  2352. """<extension base>
  2353. parents:
  2354. complexContent
  2355. attributes:
  2356. id -- ID
  2357. base -- QName, required
  2358. contents:
  2359. annotation?, (group | all | choice | sequence)?,
  2360. (attribute | attributeGroup)*, anyAttribute?
  2361. """
  2362. tag = 'extension'
  2363. class Restriction(_DerivationBase,
  2364. RestrictionMarker):
  2365. """<restriction base>
  2366. parents:
  2367. complexContent
  2368. attributes:
  2369. id -- ID
  2370. base -- QName, required
  2371. contents:
  2372. annotation?, (group | all | choice | sequence)?,
  2373. (attribute | attributeGroup)*, anyAttribute?
  2374. """
  2375. tag = 'restriction'
  2376. class SimpleContent(_DerivedType,
  2377. SimpleMarker):
  2378. """<simpleContent>
  2379. parents:
  2380. complexType
  2381. attributes:
  2382. id -- ID
  2383. contents:
  2384. annotation?, (restriction | extension)
  2385. """
  2386. attributes = {'id': None}
  2387. contents = {'xsd': ['annotation', 'restriction', 'extension']}
  2388. tag = 'simpleContent'
  2389. class Extension(XMLSchemaComponent,
  2390. ExtensionMarker):
  2391. """<extension base>
  2392. parents:
  2393. simpleContent
  2394. attributes:
  2395. id -- ID
  2396. base -- QName, required
  2397. contents:
  2398. annotation?, (attribute | attributeGroup)*, anyAttribute?
  2399. """
  2400. required = ['base']
  2401. attributes = {'id': None,
  2402. 'base': None}
  2403. contents = {'xsd': ['annotation', 'attribute', 'attributeGroup',
  2404. 'anyAttribute']}
  2405. tag = 'extension'
  2406. def __init__(self, parent):
  2407. XMLSchemaComponent.__init__(self, parent)
  2408. self.annotation = None
  2409. self.attr_content = None
  2410. def getAttributeContent(self):
  2411. return self.attr_content
  2412. def fromDom(self, node):
  2413. self.setAttributes(node)
  2414. contents = self.getContents(node)
  2415. indx = 0
  2416. num = len(contents)
  2417. if num:
  2418. component = SplitQName(contents[indx].getTagName())[1]
  2419. if component == 'annotation':
  2420. self.annotation = Annotation(self)
  2421. self.annotation.fromDom(contents[indx])
  2422. indx += 1
  2423. component = SplitQName(contents[indx].getTagName())[1]
  2424. content = []
  2425. while indx < num:
  2426. component = SplitQName(contents[indx].getTagName())[1]
  2427. if component == 'attribute':
  2428. if contents[indx].hasattr('ref'):
  2429. content.append(AttributeReference(self))
  2430. else:
  2431. content.append(LocalAttributeDeclaration(self))
  2432. elif component == 'attributeGroup':
  2433. content.append(AttributeGroupReference(self))
  2434. elif component == 'anyAttribute':
  2435. content.append(AttributeWildCard(self))
  2436. else:
  2437. raise SchemaError('Unknown component (%s)' %
  2438. (contents[indx].getTagName()))
  2439. content[-1].fromDom(contents[indx])
  2440. indx += 1
  2441. self.attr_content = tuple(content)
  2442. class Restriction(XMLSchemaComponent,
  2443. RestrictionMarker):
  2444. """<restriction base>
  2445. parents:
  2446. simpleContent
  2447. attributes:
  2448. id -- ID
  2449. base -- QName, required
  2450. contents:
  2451. annotation?, simpleType?, (enumeration | length |
  2452. maxExclusive | maxInclusive | maxLength | minExclusive |
  2453. minInclusive | minLength | pattern | fractionDigits |
  2454. totalDigits | whiteSpace)*, (attribute | attributeGroup)*,
  2455. anyAttribute?
  2456. """
  2457. required = ['base']
  2458. attributes = {'id': None,
  2459. 'base': None}
  2460. contents = {'xsd': ['annotation', 'simpleType', 'attribute',
  2461. 'attributeGroup', 'anyAttribute'] + RestrictionMarker.facets}
  2462. tag = 'restriction'
  2463. def __init__(self, parent):
  2464. XMLSchemaComponent.__init__(self, parent)
  2465. self.annotation = None
  2466. self.content = None
  2467. self.attr_content = None
  2468. def getAttributeContent(self):
  2469. return self.attr_content
  2470. def fromDom(self, node):
  2471. self.content = []
  2472. self.setAttributes(node)
  2473. contents = self.getContents(node)
  2474. indx = 0
  2475. num = len(contents)
  2476. component = SplitQName(contents[indx].getTagName())[1]
  2477. if component == 'annotation':
  2478. self.annotation = Annotation(self)
  2479. self.annotation.fromDom(contents[indx])
  2480. indx += 1
  2481. component = SplitQName(contents[indx].getTagName())[1]
  2482. content = []
  2483. while indx < num:
  2484. component = SplitQName(contents[indx].getTagName())[1]
  2485. if component == 'attribute':
  2486. if contents[indx].hasattr('ref'):
  2487. content.append(AttributeReference(self))
  2488. else:
  2489. content.append(LocalAttributeDeclaration(self))
  2490. elif component == 'attributeGroup':
  2491. content.append(AttributeGroupReference(self))
  2492. elif component == 'anyAttribute':
  2493. content.append(AttributeWildCard(self))
  2494. elif component == 'simpleType':
  2495. self.content.append(AnonymousSimpleType(self))
  2496. self.content[-1].fromDom(contents[indx])
  2497. else:
  2498. raise SchemaError('Unknown component (%s)' %
  2499. (contents[indx].getTagName()))
  2500. content[-1].fromDom(contents[indx])
  2501. indx += 1
  2502. self.attr_content = tuple(content)
  2503. class LocalComplexType(ComplexType,
  2504. LocalMarker):
  2505. """<complexType>
  2506. parents:
  2507. element
  2508. attributes:
  2509. id -- ID
  2510. mixed -- boolean, false
  2511. contents:
  2512. annotation?, (simpleContent | complexContent |
  2513. ((group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?))
  2514. """
  2515. required = []
  2516. attributes = {'id': None,
  2517. 'mixed': 0}
  2518. tag = 'complexType'
  2519. class SimpleType(XMLSchemaComponent,
  2520. DefinitionMarker,
  2521. SimpleMarker):
  2522. """<simpleType name>
  2523. parents:
  2524. redefine, schema
  2525. attributes:
  2526. id -- ID
  2527. name -- NCName, required
  2528. final -- ('#all' | ('extension' | 'restriction' | 'list' | 'union')*),
  2529. schema.finalDefault
  2530. contents:
  2531. annotation?, (restriction | list | union)
  2532. """
  2533. required = ['name']
  2534. attributes = {'id': None,
  2535. 'name': None,
  2536. 'final': lambda self: self._parent().getFinalDefault()}
  2537. contents = {'xsd': ['annotation', 'restriction', 'list', 'union']}
  2538. tag = 'simpleType'
  2539. def __init__(self, parent):
  2540. XMLSchemaComponent.__init__(self, parent)
  2541. self.annotation = None
  2542. self.content = None
  2543. def getElementDeclaration(self, attribute):
  2544. raise Warning('invalid operation for <%s>' % self.tag)
  2545. def getTypeDefinition(self, attribute):
  2546. raise Warning('invalid operation for <%s>' % self.tag)
  2547. def fromDom(self, node):
  2548. self.setAttributes(node)
  2549. contents = self.getContents(node)
  2550. for child in contents:
  2551. component = SplitQName(child.getTagName())[1]
  2552. if component == 'annotation':
  2553. self.annotation = Annotation(self)
  2554. self.annotation.fromDom(child)
  2555. continue
  2556. break
  2557. else:
  2558. return
  2559. if component == 'restriction':
  2560. self.content = self.__class__.Restriction(self)
  2561. elif component == 'list':
  2562. self.content = self.__class__.List(self)
  2563. elif component == 'union':
  2564. self.content = self.__class__.Union(self)
  2565. else:
  2566. raise SchemaError('Unknown component (%s)' % (component))
  2567. self.content.fromDom(child)
  2568. class Restriction(XMLSchemaComponent,
  2569. RestrictionMarker):
  2570. """<restriction base>
  2571. parents:
  2572. simpleType
  2573. attributes:
  2574. id -- ID
  2575. base -- QName, required or simpleType child
  2576. contents:
  2577. annotation?, simpleType?, (enumeration | length |
  2578. maxExclusive | maxInclusive | maxLength | minExclusive |
  2579. minInclusive | minLength | pattern | fractionDigits |
  2580. totalDigits | whiteSpace)*
  2581. """
  2582. attributes = {'id': None,
  2583. 'base': None}
  2584. contents = {'xsd': ['annotation', 'simpleType'] +
  2585. RestrictionMarker.facets}
  2586. tag = 'restriction'
  2587. def __init__(self, parent):
  2588. XMLSchemaComponent.__init__(self, parent)
  2589. self.annotation = None
  2590. self.content = None
  2591. self.facets = None
  2592. def getAttributeBase(self):
  2593. return XMLSchemaComponent.getAttribute(self, 'base')
  2594. def getTypeDefinition(self, attribute='base'):
  2595. return XMLSchemaComponent.getTypeDefinition(self, attribute)
  2596. def getSimpleTypeContent(self):
  2597. for el in self.content:
  2598. if el.isSimple():
  2599. return el
  2600. return None
  2601. def fromDom(self, node):
  2602. self.facets = []
  2603. self.setAttributes(node)
  2604. contents = self.getContents(node)
  2605. content = []
  2606. for indx in range(len(contents)):
  2607. component = SplitQName(contents[indx].getTagName())[1]
  2608. if (component == 'annotation') and (not indx):
  2609. self.annotation = Annotation(self)
  2610. self.annotation.fromDom(contents[indx])
  2611. continue
  2612. elif (component == 'simpleType') and (not indx or indx == 1):
  2613. content.append(AnonymousSimpleType(self))
  2614. content[-1].fromDom(contents[indx])
  2615. elif component in RestrictionMarker.facets:
  2616. self.facets.append(contents[indx])
  2617. else:
  2618. raise SchemaError('Unknown component (%s)' %
  2619. (contents[indx].getTagName()))
  2620. self.content = tuple(content)
  2621. class Union(XMLSchemaComponent,
  2622. UnionMarker):
  2623. """<union>
  2624. parents:
  2625. simpleType
  2626. attributes:
  2627. id -- ID
  2628. memberTypes -- list of QNames, required or simpleType child.
  2629. contents:
  2630. annotation?, simpleType*
  2631. """
  2632. attributes = {'id': None,
  2633. 'memberTypes': None}
  2634. contents = {'xsd': ['annotation', 'simpleType']}
  2635. tag = 'union'
  2636. def __init__(self, parent):
  2637. XMLSchemaComponent.__init__(self, parent)
  2638. self.annotation = None
  2639. self.content = None
  2640. def fromDom(self, node):
  2641. self.setAttributes(node)
  2642. contents = self.getContents(node)
  2643. content = []
  2644. for indx in range(len(contents)):
  2645. component = SplitQName(contents[indx].getTagName())[1]
  2646. if (component == 'annotation') and (not indx):
  2647. self.annotation = Annotation(self)
  2648. self.annotation.fromDom(contents[indx])
  2649. elif (component == 'simpleType'):
  2650. content.append(AnonymousSimpleType(self))
  2651. content[-1].fromDom(contents[indx])
  2652. else:
  2653. raise SchemaError('Unknown component (%s)' %
  2654. (contents[indx].getTagName()))
  2655. self.content = tuple(content)
  2656. class List(XMLSchemaComponent,
  2657. ListMarker):
  2658. """<list>
  2659. parents:
  2660. simpleType
  2661. attributes:
  2662. id -- ID
  2663. itemType -- QName, required or simpleType child.
  2664. contents:
  2665. annotation?, simpleType?
  2666. """
  2667. attributes = {'id': None,
  2668. 'itemType': None}
  2669. contents = {'xsd': ['annotation', 'simpleType']}
  2670. tag = 'list'
  2671. def __init__(self, parent):
  2672. XMLSchemaComponent.__init__(self, parent)
  2673. self.annotation = None
  2674. self.content = None
  2675. def getItemType(self):
  2676. return self.attributes.get('itemType')
  2677. def getTypeDefinition(self, attribute='itemType'):
  2678. """
  2679. return the type refered to by itemType attribute or
  2680. the simpleType content. If returns None, then the
  2681. type refered to by itemType is primitive.
  2682. """
  2683. tp = XMLSchemaComponent.getTypeDefinition(self, attribute)
  2684. return tp or self.content
  2685. def fromDom(self, node):
  2686. self.annotation = None
  2687. self.content = None
  2688. self.setAttributes(node)
  2689. contents = self.getContents(node)
  2690. for indx in range(len(contents)):
  2691. component = SplitQName(contents[indx].getTagName())[1]
  2692. if (component == 'annotation') and (not indx):
  2693. self.annotation = Annotation(self)
  2694. self.annotation.fromDom(contents[indx])
  2695. elif (component == 'simpleType'):
  2696. self.content = AnonymousSimpleType(self)
  2697. self.content.fromDom(contents[indx])
  2698. break
  2699. else:
  2700. raise SchemaError('Unknown component (%s)' %
  2701. (contents[indx].getTagName()))
  2702. class AnonymousSimpleType(SimpleType,
  2703. SimpleMarker,
  2704. LocalMarker):
  2705. """<simpleType>
  2706. parents:
  2707. attribute, element, list, restriction, union
  2708. attributes:
  2709. id -- ID
  2710. contents:
  2711. annotation?, (restriction | list | union)
  2712. """
  2713. required = []
  2714. attributes = {'id': None}
  2715. tag = 'simpleType'
  2716. class Redefine:
  2717. """<redefine>
  2718. parents:
  2719. attributes:
  2720. contents:
  2721. """
  2722. tag = 'redefine'
  2723. ###########################
  2724. ###########################
  2725. if sys.version_info[:2] >= (2, 2):
  2726. tupleClass = tuple
  2727. else:
  2728. from . import UserTuple
  2729. tupleClass = UserTuple.UserTuple
  2730. class TypeDescriptionComponent(tupleClass):
  2731. """Tuple of length 2, consisting of
  2732. a namespace and unprefixed name.
  2733. """
  2734. def __new__(typ, args):
  2735. """args -- (namespace, name)
  2736. Remove the name's prefix, irrelevant.
  2737. """
  2738. if len(args) != 2:
  2739. raise TypeError('expecting tuple (namespace, name), got %s' % args)
  2740. elif args[1].find(':') >= 0:
  2741. args = (args[0], SplitQName(args[1])[1])
  2742. return tuple.__new__(typ, args)
  2743. def getTargetNamespace(self):
  2744. return self[0]
  2745. def getName(self):
  2746. return self[1]