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