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