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.
 
 
 

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