import javax.xml.soap.*;
import java.util.Iterator;
import java.net.URL;
import java.io.*;

public class Client {

    public static void main(String[] args) {
        try {
            SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection connection = soapConnectionFactory.createConnection();
            SOAPMessage message = prepareMessage();

            System.out.print("\nPrinting the message that is being sent: \n\n");
            message.writeTo(System.out);
            System.out.println("\n\n");

            URL endpoint = new URL("https://opendap.co-ops.nos.noaa.gov/axis/services/Datums");
            SOAPMessage response = connection.call(message, endpoint);
            connection.close();

            /*
            System.out.println("\nPrinting the respone that was recieved: \n\n" );
            response.writeTo(System.out);
             */

            //Uncoment this part if you want the response to be saved locally in an XML file
            /*
            FileOutputStream fout = new FileOutputStream ("SoapResponse.xml");
            response.writeTo(fout);
            fout.close();
             */

            //You can also stores the response as a String
            /*
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.writeTo( out );
            String str = out.toString();  
             */

            System.out.println("\n\nIterating through the response object to get the values:\n\n");
            SOAPBody responseBody = response.getSOAPBody();

            //Checking for errors
            if (responseBody.hasFault()) {
                SOAPFault fault = responseBody.getFault();
                String actor = fault.getFaultActor();
                System.out.println("Fault contains: ");
                System.out.println("Fault code: " + fault.getFaultCodeAsName().getQualifiedName());
                System.out.println("Fault string: " + fault.getFaultString());
                if (actor != null) {
                    System.out.println("Actor: " + actor);
                }
            } else {
                Iterator iterator = responseBody.getChildElements();
                Iterator iterator2 = null;                

                String tagName = null;
                SOAPElement se = null;

                if (iterator.hasNext()) {
                    se = (SOAPElement) iterator.next();
                    iterator = se.getChildElements();
                    while (iterator.hasNext()) {
                        se = (SOAPElement) iterator.next();
                        printMetadata(se);
                        tagName = se.getElementName().getLocalName();
                        if ("datums".equals(tagName) || "MinMaxWL".equals(tagName)) {
                            iterator2 = se.getChildElements();
                            while (iterator2.hasNext()) {
                                se = (SOAPElement) iterator2.next();
                                 printData(se);
                            }
                        }
                    }
                }
            }

        } catch (SOAPException e) {
            System.err.println("ERROR: ******* " + e.toString());
        } catch (IOException io) {
            System.err.println("ERROR: ******* " + io.toString());
        }
    }

    public static SOAPMessage prepareMessage() {
        SOAPMessage message = null;
        try {
            SOAPFactory soapFactory = SOAPFactory.newInstance();

            MessageFactory factory = MessageFactory.newInstance();
            message = factory.createMessage();

            SOAPBody body = message.getSOAPBody();
            Name bodyName = soapFactory.createName("getDatumsAndMetadata", "datums",
                    "https://opendap.co-ops.nos.noaa.gov/axis/webservices/datums/wsdl");
            SOAPBodyElement bodyElement = body.addBodyElement(bodyName);

            //Constructing the body for the request
            Name name = soapFactory.createName("stationId");
            SOAPElement symbol = bodyElement.addChildElement(name);
            symbol.addTextNode("8454000");
            name = soapFactory.createName("epoch");
            symbol = bodyElement.addChildElement(name);
            symbol.addTextNode("A");
            name = soapFactory.createName("unit");
            symbol = bodyElement.addChildElement(name);
            symbol.addTextNode("0");
        } catch (SOAPException e) {
            System.err.println("ERROR: ******* " + e.toString());
        }
        return message;
    }

    public static void printMetadata(SOAPElement se) {
        String tagName = se.getElementName().getLocalName();
        if (tagName != null) {
            if ("stationId".equals(tagName)) {
                System.out.println("Printing Metadata \n");
                System.out.println("Station ID       : " + se.getValue());
            } else if ("stationName".equals(tagName)) {
                System.out.println("station Name     : " + se.getValue());
            } else if ("latitude".equals(tagName)) {
                System.out.println("Latitude         : " + se.getValue());
            } else if ("longitude".equals(tagName)) {
                System.out.println("Longitude        : " + se.getValue());
            } else if ("state".equals(tagName)) {
                System.out.println("State            : " + se.getValue());
            } else if ("dataSource".equals(tagName)) {
                System.out.println("Data Source      : " + se.getValue());
            } else if ("status".equals(tagName)) {
                System.out.println("Status           : " + se.getValue());
            } else if ("epoch".equals(tagName)) {
                System.out.println("Epoch            : " + se.getValue());
            } else if ("unit".equals(tagName)) {
                System.out.println("Unit             : " + se.getValue() + "\n");
            } else if ("elevation".equals(tagName)) {
                System.out.println("Elevation        : " + se.getValue() + "\n");
                System.out.println("Printing the data \n");
            }
        }
    }

    public static void printData(SOAPElement se) {
        String tagName = se.getElementName().getLocalName();
        if (tagName != null) {
            if (tagName.equals("MHHW")) {
                System.out.println("MHHW      : " + se.getValue());
            } else if (tagName.equals("MHW")) {
                System.out.println("MHW       : " + se.getValue());
            } else if (tagName.equals("DTL")) {
                System.out.println("DTL       : " + se.getValue());
            } else if (tagName.equals("MTL")) {
                System.out.println("MTL       : " + se.getValue());
            } else if (tagName.equals("MSL")) {
                System.out.println("MSL       : " + se.getValue());
            } else if (tagName.equals("MLW")) {
                System.out.println("MLW       : " + se.getValue());
            } else if (tagName.equals("MLLW")) {
                System.out.println("MLLW       : " + se.getValue());
            } else if (tagName.equals("GT")) {
                System.out.println("GT        : " + se.getValue());
            } else if (tagName.equals("MN")) {
                System.out.println("MN        : " + se.getValue());
            } else if (tagName.equals("DHQ")) {
                System.out.println("DHQ       : " + se.getValue());
            } else if (tagName.equals("DLQ")) {
                System.out.println("DLQ       : " + se.getValue());
            } else if (tagName.equals("HWI")) {
                System.out.println("HWI       : " + se.getValue());
            } else if (tagName.equals("LWI")) {
                System.out.println("LWI       : " + se.getValue());
            } else if (tagName.equals("NAVD")) {
                System.out.println("NAVD      : " + se.getValue() + "\n");
            } else if (tagName.equals("maxWaterLevel")) {
                System.out.println("Max Water Level   : " + se.getValue());
            } else if (tagName.equals("maxDateTime")) {
                System.out.println("Max Date Time     : " + se.getValue());
            } else if (tagName.equals("minWaterLevel")) {
                System.out.println("Min Water Level   : " + se.getValue());
            } else if (tagName.equals("minDateTime")) {
                System.out.println("Min Date Time     : " + se.getValue() + "\n");
            }
        }
    }
}
/****************************************************
SAMPLE RUN

>java Client

Printing the message that is being sent: 
 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <datums:getDatumsAndMetadata xmlns:datums="https://opendap.co-ops.nos.noaa.gov/axis/webservices/datums/wsdl">
            <stationId>8454000</stationId>
            <epoch>A</epoch>
            <unit>0</unit>
        </datums:getDatumsAndMetadata>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Iterating through the response object to get the values:

Printing Metadata 

Station ID       : 8454000
station Name     : Providence
Latitude         : 41.8071
Longitude        : -71.4012
State            : RI
Data Source      : USDOC/NOAA/NOS/COOPS(Center for Operational Oceanographic Products and Services)
Status           : Accepted
Epoch            : Current
Unit             : Meters
Elevation        : Elevation is on Station Datum. To refer Water Level Heights to a Tidal Datum, apply the desired Datum value

Printing the data 

MHHW      : 2.539
MHW       : 2.464
DTL       : 1.802
MTL       : 1.791
MSL       : 1.749
MLW       : 1.119
MLLW      : 1.064
GT        : 1.476
MN        : 1.346
DHQ       : 0.075
DLQ       : 0.055
HWI       : 0.477
LWI       : 5.921
NAVD      : 1.818

Max Water Level   : 6.401
Max Date Time     : 1938-09-21 00:00
Min Water Level   : -0.03
Min Date Time     : 1959-01-05 21:36

**********************************************************/