Browse Source

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

Modified Files:
        ** removed all "imports" of ZSI or ZSI.wstools, so wstools
        can be used independently by SOAPpy.

 	Namespaces.py
        -- added a namespace

        Utility.py
        -- moved ZSI.utility here, and the "Base" class for logging.

        WSDLTools.py
        -- added a "toDom" and "GetWSDL" methods to several classes,
        so now you can construct a WSDL instance and then call
        WSDL.toDom() --> DOM --> and create a WSDL file.

        __init__.py
        -- removed "Base" class for logging.

 Added Files:
 	c14n.py
        -- moved the c14n stuff from ZSI.compat here.

 ----------------------------------------------------------------------
main
Joshua Boverhof 20 years ago
parent
commit
07d07f3cff
5 changed files with 1255 additions and 16 deletions
  1. +3
    -0
      Namespaces.py
  2. +492
    -6
      Utility.py
  3. +254
    -6
      WSDLTools.py
  4. +1
    -4
      __init__.py
  5. +505
    -0
      c14n.py

+ 3
- 0
Namespaces.py View File

@@ -75,6 +75,7 @@ class OASIS:
WSSE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" WSSE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
UTILITY = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" UTILITY = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
LIFETIME = "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd" LIFETIME = "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd"
PROPERTIES = "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"


class WSSE: class WSSE:
BASE = "http://schemas.xmlsoap.org/ws/2002/04/secext" BASE = "http://schemas.xmlsoap.org/ws/2002/04/secext"
@@ -109,3 +110,5 @@ class GLOBUS:
SECCONV = "http://wsrf.globus.org/core/2004/07/security/secconv" SECCONV = "http://wsrf.globus.org/core/2004/07/security/secconv"
CORE = "http://www.globus.org/namespaces/2004/06/core" CORE = "http://www.globus.org/namespaces/2004/06/core"
SIG = "http://www.globus.org/2002/04/xmlenc#gssapi-sign" SIG = "http://www.globus.org/2002/04/xmlenc#gssapi-sign"

ZSI_SCHEMA_URI = 'http://www.zolera.com/schemas/ZSI/'

+ 492
- 6
Utility.py View File

@@ -11,15 +11,22 @@ ident = "$Id$"


import types import types
import string, httplib, smtplib, urllib, socket, weakref import string, httplib, smtplib, urllib, socket, weakref
import xml.dom.minidom
from string import join, strip, split from string import join, strip, split
from UserDict import UserDict from UserDict import UserDict
from StringIO import StringIO
from cStringIO import StringIO
from TimeoutSocket import TimeoutSocket, TimeoutError from TimeoutSocket import TimeoutSocket, TimeoutError
from urlparse import urlparse from urlparse import urlparse
from httplib import HTTPConnection, HTTPSConnection from httplib import HTTPConnection, HTTPSConnection
from exceptions import Exception from exceptions import Exception


import xml.dom.minidom
from xml.dom import Node

import logging
from c14n import Canonicalize
from Namespaces import SCHEMA, SOAP, XMLNS, ZSI_SCHEMA_URI


try: try:
from xml.dom.ext import SplitQName from xml.dom.ext import SplitQName
except: except:
@@ -46,13 +53,29 @@ except:
return return
return tuple(l) return tuple(l)



class NamespaceError(Exception):
"""Used to indicate a Namespace Error."""


class RecursionError(Exception): class RecursionError(Exception):
"""Used to indicate a HTTP redirect recursion.""" """Used to indicate a HTTP redirect recursion."""
pass


class ParseError(Exception): class ParseError(Exception):
"""Used to indicate a XML parsing error.""" """Used to indicate a XML parsing error."""



class DOMException(Exception):
"""Used to indicate a problem processing DOM."""


class Base:
"""Base class for instance level Logging"""
def __init__(self, module=__name__):
self.logger = logging.getLogger('%s-%s(%x)' %(module, self.__class__, id(self)))


class HTTPResponse: class HTTPResponse:
"""Captures the information in an HTTP response message.""" """Captures the information in an HTTP response message."""


@@ -586,11 +609,473 @@ class DOM:
file.close() file.close()
return result return result


DOM = DOM()


class DOMException(Exception):
pass


DOM = DOM()
class MessageInterface:
'''Higher Level Interface, delegates to DOM singleton, must
be subclassed and implement all methods that throw NotImplementedError.
'''
def __init__(self, sw):
'''Constructor, May be extended, do not override.
sw -- soapWriter instance
'''
self.sw = sw

def getSoapWriter(self, sw):
return self._sw()
def setSoapWriter(self, sw):
self._sw = weakref.ref(sw)
sw = property(getSoapWriter, setSoapWriter, None, "soap writer instance.")

def AddCallback(self, func, *arglist):
self.sw.AddCallback(func, *arglist)

def Known(self, obj):
return self.sw.Known(obj)

def Forget(self, obj):
return self.sw.Forget(obj)

def canonicalize(self):
'''canonicalize the underlying DOM, and return as string.
'''
raise NotImplementedError, ''

def createDocument(self, namespaceURI=SOAP.ENV, localName='Envelope'):
'''create Document
'''
raise NotImplementedError, ''

def createAppendElement(self, namespaceURI, localName):
'''create and append element(namespaceURI,localName), and return
the node.
'''
raise NotImplementedError, ''

def findNamespaceURI(self, qualifiedName):
raise NotImplementedError, ''

def resolvePrefix(self, prefix):
raise NotImplementedError, ''

def setAttributeNS(self, namespaceURI, localName, value):
'''set attribute (namespaceURI, localName)=value
'''
raise NotImplementedError, ''

def setAttributeType(self, namespaceURI, localName):
'''set attribute xsi:type=(namespaceURI, localName)
'''
raise NotImplementedError, ''

def setNamespaceAttribute(self, namespaceURI, prefix):
'''set namespace attribute xmlns:prefix=namespaceURI
'''
raise NotImplementedError, ''


class ElementProxy(Base, MessageInterface):
'''
'''
_soap_env_prefix = 'SOAP-ENV'
_soap_enc_prefix = 'SOAP-ENC'
_zsi_prefix = 'ZSI'
_xsd_prefix = 'xsd'
_xsi_prefix = 'xsi'
_xml_prefix = 'xml'
_xmlns_prefix = 'xmlns'

_soap_env_nsuri = SOAP.ENV
_soap_enc_nsuri = SOAP.ENC
_zsi_nsuri = ZSI_SCHEMA_URI
_xsd_nsuri = SCHEMA.XSD3
_xsi_nsuri = SCHEMA.XSI3
_xml_nsuri = XMLNS.XML
_xmlns_nsuri = XMLNS.BASE

standard_ns = {\
_xml_prefix:_xml_nsuri,
_xmlns_prefix:_xmlns_nsuri
}
reserved_ns = {\
_soap_env_prefix:_soap_env_nsuri,
_soap_enc_prefix:_soap_enc_nsuri,
_zsi_prefix:_zsi_nsuri,
_xsd_prefix:_xsd_nsuri,
_xsi_prefix:_xsi_nsuri,
}
name = None
namespaceURI = None

def __init__(self, sw, message=None):
'''Initialize.
sw -- SoapWriter
'''
self._indx = 0
MessageInterface.__init__(self, sw)
Base.__init__(self)
self._dom = DOM
self.node = None
if type(message) in (types.StringType,types.UnicodeType):
self.loadFromString(message)
elif isinstance(message, ElementProxy):
self.node = message._getNode()
else:
self.node = message
self.processorNss = self.standard_ns.copy()
self.processorNss.update(self.reserved_ns)

def __str__(self):
return self.toString()

def evaluate(self, expression, processorNss=None):
'''expression -- XPath compiled expression
'''
from Ft.Xml import XPath
if not processorNss:
context = XPath.Context.Context(self.node, processorNss=self.processorNss)
else:
context = XPath.Context.Context(self.node, processorNss=processorNss)
nodes = expression.evaluate(context)
return map(lambda node: ElementProxy(self.sw,node), nodes)

#############################################
# Methods for checking/setting the
# classes (namespaceURI,name) node.
#############################################
def checkNode(self, namespaceURI=None, localName=None):
'''
namespaceURI -- namespace of element
localName -- local name of element
'''
namespaceURI = namespaceURI or self.namespaceURI
localName = localName or self.name
check = False
if localName and self.node:
check = self._dom.isElement(self.node, localName, namespaceURI)
if not check:
raise NamespaceError, 'unexpected node type %s, expecting %s' %(self.node, localName)

def setNode(self, node=None):
if node:
if isinstance(node, ElementProxy):
self.node = node._getNode()
else:
self.node = node
elif self.node:
node = self._dom.getElement(self.node, self.name, self.namespaceURI, default=None)
if not node:
raise NamespaceError, 'cant find element (%s,%s)' %(self.namespaceURI,self.name)
self.node = node
else:
#self.node = self._dom.create(self.node, self.name, self.namespaceURI, default=None)
self.createDocument(self.namespaceURI, localName=self.name, doctype=None)
self.checkNode()

#############################################
# Wrapper Methods for direct DOM Element Node access
#############################################
def _getNode(self):
return self.node

def _getElements(self):
return self._dom.getElements(self.node, name=None)

def _getOwnerDocument(self):
return self.node.ownerDocument or self.node

def _getUniquePrefix(self):
'''I guess we need to resolve all potential prefixes
because when the current node is attached it copies the
namespaces into the parent node.
'''
while 1:
self._indx += 1
prefix = 'ns%d' %self._indx
try:
self._dom.findNamespaceURI(prefix, self._getNode())
except DOMException, ex:
break
return prefix

def _getPrefix(self, node, nsuri):
'''
Keyword arguments:
node -- DOM Element Node
nsuri -- namespace of attribute value
'''
try:
if node and (node.nodeType == node.ELEMENT_NODE) and \
(nsuri == self._dom.findDefaultNS(node)):
return None
except DOMException, ex:
pass
if nsuri == XMLNS.XML:
return self._xml_prefix
if node.nodeType == Node.ELEMENT_NODE:
for attr in node.attributes.values():
if attr.namespaceURI == XMLNS.BASE \
and nsuri == attr.value:
return attr.localName
else:
if node.parentNode:
return self._getPrefix(node.parentNode, nsuri)
raise NamespaceError, 'namespaceURI "%s" is not defined' %nsuri

def _appendChild(self, node):
'''
Keyword arguments:
node -- DOM Element Node
'''
if node is None:
raise TypeError, 'node is None'
self.node.appendChild(node)

def _insertBefore(self, newChild, refChild):
'''
Keyword arguments:
child -- DOM Element Node to insert
refChild -- DOM Element Node
'''
self.node.insertBefore(newChild, refChild)

def _setAttributeNS(self, namespaceURI, qualifiedName, value):
'''
Keyword arguments:
namespaceURI -- namespace of attribute
qualifiedName -- qualified name of new attribute value
value -- value of attribute
'''
self.node.setAttributeNS(namespaceURI, qualifiedName, value)

#############################################
#General Methods
#############################################
def isFault(self):
'''check to see if this is a soap:fault message.
'''
return False

def getPrefix(self, namespaceURI):
try:
prefix = self._getPrefix(node=self.node, nsuri=namespaceURI)
except NamespaceError, ex:
prefix = self._getUniquePrefix()
self.setNamespaceAttribute(prefix, namespaceURI)
return prefix

def getDocument(self):
return self._getOwnerDocument()

def setDocument(self, document):
self.node = document

def importFromString(self, xmlString):
doc = self._dom.loadDocument(StringIO(xmlString))
node = self._dom.getElement(doc, name=None)
clone = self.importNode(node)
self._appendChild(clone)

def importNode(self, node):
if isinstance(node, ElementProxy):
node = node._getNode()
return self._dom.importNode(self._getOwnerDocument(), node, deep=1)

def loadFromString(self, data):
self.node = self._dom.loadDocument(StringIO(data))

def canonicalize(self):
return Canonicalize(self.node)

def toString(self):
return self.canonicalize()

def createDocument(self, namespaceURI, localName, doctype=None):
prefix = self._soap_env_prefix
if namespaceURI != self.reserved_ns[prefix]:
raise KeyError, 'only support creation of document in %s' %self.reserved_ns[prefix]
qualifiedName = '%s:%s' %(prefix,localName)

document = self._dom.createDocument(nsuri=namespaceURI, qname=qualifiedName, doctype=doctype)
self.node = document.childNodes[0]

#set up reserved namespace attributes
for prefix,nsuri in self.reserved_ns.items():
self._setAttributeNS(namespaceURI=self._xmlns_nsuri,
qualifiedName='%s:%s' %(self._xmlns_prefix,prefix),
value=nsuri)

#############################################
#Methods for attributes
#############################################
def hasAttribute(self, namespaceURI, localName):
return self._dom.hasAttr(self._getNode(), name=localName, nsuri=namespaceURI)

def setAttributeType(self, namespaceURI, localName):
'''set xsi:type
Keyword arguments:
namespaceURI -- namespace of attribute value
localName -- name of new attribute value

'''
self.logger.debug('setAttributeType: (%s,%s)', namespaceURI, localName)
value = localName
if namespaceURI:
value = '%s:%s' %(self.getPrefix(namespaceURI),localName)
self._setAttributeNS(self._xsi_nsuri, '%s:type' %self._xsi_prefix, value)

def createAttributeNS(self, namespace, name, value):
document = self._getOwnerDocument()
attrNode = document.createAttributeNS(namespace, name, value)

def setAttributeNS(self, namespaceURI, localName, value):
'''
Keyword arguments:
namespaceURI -- namespace of attribute to create, None is for
attributes in no namespace.
localName -- local name of new attribute
value -- value of new attribute
'''
prefix = None
if namespaceURI:
try:
prefix = self.getPrefix(namespaceURI)
except KeyError, ex:
prefix = 'ns2'
self.setNamespaceAttribute(prefix, namespaceURI)
qualifiedName = localName
if prefix:
qualifiedName = '%s:%s' %(prefix, localName)
self._setAttributeNS(namespaceURI, qualifiedName, value)

def setNamespaceAttribute(self, prefix, namespaceURI):
'''
Keyword arguments:
prefix -- xmlns prefix
namespaceURI -- value of prefix
'''
self._setAttributeNS(XMLNS.BASE, 'xmlns:%s' %prefix, namespaceURI)

#############################################
#Methods for elements
#############################################
def createElementNS(self, namespace, qname):
'''
Keyword arguments:
namespace -- namespace of element to create
qname -- qualified name of new element
'''
document = self._getOwnerDocument()
node = document.createElementNS(namespace, qname)
return ElementProxy(self.sw, node)

def createAppendSetElement(self, namespaceURI, localName, prefix=None):
'''Create a new element (namespaceURI,name), append it
to current node, then set it to be the current node.
Keyword arguments:
namespaceURI -- namespace of element to create
localName -- local name of new element
prefix -- if namespaceURI is not defined, declare prefix. defaults
to 'ns1' if left unspecified.
'''
node = self.createAppendElement(namespaceURI, localName, prefix=None)
node=node._getNode()
self._setNode(node._getNode())

def createAppendElement(self, namespaceURI, localName, prefix=None):
'''Create a new element (namespaceURI,name), append it
to current node, and return the newly created node.
Keyword arguments:
namespaceURI -- namespace of element to create
localName -- local name of new element
prefix -- if namespaceURI is not defined, declare prefix. defaults
to 'ns1' if left unspecified.
'''
declare = False
qualifiedName = localName
if namespaceURI:
try:
prefix = self.getPrefix(namespaceURI)
except:
declare = True
prefix = prefix or self._getUniquePrefix()
if prefix:
qualifiedName = '%s:%s' %(prefix, localName)
node = self.createElementNS(namespaceURI, qualifiedName)
if declare:
node._setAttributeNS(XMLNS.BASE, 'xmlns:%s' %prefix, namespaceURI)
self._appendChild(node=node._getNode())
return node

def createInsertBefore(self, namespaceURI, localName, refChild):
qualifiedName = localName
prefix = self.getPrefix(namespaceURI)
if prefix:
qualifiedName = '%s:%s' %(prefix, localName)
node = self.createElementNS(namespaceURI, qualifiedName)
self._insertBefore(newChild=node._getNode(), refChild=refChild._getNode())
return node

def getElement(self, namespaceURI, localName):
'''
Keyword arguments:
namespaceURI -- namespace of element
localName -- local name of element
'''
node = self._dom.getElement(self.node, localName, namespaceURI, default=None)
if node:
return ElementProxy(self.sw, node)
return None

def getAttributeValue(self, namespaceURI, localName):
'''
Keyword arguments:
namespaceURI -- namespace of attribute
localName -- local name of attribute
'''
if self.hasAttribute(namespaceURI, localName):
attr = self.node.getAttributeNodeNS(namespaceURI,localName)
return attr.value
return None

def getValue(self):
return self._dom.getElementText(self.node, preserve_ws=True)

#############################################
#Methods for text nodes
#############################################
def createAppendTextNode(self, pyobj):
node = self.createTextNode(pyobj)
self._appendChild(node=node._getNode())
return node

def createTextNode(self, pyobj):
document = self._getOwnerDocument()
node = document.createTextNode(pyobj)
return ElementProxy(self.sw, node)

#############################################
#Methods for retrieving namespaceURI's
#############################################
def findNamespaceURI(self, qualifiedName):
parts = SplitQName(qualifiedName)
element = self._getNode()
if len(parts) == 1:
return (self._dom.findTargetNS(element), value)
return self._dom.findNamespaceURI(parts[0], element)

def resolvePrefix(self, prefix):
element = self._getNode()
return self._dom.findNamespaceURI(prefix, element)

def getSOAPEnvURI(self):
return self._soap_env_nsuri

def isEmpty(self):
return not self.node





class Collection(UserDict): class Collection(UserDict):
@@ -845,3 +1330,4 @@ if 1:
return clone return clone


xml.dom.minidom._clone_node = _clone_node xml.dom.minidom._clone_node = _clone_node


+ 254
- 6
WSDLTools.py View File

@@ -9,11 +9,11 @@


ident = "$Id$" ident = "$Id$"


from Utility import DOM, Collection, CollectionNS
import urllib, weakref
from cStringIO import StringIO
from Namespaces import OASIS, WSA, XMLNS
from Utility import Collection, CollectionNS, DOM, ElementProxy
from XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter from XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter
from Namespaces import WSR, WSA
from StringIO import StringIO
import urllib




class WSDLReader: class WSDLReader:
@@ -130,6 +130,39 @@ class WSDL:
self.imports[namespace] = item self.imports[namespace] = item
return item return item


def toDom(self):
""" Generate a DOM representation of the WSDL instance.
Not dealing with generating XML Schema, thus the targetNamespace
of all XML Schema elements or types used by WSDL message parts
needs to be specified via import information items.
"""
namespaceURI = DOM.GetWSDLUri(self.version)
self.document = DOM.createDocument(namespaceURI ,'wsdl:definitions')

# Set up a couple prefixes for easy reading.
child = DOM.getElement(self.document, None)
child.setAttributeNS(None, 'targetNamespace', self.targetNamespace)
child.setAttributeNS(XMLNS.BASE, 'xmlns:wsdl', namespaceURI)
child.setAttributeNS(XMLNS.BASE, 'xmlns:xsd', 'http://www.w3.org/1999/XMLSchema')
child.setAttributeNS(XMLNS.BASE, 'xmlns:soap', 'http://schemas.xmlsoap.org/wsdl/soap/')
child.setAttributeNS(XMLNS.BASE, 'xmlns:tns', self.targetNamespace)

# wsdl:import
for item in self.imports:
item.toDom()
# wsdl:message
for item in self.messages:
item.toDom()
# wsdl:portType
for item in self.portTypes:
item.toDom()
# wsdl:binding
for item in self.bindings:
item.toDom()
# wsdl:service
for item in self.services:
item.toDom()

def load(self, document): def load(self, document):
# We save a reference to the DOM document to ensure that elements # We save a reference to the DOM document to ensure that elements
# saved as "extensions" will continue to have a meaningful context # saved as "extensions" will continue to have a meaningful context
@@ -330,6 +363,7 @@ class Element:
self.extensions = [] self.extensions = []


def addExtension(self, item): def addExtension(self, item):
item.parent = weakref.ref(self)
self.extensions.append(item) self.extensions.append(item)




@@ -338,6 +372,17 @@ class ImportElement(Element):
self.namespace = namespace self.namespace = namespace
self.location = location self.location = location


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

def toDom(self):
wsdl = self.getWSDL()
ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'import')
epc.setAttributeNS(None, 'namespace', self.namespace)
epc.setAttributeNS(None, 'location', self.location)

_loaded = None _loaded = None




@@ -393,6 +438,19 @@ class Message(Element):
if elemref is not None: if elemref is not None:
part.element = ParseTypeRef(elemref, element) part.element = ParseTypeRef(elemref, element)


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

def toDom(self):
wsdl = self.getWSDL()
ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'message')
epc.setAttributeNS(None, 'name', self.name)

for part in self.parts:
part.toDom(epc._getNode())



class MessagePart(Element): class MessagePart(Element):
def __init__(self, name): def __init__(self, name):
@@ -416,6 +474,22 @@ class MessagePart(Element):
schema = wsdl.types.get(nsuri, {}) schema = wsdl.types.get(nsuri, {})
return schema.get(name) return schema.get(name)


def toDom(self, node):
"""node -- node representing message"""
wsdl = self.getWSDL()
ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'part')
epc.setAttributeNS(None, 'name', self.name)

if self.element is not None:
ns,name = self.element
prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, 'element', '%s:%s'%(prefix,name))
elif self.type is not None:
ns,name = self.type
prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, 'type', '%s:%s'%(prefix,name))



class PortType(Element): class PortType(Element):
'''PortType has a anyAttribute, thus must provide for an extensible '''PortType has a anyAttribute, thus must provide for an extensible
@@ -455,8 +529,8 @@ class PortType(Element):
self.documentation = GetDocumentation(element) self.documentation = GetDocumentation(element)
self.targetNamespace = DOM.getAttr(element, 'targetNamespace') self.targetNamespace = DOM.getAttr(element, 'targetNamespace')


if DOM.hasAttr(element, 'ResourceProperties', WSR.PROPERTIES):
rpref = DOM.getAttr(element, 'ResourceProperties', WSR.PROPERTIES)
if DOM.hasAttr(element, 'ResourceProperties', OASIS.PROPERTIES):
rpref = DOM.getAttr(element, 'ResourceProperties', OASIS.PROPERTIES)
self.resourceProperties = ParseQName(rpref, element) self.resourceProperties = ParseQName(rpref, element)


NS_WSDL = DOM.GetWSDLUri(self.getWSDL().version) NS_WSDL = DOM.GetWSDLUri(self.getWSDL().version)
@@ -501,6 +575,20 @@ class PortType(Element):
action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None) action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None)
operation.addFault(message, name, docs, action) operation.addFault(message, name, docs, action)
def toDom(self):
wsdl = self.getWSDL()

ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'portType')
epc.setAttributeNS(None, 'name', self.name)
if self.resourceProperties:
ns,name = self.resourceProperties
prefix = epc.getPrefix(ns)
epc.setAttributeNS(OASIS.PROPERTIES, 'ResourceProperties', '%s:%s'%(prefix,name))

for op in self.operations:
op.toDom(epc._getNode())





class Operation(Element): class Operation(Element):
@@ -511,6 +599,10 @@ class Operation(Element):
self.input = None self.input = None
self.output = None self.output = None


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

def getPortType(self): def getPortType(self):
return self.parent().parent() return self.parent().parent()


@@ -553,12 +645,28 @@ class Operation(Element):


def setInput(self, message, name='', documentation='', action=None): def setInput(self, message, name='', documentation='', action=None):
self.input = MessageRole('input', message, name, documentation, action) self.input = MessageRole('input', message, name, documentation, action)
self.input.parent = weakref.ref(self)
return self.input return self.input


def setOutput(self, message, name='', documentation='', action=None): def setOutput(self, message, name='', documentation='', action=None):
self.output = MessageRole('output', message, name, documentation, action) self.output = MessageRole('output', message, name, documentation, action)
self.output.parent = weakref.ref(self)
return self.output return self.output


def toDom(self, node):
wsdl = self.getWSDL()

ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'operation')
epc.setAttributeNS(None, 'name', self.name)
node = epc._getNode()
if self.input:
self.input.toDom(node)
if self.output:
self.output.toDom(node)
for fault in self.faults:
fault.toDom(node)



class MessageRole(Element): class MessageRole(Element):
def __init__(self, type, message, name='', documentation='', action=None): def __init__(self, type, message, name='', documentation='', action=None):
@@ -567,6 +675,22 @@ class MessageRole(Element):
self.type = type self.type = type
self.action = action self.action = action


def getWSDL(self):
"""Return the WSDL object that contains this MessageRole."""
if self.parent().getWSDL() == 'fault':
return self.parent().parent().getWSDL()
return self.parent().getWSDL()

def toDom(self, node):
wsdl = self.getWSDL()

ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), self.type)
epc.setAttributeNS(None, 'message', self.message)

if self.action:
epc.setAttributeNS(WSA.ADDRESS2004, 'Action', self.action)


class Binding(Element): class Binding(Element):
def __init__(self, name, type, documentation=''): def __init__(self, name, type, documentation=''):
@@ -641,6 +765,22 @@ class Binding(Element):
else: else:
self.addExtension(e) self.addExtension(e)


def toDom(self):
wsdl = self.getWSDL()
ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'binding')
epc.setAttributeNS(None, 'name', self.name)

ns,name = self.type
prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, 'type', '%s:%s' %(prefix,name))

node = epc._getNode()
for ext in self.extensions:
ext.toDom(node)
for op_binding in self.operations:
op_binding.toDom(node)



class OperationBinding(Element): class OperationBinding(Element):
def __init__(self, name, documentation=''): def __init__(self, name, documentation=''):
@@ -649,6 +789,11 @@ class OperationBinding(Element):
self.output = None self.output = None
self.faults = Collection(self) self.faults = Collection(self)


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


def getBinding(self): def getBinding(self):
"""Return the parent Binding object of the operation binding.""" """Return the parent Binding object of the operation binding."""
return self.parent().parent() return self.parent().parent()
@@ -669,12 +814,14 @@ class OperationBinding(Element):
def addInputBinding(self, binding): def addInputBinding(self, binding):
if self.input is None: if self.input is None:
self.input = MessageRoleBinding('input') self.input = MessageRoleBinding('input')
self.input.parent = weakref.ref(self)
self.input.addExtension(binding) self.input.addExtension(binding)
return binding return binding


def addOutputBinding(self, binding): def addOutputBinding(self, binding):
if self.output is None: if self.output is None:
self.output = MessageRoleBinding('output') self.output = MessageRoleBinding('output')
self.output.parent = weakref.ref(self)
self.output.addExtension(binding) self.output.addExtension(binding)
return binding return binding


@@ -702,12 +849,34 @@ class OperationBinding(Element):
else: else:
self.addExtension(e) self.addExtension(e)


def toDom(self, node):
wsdl = self.getWSDL()
ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'operation')
epc.setAttributeNS(None, 'name', self.name)

node = epc._getNode()
for ext in self.extensions:
ext.toDom(node)
if self.input:
self.input.toDom(node)
if self.output:
self.output.toDom(node)
for fault in self.faults:
fault.toDom(node)



class MessageRoleBinding(Element): class MessageRoleBinding(Element):
def __init__(self, type, name='', documentation=''): def __init__(self, type, name='', documentation=''):
Element.__init__(self, name, documentation) Element.__init__(self, name, documentation)
self.type = type self.type = type


def getWSDL(self):
"""Return the WSDL object that contains this MessageRole."""
if self.type == 'fault':
return self.parent().parent().getWSDL()
return self.parent().getWSDL()

def findBinding(self, kind): def findBinding(self, kind):
for item in self.extensions: for item in self.extensions:
if isinstance(item, kind): if isinstance(item, kind):
@@ -795,6 +964,15 @@ class MessageRoleBinding(Element):
else: else:
self.addExtension(e) self.addExtension(e)


def toDom(self, node):
wsdl = self.getWSDL()
ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), self.type)

node = epc._getNode()
for item in self.extensions:
if item: item.toDom(node)



class Service(Element): class Service(Element):
def __init__(self, name, documentation=''): def __init__(self, name, documentation=''):
@@ -826,12 +1004,25 @@ class Service(Element):
for e in elements: for e in elements:
self.addExtension(e) self.addExtension(e)


def toDom(self):
wsdl = self.getWSDL()
ep = ElementProxy(None, DOM.getElement(wsdl.document, None))
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), "service")
epc.setAttributeNS(None, "name", self.name)

node = epc._getNode()
for port in self.ports:
port.toDom(node)



class Port(Element): class Port(Element):
def __init__(self, name, binding, documentation=''): def __init__(self, name, binding, documentation=''):
Element.__init__(self, name, documentation) Element.__init__(self, name, documentation)
self.binding = binding self.binding = binding


def getWSDL(self):
return self.parent().parent().getWSDL()

def getService(self): def getService(self):
"""Return the Service object associated with this port.""" """Return the Service object associated with this port."""
return self.parent().parent() return self.parent().parent()
@@ -874,23 +1065,69 @@ class Port(Element):
else: else:
self.addExtension(e) self.addExtension(e)


def toDom(self, node):
wsdl = self.getWSDL()
ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), "port")
epc.setAttributeNS(None, "name", self.name)

ns,name = self.binding
prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, "binding", "%s:%s" %(prefix,name))

node = epc._getNode()
for ext in self.extensions:
ext.toDom(node)



class SoapBinding: class SoapBinding:
def __init__(self, transport, style='rpc'): def __init__(self, transport, style='rpc'):
self.transport = transport self.transport = transport
self.style = style self.style = style


def getWSDL(self):
return self.parent().getWSDL()

def toDom(self, node):
wsdl = self.getWSDL()
ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'binding')
if self.transport:
epc.setAttributeNS(None, "transport", self.transport)
if self.style:
epc.setAttributeNS(None, "style", self.style)


class SoapAddressBinding: class SoapAddressBinding:
def __init__(self, location): def __init__(self, location):
self.location = location self.location = location


def getWSDL(self):
return self.parent().getWSDL()

def toDom(self, node):
wsdl = self.getWSDL()
ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'address')
epc.setAttributeNS(None, "location", self.location)



class SoapOperationBinding: class SoapOperationBinding:
def __init__(self, soapAction=None, style=None): def __init__(self, soapAction=None, style=None):
self.soapAction = soapAction self.soapAction = soapAction
self.style = style self.style = style


def getWSDL(self):
return self.parent().getWSDL()

def toDom(self, node):
wsdl = self.getWSDL()
ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'operation')
if self.soapAction:
epc.setAttributeNS(None, 'soapAction', self.soapAction)
if self.style:
epc.setAttributeNS(None, 'style', self.style)



class SoapBodyBinding: class SoapBodyBinding:
def __init__(self, use, namespace=None, encodingStyle=None, parts=None): def __init__(self, use, namespace=None, encodingStyle=None, parts=None):
@@ -905,6 +1142,17 @@ class SoapBodyBinding:
self.parts = parts self.parts = parts
self.use = use self.use = use


def getWSDL(self):
return self.parent().getWSDL()

def toDom(self, node):
wsdl = self.getWSDL()
ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'body')
epc.setAttributeNS(None, "use", self.use)
epc.setAttributeNS(None, "namespace", self.namespace)


class SoapFaultBinding: class SoapFaultBinding:
def __init__(self, name, use, namespace=None, encodingStyle=None): def __init__(self, name, use, namespace=None, encodingStyle=None):
if not use in ('literal', 'encoded'): if not use in ('literal', 'encoded'):


+ 1
- 4
__init__.py View File

@@ -3,10 +3,7 @@


ident = "$Id$" ident = "$Id$"


import WSDLTools
#import WSDLTools
import XMLname import XMLname
import logging import logging


class Base:
def __init__(self, module=__name__):
self.logger = logging.getLogger('%s-%s(%x)' %(module, self.__class__, id(self)))

+ 505
- 0
c14n.py View File

@@ -0,0 +1,505 @@
#! /usr/bin/env python
"""Compatibility module, imported by ZSI if you don't have PyXML 0.7.

No copyright violations -- we're only using parts of PyXML that we
wrote.
"""

from ZSI import _attrs, _children, _copyright

_copyright += "\n\nPortions are also: "
_copyright += '''Copyright 2001, Zolera Systems Inc. All Rights Reserved.
Copyright 2001, MIT. All Rights Reserved.

Distributed under the terms of:
Python 2.0 License or later.
http://www.python.org/2.0.1/license.html
or
W3C Software License
http://www.w3.org/Consortium/Legal/copyright-software-19980720
'''

from xml.dom import Node
from Namespaces import XMLNS
import cStringIO as StringIO
try:
from xml.dom.ext import c14n
except ImportError, ex:
_implementation2 = None
else:
class _implementation2(c14n._implementation):
"""Patch for exclusive c14n
"""
def __init__(self, node, write, **kw):
self.unsuppressedPrefixes = kw.get('unsuppressedPrefixes')
self._exclusive = None
if node.nodeType == Node.ELEMENT_NODE:
if not c14n._inclusive(self):
self._exclusive = self._inherit_context(node)
c14n._implementation.__init__(self, node, write, **kw)

def _do_element(self, node, initial_other_attrs = []):
"""Patch for the xml.dom.ext.c14n implemenation _do_element method.
This fixes a problem with sorting of namespaces.
"""
# Get state (from the stack) make local copies.
# ns_parent -- NS declarations in parent
# ns_rendered -- NS nodes rendered by ancestors
# ns_local -- NS declarations relevant to this element
# xml_attrs -- Attributes in XML namespace from parent
# xml_attrs_local -- Local attributes in XML namespace.
ns_parent, ns_rendered, xml_attrs = \
self.state[0], self.state[1].copy(), self.state[2].copy() #0422
ns_local = ns_parent.copy()
xml_attrs_local = {}

# Divide attributes into NS, XML, and others.
#other_attrs = initial_other_attrs[:]
other_attrs = []
sort_these_attrs = initial_other_attrs[:]

in_subset = c14n._in_subset(self.subset, node)
#for a in _attrs(node):
sort_these_attrs +=c14n._attrs(node)
for a in sort_these_attrs:
if a.namespaceURI == c14n.XMLNS.BASE:
n = a.nodeName
if n == "xmlns:": n = "xmlns" # DOM bug workaround
ns_local[n] = a.nodeValue
elif a.namespaceURI == c14n.XMLNS.XML:
if c14n._inclusive(self) or (in_subset and c14n._in_subset(self.subset, a)): #020925 Test to see if attribute node in subset
xml_attrs_local[a.nodeName] = a #0426
else:
if c14n._in_subset(self.subset, a): #020925 Test to see if attribute node in subset
other_attrs.append(a)
#add local xml:foo attributes to ancestor's xml:foo attributes
xml_attrs.update(xml_attrs_local)

# Render the node
W, name = self.write, None
if in_subset:
name = node.nodeName
W('<')
W(name)

# Create list of NS attributes to render.
ns_to_render = []
for n,v in ns_local.items():

# If default namespace is XMLNS.BASE or empty,
# and if an ancestor was the same
if n == "xmlns" and v in [ c14n.XMLNS.BASE, '' ] \
and ns_rendered.get('xmlns') in [ c14n.XMLNS.BASE, '', None ]:
continue

# "omit namespace node with local name xml, which defines
# the xml prefix, if its string value is
# http://www.w3.org/XML/1998/namespace."
if n in ["xmlns:xml", "xml"] \
and v in [ 'http://www.w3.org/XML/1998/namespace' ]:
continue


# If not previously rendered
# and it's inclusive or utilized
if (n,v) not in ns_rendered.items() \
and (c14n._inclusive(self) or \
c14n._utilized(n, node, other_attrs, self.unsuppressedPrefixes)):
ns_to_render.append((n, v))

#####################################
# JRB
#####################################
if not c14n._inclusive(self):
if node.prefix is None:
look_for = [('xmlns', node.namespaceURI),]
else:
look_for = [('xmlns:%s' %node.prefix, node.namespaceURI),]
for a in c14n._attrs(node):
if a.namespaceURI != XMLNS.BASE:
#print "ATTRIBUTE: ", (a.namespaceURI, a.prefix)
if a.prefix:
#print "APREFIX: ", a.prefix
look_for.append(('xmlns:%s' %a.prefix, a.namespaceURI))

for key,namespaceURI in look_for:
if ns_rendered.has_key(key):
if ns_rendered[key] == namespaceURI:
# Dont write out
pass
else:
#ns_to_render += [(key, namespaceURI)]
pass
elif (key,namespaceURI) in ns_to_render:
# Dont write out
pass
else:
# Unique write out, rewrite to render
ns_local[key] = namespaceURI
for a in self._exclusive:
if a.nodeName == key:
#self._do_attr(a.nodeName, a.value)
#ns_rendered[key] = namespaceURI
#break
ns_to_render += [(a.nodeName, a.value)]
break
elif key is None and a.nodeName == 'xmlns':
#print "DEFAULT: ", (a.nodeName, a.value)
ns_to_render += [(a.nodeName, a.value)]
break
#print "KEY: ", key
else:
#print "Look for: ", look_for
#print "NS_TO_RENDER: ", ns_to_render
#print "EXCLUSIVE NS: ", map(lambda f: (f.nodeName,f.value),self._exclusive)
raise RuntimeError, \
'can not find namespace (%s="%s") for exclusive canonicalization'\
%(key, namespaceURI)
#####################################



# Sort and render the ns, marking what was rendered.
ns_to_render.sort(c14n._sorter_ns)
for n,v in ns_to_render:
#XXX JRB, getting 'xmlns,None' here when xmlns=''
if v: self._do_attr(n, v)
else:
v = ''
self._do_attr(n, v)
ns_rendered[n]=v #0417

# If exclusive or the parent is in the subset, add the local xml attributes
# Else, add all local and ancestor xml attributes
# Sort and render the attributes.
if not c14n._inclusive(self) or c14n._in_subset(self.subset,node.parentNode): #0426
other_attrs.extend(xml_attrs_local.values())
else:
other_attrs.extend(xml_attrs.values())
#print "OTHER: ", other_attrs
other_attrs.sort(c14n._sorter)
for a in other_attrs:
self._do_attr(a.nodeName, a.value)
W('>')


# Push state, recurse, pop state.
state, self.state = self.state, (ns_local, ns_rendered, xml_attrs)
for c in c14n._children(node):
c14n._implementation.handlers[c.nodeType](self, c)
self.state = state

if name: W('</%s>' % name)
c14n._implementation.handlers[c14n.Node.ELEMENT_NODE] = _do_element


_IN_XML_NS = lambda n: n.namespaceURI == XMLNS.XML

# Does a document/PI has lesser/greater document order than the
# first element?
_LesserElement, _Element, _GreaterElement = range(3)

def _sorter(n1,n2):
'''_sorter(n1,n2) -> int
Sorting predicate for non-NS attributes.'''

i = cmp(n1.namespaceURI, n2.namespaceURI)
if i: return i
return cmp(n1.localName, n2.localName)


def _sorter_ns(n1,n2):
'''_sorter_ns((n,v),(n,v)) -> int
"(an empty namespace URI is lexicographically least)."'''

if n1[0] == 'xmlns': return -1
if n2[0] == 'xmlns': return 1
return cmp(n1[0], n2[0])

def _utilized(n, node, other_attrs, unsuppressedPrefixes):
'''_utilized(n, node, other_attrs, unsuppressedPrefixes) -> boolean
Return true if that nodespace is utilized within the node'''

if n.startswith('xmlns:'):
n = n[6:]
elif n.startswith('xmlns'):
n = n[5:]
if n == node.prefix or n in unsuppressedPrefixes: return 1
for attr in other_attrs:
if n == attr.prefix: return 1
return 0

_in_subset = lambda subset, node: not subset or node in subset

#
# JRB. Currently there is a bug in do_element, but since the underlying
# Data Structures in c14n have changed I can't just apply the
# _implementation2 patch above. But this will work OK for most uses,
# just not XML Signatures.
#
class _implementation:
'''Implementation class for C14N. This accompanies a node during it's
processing and includes the parameters and processing state.'''

# Handler for each node type; populated during module instantiation.
handlers = {}

def __init__(self, node, write, **kw):
'''Create and run the implementation.'''

self.write = write
self.subset = kw.get('subset')
if self.subset:
self.comments = kw.get('comments', 1)
else:
self.comments = kw.get('comments', 0)
self.unsuppressedPrefixes = kw.get('unsuppressedPrefixes')
nsdict = kw.get('nsdict', { 'xml': XMLNS.XML, 'xmlns': XMLNS.BASE })

# Processing state.
self.state = (nsdict, ['xml'], [])

if node.nodeType == Node.DOCUMENT_NODE:
self._do_document(node)
elif node.nodeType == Node.ELEMENT_NODE:
self.documentOrder = _Element # At document element
if self.unsuppressedPrefixes is not None:
self._do_element(node)
else:
inherited = self._inherit_context(node)
self._do_element(node, inherited)
elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
pass
else:
raise TypeError, str(node)


def _inherit_context(self, node):
'''_inherit_context(self, node) -> list
Scan ancestors of attribute and namespace context. Used only
for single element node canonicalization, not for subset
canonicalization.'''

# Collect the initial list of xml:foo attributes.
xmlattrs = filter(_IN_XML_NS, _attrs(node))

# Walk up and get all xml:XXX attributes we inherit.
inherited, parent = [], node.parentNode
while parent and parent.nodeType == Node.ELEMENT_NODE:
for a in filter(_IN_XML_NS, _attrs(parent)):
n = a.localName
if n not in xmlattrs:
xmlattrs.append(n)
inherited.append(a)
parent = parent.parentNode
return inherited


def _do_document(self, node):
'''_do_document(self, node) -> None
Process a document node. documentOrder holds whether the document
element has been encountered such that PIs/comments can be written
as specified.'''

self.documentOrder = _LesserElement
for child in node.childNodes:
if child.nodeType == Node.ELEMENT_NODE:
self.documentOrder = _Element # At document element
self._do_element(child)
self.documentOrder = _GreaterElement # After document element
elif child.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
self._do_pi(child)
elif child.nodeType == Node.COMMENT_NODE:
self._do_comment(child)
elif child.nodeType == Node.DOCUMENT_TYPE_NODE:
pass
else:
raise TypeError, str(child)
handlers[Node.DOCUMENT_NODE] = _do_document


def _do_text(self, node):
'''_do_text(self, node) -> None
Process a text or CDATA node. Render various special characters
as their C14N entity representations.'''
if not _in_subset(self.subset, node): return
s = node.data \
.replace("&", "&amp;") \
.replace("<", "&lt;") \
.replace(">", "&gt;") \
.replace("\015", "&#xD;")
if s: self.write(s)
handlers[Node.TEXT_NODE] = _do_text
handlers[Node.CDATA_SECTION_NODE] = _do_text


def _do_pi(self, node):
'''_do_pi(self, node) -> None
Process a PI node. Render a leading or trailing #xA if the
document order of the PI is greater or lesser (respectively)
than the document element.
'''
if not _in_subset(self.subset, node): return
W = self.write
if self.documentOrder == _GreaterElement: W('\n')
W('<?')
W(node.nodeName)
s = node.data
if s:
W(' ')
W(s)
W('?>')
if self.documentOrder == _LesserElement: W('\n')
handlers[Node.PROCESSING_INSTRUCTION_NODE] = _do_pi


def _do_comment(self, node):
'''_do_comment(self, node) -> None
Process a comment node. Render a leading or trailing #xA if the
document order of the comment is greater or lesser (respectively)
than the document element.
'''
if not _in_subset(self.subset, node): return
if self.comments:
W = self.write
if self.documentOrder == _GreaterElement: W('\n')
W('<!--')
W(node.data)
W('-->')
if self.documentOrder == _LesserElement: W('\n')
handlers[Node.COMMENT_NODE] = _do_comment


def _do_attr(self, n, value):
''''_do_attr(self, node) -> None
Process an attribute.'''

W = self.write
W(' ')
W(n)
W('="')
s = value \
.replace("&", "&amp;") \
.replace("<", "&lt;") \
.replace('"', '&quot;') \
.replace('\011', '&#x9') \
.replace('\012', '&#xA') \
.replace('\015', '&#xD')
W(s)
W('"')

def _do_element(self, node, initial_other_attrs = []):
'''_do_element(self, node, initial_other_attrs = []) -> None
Process an element (and its children).'''

# Get state (from the stack) make local copies.
# ns_parent -- NS declarations in parent
# ns_rendered -- NS nodes rendered by ancestors
# xml_attrs -- Attributes in XML namespace from parent
# ns_local -- NS declarations relevant to this element
ns_parent, ns_rendered, xml_attrs = \
self.state[0], self.state[1][:], self.state[2][:]
ns_local = ns_parent.copy()

# Divide attributes into NS, XML, and others.
other_attrs = initial_other_attrs[:]
in_subset = _in_subset(self.subset, node)
for a in _attrs(node):
if a.namespaceURI == XMLNS.BASE:
n = a.nodeName
if n == "xmlns:": n = "xmlns" # DOM bug workaround
ns_local[n] = a.nodeValue
elif a.namespaceURI == XMLNS.XML:
if self.unsuppressedPrefixes is None or in_subset:
xml_attrs.append(a)
else:
other_attrs.append(a)

# Render the node
W, name = self.write, None
if in_subset:
name = node.nodeName
W('<')
W(name)

# Create list of NS attributes to render.
ns_to_render = []
for n,v in ns_local.items():
pval = ns_parent.get(n)

# If default namespace is XMLNS.BASE or empty, skip
if n == "xmlns" \
and v in [ XMLNS.BASE, '' ] and pval in [ XMLNS.BASE, '' ]:
continue

# "omit namespace node with local name xml, which defines
# the xml prefix, if its string value is
# http://www.w3.org/XML/1998/namespace."
if n == "xmlns:xml" \
and v in [ 'http://www.w3.org/XML/1998/namespace' ]:
continue

# If different from parent, or parent didn't render
# and if not exclusive, or this prefix is needed or
# not suppressed
if (v != pval or n not in ns_rendered) \
and (self.unsuppressedPrefixes is None or \
_utilized(n, node, other_attrs, self.unsuppressedPrefixes)):
ns_to_render.append((n, v))

# Sort and render the ns, marking what was rendered.
ns_to_render.sort(_sorter_ns)
for n,v in ns_to_render:
self._do_attr(n, v)
ns_rendered.append(n)

# Add in the XML attributes (don't pass to children, since
# we're rendering them), sort, and render.
other_attrs.extend(xml_attrs)
xml_attrs = []
other_attrs.sort(_sorter)
for a in other_attrs:
self._do_attr(a.nodeName, a.value)
W('>')

# Push state, recurse, pop state.
state, self.state = self.state, (ns_local, ns_rendered, xml_attrs)
for c in _children(node):
_implementation.handlers[c.nodeType](self, c)
self.state = state

if name: W('</%s>' % name)
handlers[Node.ELEMENT_NODE] = _do_element


def Canonicalize(node, output=None, **kw):
'''Canonicalize(node, output=None, **kw) -> UTF-8

Canonicalize a DOM document/element node and all descendents.
Return the text; if output is specified then output.write will
be called to output the text and None will be returned
Keyword parameters:
nsdict: a dictionary of prefix:uri namespace entries
assumed to exist in the surrounding context
comments: keep comments if non-zero (default is 0)
subset: Canonical XML subsetting resulting from XPath
(default is [])
unsuppressedPrefixes: do exclusive C14N, and this specifies the
prefixes that should be inherited.
'''
if output:
if _implementation2 is None:
_implementation(node, output.write, **kw)
else:
apply(_implementation2, (node, output.write), kw)
else:
s = c14n.StringIO.StringIO()
if _implementation2 is None:
_implementation(node, s.write, **kw)
else:
apply(_implementation2, (node, s.write), kw)
return s.getvalue()


if __name__ == '__main__': print _copyright

Loading…
Cancel
Save