XML input/output implementation was more "tricky", and required some implementation decisions.
anyType schema defintion
WSDL's schema section defines the input/output content of the service, in theory a type that isn't set should be considered xsd:anyType, meaning it can be a string, numerical or XML content.
<schema targetNamespace="http://www.opengis.net/wps/1.0.0"> <element name="ExecuteProcess_BufferProcessResponse"> <complexType> <sequence> <element name="bufferResult" minOccurs="1" maxOccurs="1"/> </sequence> </complexType> </element> </schema>
In theory the XML above should inform the XMLSplitters that bufferResult contains a string or XML and a XMLSplitter should fetch all the content that is child of <bufferResult> element. Unfortunally the XMLSplitter will not work if the content type isn't set and the only way to implemented it by creating a new type inside the schema section, as follows:
<schema targetNamespace="http://www.opengis.net/wps/1.0.0"> <element name="ExecuteProcess_BufferProcessResponse"> <complexType> <sequence> <element name="bufferResult" minOccurs="1" maxOccurs="1" type="wps:dummyType"/> </sequence> </complexType> </element> <complexType name="dummyType"> <sequence> <any namespace="##any" processContents="skip" minOccurs="1" maxOccurs="1"></any> </sequence> </complexType> </schema>
Here we say: bufferResult is a dummyType and in turn dummyType can be any XML content. When applying an XML splitter the output XML will contain a root element with the output name:
<bufferResult> <gml>.......</gml </bufferResult>
Having this root element, prevents for the XML output to be sent directly to a different service as input. Therefore the XML output has to be sent to another service (XPath) to have the root element removed.
Another problem is the WPS ComplexData structure that can contain XML or String (for example base64), if a ComplexData contains a base64 string image it's necessary to remove the anyType definition for the XMLSplitter to work. The ComplexData could be overcome by checking its mimeType and setting the proper WSDL structure.
To make things simpler it was decided to drop the anyType declaration and the use of XMLSplitters in case of ComplexData outputs. If a process has a ComplexData output it shouldn't be a problem if the content is a base64 string, if its an XML content it should be fetched using the Xpath plugin.
XML is inputed as a file in the Workflow flow input port.
The following example uses a buffer process that accepts a GML feature collection with polygon data and calculates a new buffer for each feature and returns it.
The blue boxes are wokflow input/output ports, the grey box is a constant value (in this case it was set to 0.001 degrees) and the green service the WPS service.
When the workflow is run the Input window will open and request for user input location, since the GML with the feature collection is a local file it's enough to click on "Add file location(s)" and select the correct file
Since we haven't applied an XML output splitter to the WPS service DataOutput we will have the complete service response in the GML_result output port.
GML's FeatureCollection is a child of the bufferResult element, to get a pure GML output its necessary pass the XML thru the XPath plugin. This plugin supports Xpath XML extraction, but without entering into details we just need any XML that is child of bufferResult, this can be easily done using the a Xpath query "''*[local-name()='bufferResult']/*", that says: "Get me all the children (/*) of an element that has name "bufferResult", ignoring any namespace defintion".
To run an Xpath query it's necessary to install the Xpath plugin (see: Installation section), and then select it as a service in the Service Templates locate in the Service Panel
The Xpath service will appear as a yellow box. To set the Xpath expression: Right click on Xpath service > Configure Xpath Service
The new window is a practical Xpath GUI, where the user can paste his XML input, check the validiy of Xpath syntax and check on the fly the output.
Probably 99% of the users only need the processe's XML output, a generic XPath query like: "''//*[local-name()='<output result element>']/*" should be enough !!!!
Now the workflow will look like this and the GML_Output will contain a pure GML result that can be used in another service or just saved as a file.
To make things more interesting, we can chain the input/output and call the buffer process a second time.
The workbench's input/output ports content can be saved after running the workflow (GML_Output_0.01 and GML_Output_0.01_0.01 ) and their values checked using QGIS.
Easy no !?
--Wikiadmin 17:12, 10 January 2011 (UTC)