Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple way to parse a WSDL

Tags:

java

wsdl

parsing

I am trying to parse a WSDL to get the operations, endpoint and an example payload. The WSDL in inputted by the user. I can't find a tutorial to do this.

I can only find ones that generate source code which I don't need. I've tried using XBeans but apparently I need Saxon. Is there a simple lightweight way to do this without Saxon?

E.g.

   <?xml version="1.0"?>
  <definitions name="StockQuote"
  targetNamespace=
    "http://example.com/stockquote.wsdl"
  xmlns:tns="http://example.com/stockquote.wsdl"
  xmlns:xsd1="http://example.com/stockquote.xsd"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns="http://schemas.xmlsoap.org/wsdl/">
   <types>
   <schema targetNamespace=
     "http://example.com/stockquote.xsd"
     xmlns="http://www.w3.org/2000/10/XMLSchema">
      <element name="TradePriceRequest">
        <complexType>
           <all>
             <element name="tickerSymbol" 
               type="string"/>
           </all>
        </complexType>
      </element>
      <element name="TradePrice">
        <complexType>
          <all>
            <element name="price" type="float"/>
          </all>
        </complexType>
      </element>
   </schema>
   </types>
   <message name="GetLastTradePriceInput">
     <part name="body" element=
       "xsd1:TradePriceRequest"/>
   </message>
   <message name="GetLastTradePriceOutput">
     <part name="body" element="xsd1:TradePrice"/>
   </message>
   <portType name="StockQuotePortType">
     <operation name="GetLastTradePrice">
       <input message="tns:GetLastTradePriceInput"/>
       <output message="tns:GetLastTradePriceOutput"/>
     </operation>
   </portType>
     <binding name="StockQuoteSoapBinding"
       type="tns:StockQuotePortType">
       <soap:binding style="document"
         transport=
           "http://schemas.xmlsoap.org/soap/http"/>
     <operation name="GetLastTradePrice">
       <soap:operation
         soapAction=
           "http://example.com/GetLastTradePrice"/>
         <input>
           <soap:body use="literal"/>
         </input>
         <output>
           <soap:body use="literal"/>
         </output>
       </operation>
     </binding>
     <service name="StockQuoteService">
       <documentation>My first service</documentation>
       <port name="StockQuotePort" 
         binding="tns:StockQuoteBinding">
         <soap:address location=
           "http://example.com/stockquote"/>
       </port>
     </service>
    </definitions>

Should get operations: GetLastTradePrice, GetLastTradePrice

Endpoint: StockQuotePort

Sample Payload:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stoc="http://example.com/stockquote.xsd">
   <soapenv:Header/>
   <soapenv:Body>
      <stoc:TradePriceRequest/>
   </soapenv:Body>
</soapenv:Envelope>

This is like what SoapUI does. But I'm mainly concerned with being able to parse the WSDL. A bit more context is the WSDL is uploaded and then the result is displayed in a GWT application (file upload must go to the servlet). So I need to parse the file and create an object the GWT will be able to understand.

like image 855
Rebzie Avatar asked May 16 '12 01:05

Rebzie


2 Answers

This looks nice: http://www.membrane-soa.org/soa-model-doc/1.4/java-api/parse-wsdl-java-api.htm

Didn't work on first attempt for me though, So I wrote a method that returns the suggested results for the sample wsdl - no dependencies outside of J2SE6.

public String[] listOperations(String filename) throws FileNotFoundException, SAXException, IOException, ParserConfigurationException {
  Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(filename));
  NodeList elements = d.getElementsByTagName("operation");
  ArrayList<String> operations = new ArrayList<String>();
  for (int i = 0; i < elements.getLength(); i++) {
    operations.add(elements.item(i).getAttributes().getNamedItem("name").getNodeValue());
  }
  return operations.toArray(new String[operations.size()]);
}

Seems like you would want to remove the duplicates, since each operation is listed twice in WSDL. That's easy using a Set. Uploaded complete eclipse project that shows both unique and non-unique results here: https://github.com/sek/wsdlparser

like image 87
Stan Kurdziel Avatar answered Sep 20 '22 20:09

Stan Kurdziel


I use easywsdl.

A place to start

Maven:
<dependency>
  <groupId>org.ow2.easywsdl</groupId>
  <artifactId>easywsdl-wsdl</artifactId>
  <version>2.1</version>
</dependency>


// Read a WSDL 1.1 or 2.0
WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
Description desc = reader.read(new URL("http://file/path/document.wsdl"));
// Endpoints take place in services. 
// Select a service
Service service = desc.getServices().get(0);

// List endpoints
List<Endpoint> endpoints = service.getEndpoints(); 

// Read specific endpoint
//An endpoint has getBinding and then you getInterface from binding and so on
Endpoint specificEndpoint = service.getEndpoint("endpointName");

// Add endpoint to service
service.addEndpoint(specificEndpoint);

// Remove a specific enpoint
service.removeEndpoint("endpointName");

// Create endpoint
Endpoint createdEndpoint = service.createEndpoint();
service.addEndpoint(createdEndpoint);

My sample code:
    try {
        // Read a WSDL 1.1 or 2.0
        WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
        Description desc = reader.read(new URL("file:///C:/your/file/path/sample.wsdl"));
        // Endpoints take place in services. 
        // Select a service
        Service service = desc.getServices().get(0);
        List<Endpoint> endpoints = service.getEndpoints();
        //Gets address of first endpoint
        System.out.println(endpoints.get(0).getAddress());
        //Gets http method
        System.out.println(endpoints.get(0).getBinding().getBindingOperations().get(0).getHttpMethod());
        //Gets input type
        System.out.println(endpoints.get(0).getBinding().getInterface().getOperations().get(0).getInput().getElement().getType().getQName().getLocalPart());

    } catch (WSDLException | IOException | URISyntaxException e1) {
        e1.printStackTrace();
    }
like image 27
Uttam Avatar answered Sep 19 '22 20:09

Uttam