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.
 
 
 

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