Browse Source

----------------------------------------------------------------------

Modified Files:

        Utility.py -- added a CollectionNS class that keys items via
            (targetNamespace, name).

        WSDLTools.py --

            Made WSDL Collections into CollectionNS instances,
            this fixes problem with collisions, caused by wsdl:imports,
            between items with same name but defined in different
            targetNamespaces.  So now all items can be accessed via
            (namespace,name), but ONLY those items defined in
            WSDL.targetNamepsace (not an import.targetNamespace) can
            be accessed using just 'name'.

            Also changed how portType is "loaded".  Now instead of
            dropping all the operation nodes in "load", I drop
            the portType node into "load".  This makes sense because
            portType really should know about itself, and the
            XML Schema definition of "portType" includes an "anyAttribute"
            and I need to make this stuff available.  I may change the
            other WSDL information items to do this to be consistent.

 ----------------------------------------------------------------------
main
Joshua Boverhof 21 years ago
parent
commit
b3575379e4
2 changed files with 111 additions and 17 deletions
  1. +52
    -0
      Utility.py
  2. +59
    -17
      WSDLTools.py

+ 52
- 0
Utility.py View File

@@ -9,6 +9,7 @@

ident = "$Id$"

import types
from string import join, strip, split
from UserDict import UserDict
from StringIO import StringIO
@@ -421,6 +422,14 @@ class DOM:
return default
return ''

def getAttrs(self, node):
"""Return a Collection of all attributes
"""
attrs = {}
for k,v in node._attrs.items():
attrs[k] = v.value
return attrs

def getElementText(self, node, preserve_ws=None):
"""Return the text value of an xml element node. Leading and trailing
whitespace is stripped from the value unless the preserve_ws flag
@@ -584,6 +593,49 @@ class Collection(UserDict):
return self.list


class CollectionNS(UserDict):
"""Helper class for maintaining ordered named collections."""
default = lambda self,k: k.name
def __init__(self, parent, key=None):
UserDict.__init__(self)
self.parent = weakref.ref(parent)
self.targetNamespace = None
self.list = []
self._func = key or self.default

def __getitem__(self, key):
self.targetNamespace = self.parent().targetNamespace
if type(key) is types.IntType:
return self.list[key]
elif self.__isSequence(key):
nsuri,name = key
return self.data[nsuri][name]
return self.data[self.parent().targetNamespace][key]

def __setitem__(self, key, item):
item.parent = weakref.ref(self)
self.list.append(item)
targetNamespace = getattr(item, 'targetNamespace', self.parent().targetNamespace)
if not self.data.has_key(targetNamespace):
self.data[targetNamespace] = {}
self.data[targetNamespace][key] = item

def __isSequence(self, key):
return (type(key) in (types.TupleType,types.ListType) and len(key) == 2)

def keys(self):
keys = []
for tns in self.data.keys():
keys.append(map(lambda i: (tns,self._func(i)), self.data[tns].values()))
return keys

def items(self):
return map(lambda i: (self._func(i), i), self.list)

def values(self):
return self.list



# This is a runtime guerilla patch for pulldom (used by minidom) so
# that xml namespace declaration attributes are not lost in parsing.


+ 59
- 17
WSDLTools.py View File

@@ -9,7 +9,7 @@

ident = "$Id$"

from Utility import DOM, Collection
from Utility import DOM, Collection, CollectionNS
from XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter
from StringIO import StringIO
import urllib
@@ -64,10 +64,10 @@ class WSDL:
self.location = None
self.document = None
self.name = None
self.services = Collection(self)
self.messages = Collection(self)
self.portTypes = Collection(self)
self.bindings = Collection(self)
self.services = CollectionNS(self)
self.messages = CollectionNS(self)
self.portTypes = CollectionNS(self)
self.bindings = CollectionNS(self)
self.imports = Collection(self)
self.types = Types(self)
self.extensions = []
@@ -80,39 +80,47 @@ class WSDL:

version = '1.1'

def addService(self, name, documentation=''):
def addService(self, name, documentation='', targetNamespace=None):
if self.services.has_key(name):
raise WSDLError(
'Duplicate service element: %s' % name
)
item = Service(name, documentation)
if targetNamespace:
item.targetNamespace = targetNamespace
self.services[name] = item
return item

def addMessage(self, name, documentation=''):
def addMessage(self, name, documentation='', targetNamespace=None):
if self.messages.has_key(name):
raise WSDLError(
'Duplicate message element: %s.' % name
)
item = Message(name, documentation)
if targetNamespace:
item.targetNamespace = targetNamespace
self.messages[name] = item
return item

def addPortType(self, name, documentation=''):
def addPortType(self, name, documentation='', targetNamespace=None):
if self.portTypes.has_key(name):
raise WSDLError(
'Duplicate portType element: name'
)
item = PortType(name, documentation)
if targetNamespace:
item.targetNamespace = targetNamespace
self.portTypes[name] = item
return item

def addBinding(self, name, type, documentation=''):
def addBinding(self, name, type, documentation='', targetNamespace=None):
if self.bindings.has_key(name):
raise WSDLError(
'Duplicate binding element: %s' % name
)
item = Binding(name, type, documentation)
if targetNamespace:
item.targetNamespace = targetNamespace
self.bindings[name] = item
return item

@@ -158,6 +166,7 @@ class WSDL:

reader = SchemaReader(base_url=self.location)
for element in DOM.getElements(definitions, None, None):
targetNamespace = DOM.getAttr(element, 'targetNamespace')
localName = element.localName

if not DOM.nsUriMatch(element.namespaceURI, NS_WSDL):
@@ -172,7 +181,7 @@ class WSDL:
elif localName == 'message':
name = DOM.getAttr(element, 'name')
docs = GetDocumentation(element)
message = self.addMessage(name, docs)
message = self.addMessage(name, docs, targetNamespace)
parts = DOM.getElements(element, 'part', NS_WSDL)
message.load(parts)
continue
@@ -180,9 +189,10 @@ class WSDL:
elif localName == 'portType':
name = DOM.getAttr(element, 'name')
docs = GetDocumentation(element)
ptype = self.addPortType(name, docs)
operations = DOM.getElements(element, 'operation', NS_WSDL)
ptype.load(operations)
ptype = self.addPortType(name, docs, targetNamespace)
#operations = DOM.getElements(element, 'operation', NS_WSDL)
#ptype.load(operations)
ptype.load(element)
continue

elif localName == 'binding':
@@ -194,7 +204,7 @@ class WSDL:
)
type = type.split(':', 1)[-1]
docs = GetDocumentation(element)
binding = self.addBinding(name, type, docs)
binding = self.addBinding(name, type, docs, targetNamespace)
operations = DOM.getElements(element, 'operation', NS_WSDL)
binding.load(operations)
binding.load_ex(GetExtensions(element))
@@ -203,7 +213,7 @@ class WSDL:
elif localName == 'service':
name = DOM.getAttr(element, 'name')
docs = GetDocumentation(element)
service = self.addService(name, docs)
service = self.addService(name, docs, targetNamespace)
ports = DOM.getElements(element, 'port', NS_WSDL)
service.load(ports)
service.load_ex(GetExtensions(element))
@@ -350,11 +360,37 @@ class MessagePart(Element):
self.element = None
self.type = None

def getWSDL(self):
"""Return the WSDL object that contains this Message Part."""
return self.parent().parent().parent().parent()

def getTypeDefinition(self):
wsdl = self.getWSDL()
nsuri,name = self.type
schema = wsdl.types.get(nsuri, {})
return schema.get(name)

def getElementDeclaration(self):
wsdl = self.getWSDL()
nsuri,name = self.element
schema = wsdl.types.get(nsuri, {})
return schema.get(name)


class PortType(Element):
'''PortType has a anyAttribute, thus must provide for an extensible
mechanism for supporting such attributes.

Instance Data:
operations --
attributes --

'''

def __init__(self, name, documentation=''):
Element.__init__(self, name, documentation)
self.operations = Collection(self)
self.attributes = {}

def getWSDL(self):
return self.parent().parent()
@@ -364,7 +400,13 @@ class PortType(Element):
self.operations[name] = item
return item

def load(self, elements):
def load(self, element):
self.name = DOM.getAttr(element, 'name')
self.documentation = GetDocumentation(element)
self.attributes.update(DOM.getAttrs(element))

NS_WSDL = DOM.GetWSDLUri(self.getWSDL().version)
elements = DOM.getElements(element, 'operation', NS_WSDL)
for element in elements:
name = DOM.getAttr(element, 'name')
docs = GetDocumentation(element)
@@ -424,7 +466,7 @@ class Operation(Element):
wsdl = self.getPortType().getWSDL()
return wsdl.messages[self.faults[name].message]

def addFault(self, name, message, documentation=''):
def addFault(self, message, name, documentation=''):
if self.faults.has_key(name):
raise WSDLError(
'Duplicate fault element: %s' % name


Loading…
Cancel
Save