 function SOAPClient()
{
    var m_serviceurl;
    var m_servicenamespace = "";
    var m_methodname;    
    var m_parameters = new Array();

    this.setServiceUrl = function(val)
    {
        m_serviceurl = val;
    }

    this.setServiceNamespace = function(val)
    {
        m_servicenamespace = val;
    }
    
    this.setMethodName = function(val)
    {
        m_methodname = val;
    }

    this.addParameter = function(pname, pval)
    {
        m_parameters[pname] = pval;
    }
}

 this.call = function()
{
    // load WSDL
    m_wsdl = Server.CreateObject("Microsoft.XMLDOM") ;
    m_wsdl.load(m_serviceurl + "?wsdl");            
        
    // build SOAP request
    var sXml =
        "<?xml version=\"1.0\" ?>" +
        "<soap:Envelope " +
        "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
        "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
        "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
        "<soap:Body>" +
        "<" + m_methodname + " xmlns=\"" + m_servicenamespace + "\">";
    for(var i in m_parameters)
        sXml += "<" + i + ">" + m_parameters[i] + "</" + i + ">";
    sXml += "</" + m_methodname + "></soap:Body></soap:Envelope>";
    var xmlHTTP = Server.CreateObject("Msxml2.XMLHTTP");
    xmlHTTP.Open("Post", m_serviceurl, false);
    xmlHTTP.setRequestHeader("SOAPAction", m_servicenamespace + "/" + m_methodname);
    xmlHTTP.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    xmlHTTP.Send(sXml);
    
    // set raw xml
    m_rawxml = xmlHTTP.responseXML.xml + "";
    
    // .NET way - the only way :-)
    var nd = xmlHTTP.responseXML.selectSingleNode("//" + m_methodname + "Result");
    if(nd == null)
    {
        if(xmlHTTP.responseXML.selectSingleNode("//faultcode/text()"))
            throw new Error(500, xmlHTTP.responseXML.selectSingleNode("//faultcode/text()").nodeValue + " - " + xmlHTTP.responseXML.selectSingleNode("//faultstring/text()").nodeValue);
        else
            return null;
    }
    return this.soapresult2object(nd);
}

 this.soapresult2object = function(node)
{
    return this.node2object(node);
}

this.node2object = function(node)
{    
    // null node
    if(node == null)
        return null;
    // text node
    if(node.nodeType == 3 || node.nodeType == 4)
        return this.extractValue(node);

    // leaf node
    if (node.hasChildNodes() && node.childNodes.length==1 && (node.firstChild.nodeType == 3 || node.firstChild.nodeType == 4))
        return this.node2object(node.firstChild);
    var isarray = false;
    var el = m_wsdl.selectSingleNode("//s:element[@name='" + node.nodeName + "']");
    isarray = (el!=null && el.attributes.getNamedItem("type")!=null && (el.attributes.getNamedItem("type").nodeValue + "").toLowerCase().indexOf("arrayof") != -1);

    // object node
    if(!isarray)
    {
        var obj = null;
        if(node.hasChildNodes())
            obj = new Object();
        for(var i = 0; i < node.childNodes.length; i++)
        {
            var p = this.node2object(node.childNodes[i]);
            obj[node.childNodes[i].nodeName] = p;
        }
        return obj;
    }

    // list node
    else
    {
        // create node ref
        var l = new Array();
        for(var i = 0; i < node.childNodes.length; i++)
        {
            var cn = node.childNodes[i];
            l[l.length] = this.node2object(cn);
        }
        return l;
    }
    return null;
}

 this.extractValue = function(node)
{
    var value = node.nodeValue;
    var el = m_wsdl.selectSingleNode("//s:element[@name='" + node.parentNode.nodeName + "']");
    var type = (el != null && el.attributes.getNamedItem("type") != null) ? (el.attributes.getNamedItem("type").nodeValue + "").toLowerCase() : null;
    switch(type)
    {
        default:
        case "s:string":            
        {
            return (value != null) ? value + "" : "";
        }
        case "s:boolean":
        {
            return value+"" == "true";
        }
        case "s:int":
        case "s:long":
        {
            return (value != null) ? parseInt(value + "", 10) : 0;
        }
        case "s:double":
        {
            return (value != null) ? parseFloat(value + "") : 0;
        }
        case "s:datetime":
        {
            if(value == null)
                return null;
            else
            {
                value = value + "";
                value = value.substring(0, value.lastIndexOf("."));
                value = value.replace(/T/gi," ");
                value = value.replace(/-/gi,"/");
                var d = new Date();
                d.setTime(Date.parse(value));                                        
                return d;                
            }
        }
    }        
}
