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

2890 lines
99 KiB

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