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.
 
 
 

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