def parse(self, file): """Parse parameters stored as XML file :param file: input file object or class:`java.io.BufferedReader` :return: parsed input object """ maxFileSize = None inputXml = None # get the maximal input file size from configuration maxFileSize = self.getMaxFileSize( pywps.config.getConfigValue("server", "maxFileSize").lower()) # read the document if OSNAME == "java" and\ type(file) != types.FileType: inputXml = "" while 1: line = file.readLine() if not line: break inputXml += line # TODO: # if maxFileSize > 0 and\ # inputXml.__sizeof__() > maxFileSize: # raise pywps.FileSizeExceeded() # make DOM from XML import org.xml.sax.SAXException try: self.document = parseString(inputXml) except org.xml.sax.SAXException, e: raise pywps.NoApplicableCode(e.message)
def getWPSContent(self): """Get the specific WPS XML content of inside the SOAP request. The Element position may change if there is a SOAP header or if is was sent as a message inside the Body content The script will check for a standard WPS request or a ExecuteProcess_ one""" reqWPS = self.root.xpath( "//*[local-name() = 'GetCapabilities' or local-name()='DescribeProcess' or local-name()='Execute' or contains(local-name(),'ExecuteProcess_') or contains(local-name(),'ExecuteProcessAsync_')] " ) if bool(reqWPS): # General WPS: # print reqWPS[0].tag #getting the element's name if "ExecuteProcess" in reqWPS[0].tag: XMLStr = SOAPtoWPS(reqWPS[0]) XMLDoc = minidom.parseString(XMLStr) return getFirstChildNode(XMLDoc) #GetCapabilites/DescribeProcess or Execute #getCapabilities=root.xpath("//*[local-name() = 'GetCapabilities' or local-name()='DescribeProcess']") else: # Normal WPS reqWPS = doFixTavernaBug(reqWPS[0]) XMLDoc = minidom.parseString(etree.tostring(reqWPS)) return getFirstChildNode(XMLDoc) else: # if bool(reqWPS) raise pywps.NoApplicableCode( "Could not deternine the WPS request type from SOAP envelope. Couldnt determine GetCapabilities/DescribeProcess/Execute/ExecuteProcess_ from XML content" )
def __init__(self, host='', port=21): """Store the user name, password and acct for futher uses and call the ftplib.FTP.__init__()""" ftplib.FTP.__init__(self) try: self.connect(host=host, port=port) except Exception,e: raise pywps.NoApplicableCode(e.__str__()+": host=%s,port=%s" %(host,port))
def getFirstChildNode(self, document): """Find first usable child node of the document (no comments)""" node = None # get the first child (omit comments) for node in document.childNodes: if node.nodeType == xml.dom.minidom.Element.nodeType: firstChild = node if firstChild == None: raise pywps.NoApplicableCode("No root Element found!") return firstChild
def __init__(self, document=None): if document: # http://bugs.python.org/issue5762 parser = etree.XMLParser(resolve_entities=False) try: if type(input) == type(""): self.tree = etree.parse( StringIO.StringIO( unescape(document, entities={""": "'"})), parser) #<?xml version='1.0' encoding='UTF-8'?> will cause a crash # lxml.etree.XMLSyntaxError: XML declaration allowed only at # the start of the document, line 1, column 103 else: try: # Not very efficient, the XML is converted to string # and then back again to XML self.tree = etree.parse( StringIO.StringIO( unescape(document.toxml(), entities={""": "'"})), parser) except: document = doCleanBug5762(document) self.tree = etree.parse( StringIO.StringIO( unescape(document.toxml(), entities={""": "'"})), parser) except etree.XMLSyntaxError, e: # Generic parsing error raise pywps.NoApplicableCode(e.message) self.root = self.tree.getroot() # Searching of a Envelope element (case sensitive) self.envElement = self.root.xpath( "//*[contains(local-name(),'Envelope')]" ) # It actually retunrs the node # Check for SOAP name space self.nameSpaceSet = set( self.root.nsmap.values()) & set(soap_env_NS) self.nsIndex = soap_env_NS.index(self.nameSpaceSet.pop()) if (self.nsIndex == 1): self.soapVersion = 11 else: self.soapVersion = 12 # Check for ExecuteProcess self.isSoapExecute = bool( self.root.xpath("//*[contains(local-name(),'ExecuteProcess')]") ) # just to be certain that is a bool
def SOAPtoWPS(tree): # NOTE: # The etree output of ComplexData will not contain the OWS/WPS/XSI namespace since this name space is defined in the head of the WPS:Execute # The XSI is not necessary in the WPS:Execute, therefore it was deleted and its now inside the ComplexInput (if necessary) # An input shouldn't have elements in with OWS/WPS namespace, nevertheless a hack was implemented that allows for their presence. # The solution is a tiny hack the XSL file, the WPS/OWS namespace are different from the ComplexInput, something like this: http://REPLACEME/wps/1.0.0 # When etree is printed the REPLACEME is subtituted by www.opengis.net, creating the correct namespaces for the DOM parsing. # The replace is done using module re and set that it has to do only 2 # replaces in the beggining. Therefore the replace is independe of the # since of XML content global process from pywps import processes processID = tree.tag.split("_", 1)[-1] wps2 = pywps.Pywps() wps2.inputs = { 'request': 'getCapabilities', 'version': '1.0.0', 'service': 'wps' } from pywps.Wps import Request request = Request(wps2) try: process = [ process for process in request.processes if process.identifier in [processID] ][0] except IndexError: # #If the server url is incorrect the process request will not be found in the WPS process list raise pywps.NoApplicableCode( "The requested process is not part of the instance. Check pywps conf file and WSDL. WSDL has to point to the correct wrapper, please check location attribute in address element of WSDL document" ) XSLTDocIO = open(pywps.XSLT.__path__[0] + "/SOAP2WPS.xsl", "r") XSLTDoc = etree.parse(XSLTDocIO) transformer = etree.XSLT(XSLTDoc) WPSTree = transformer(tree) etree.cleanup_namespaces(WPSTree) XMLOut = etree.tostring(WPSTree) XMLOut = re.sub(r'REPLACEME', "www.opengis.net", XMLOut, 2) return XMLOut
def parseDataInputs(self, inputsNode): """ Parse input data from given node """ parsedDataInputs = [] for inputNode in inputsNode.getElementsByTagNameNS( self.nameSpace, "Input"): # input Identifier try: identifier = inputNode.getElementsByTagNameNS( self.owsNameSpace, "Identifier")[0].firstChild.nodeValue except (IndexError, AttributeError): raise pywps.NoApplicableCode("Identifier for input not set") parsedDataInputs.append({ "identifier": identifier, "value": None, "attributes": {} }) # Title and Abstract are only mandatory and not necessary: # skipping, not supported yet # formchoice try: dataTypeNode = inputNode.getElementsByTagNameNS( self.nameSpace, "Reference")[0] attributes = self.parseReferenceDataInput(dataTypeNode) attributes["identifier"] = identifier parsedDataInputs[-1] = attributes except IndexError, e: dataTypeNode = inputNode.getElementsByTagNameNS( self.nameSpace, "Data")[0] attributes = self.parseDataInput(dataTypeNode) attributes["identifier"] = identifier parsedDataInputs[-1] = attributes try: parsedDataInputs[-1] except KeyError: raise pywps.InvalidParameterValue(identifier)
self.document = parseString(inputXml) except org.xml.sax.SAXException, e: raise pywps.NoApplicableCode(e.message) else: if maxFileSize > 0: inputXml = file.read(maxFileSize) if file.read() != "": raise pywps.FileSizeExceeded() else: inputXml = file.read() # make DOM from XML try: self.document = parseString(inputXml) except xml.parsers.expat.ExpatError, e: raise pywps.NoApplicableCode(e.message) # get first child firstChild = self.isSoapFirstChild(self.document) # check service name self.checkService(firstChild) # find request type self.checkRequestType(firstChild) # parse the document self.inputs = self.requestParser.parse(self.document, self.inputs) return self.inputs