This month, I'll continue my how-to series about using PowerShell's Invoke-WebRequest cmdlet to query online Web services by moving from the newer RESTful-type Web services to the older (but still extant) SOAP-type Web services. The housing market is slowly recovering in the United States, so you might appreciate having easy access to payment information via a Web service that I'll introduce this month!
Let's query a free public SOAP service hosted (and well documented, thankfully) by www.webservice.net. Its Mortgage Web Service (MWS) accepts a loan period in years, interest rate in percent, total house loan amount, and annual taxes and insurance. It then grinds the numbers and returns the total projected monthly payment.
Take a look at MWS's home page, and find the Endpoint heading. Under that is MWS's URI:
http://www.webservicex.net/mortgage.asmx?WSDL
Notice two things. First, the URI has an .asmx extension. That's almost always the extension of a SOAP URI. Second, notice the query string ?WDSL. That is a reference to some XML that allows this Web service to describe itself and its required inputs to the outside world, and what it will provide in return. (That will be important next month, when I use something called a "Web service proxy" to simplify calling this service.)
Below the URI, you'll see GetMortgagePayment. That's the name of the "method" in this Web service. MWS has only one method, but you'll run into many more Web services that have more than one method. Click GetMortgagePayment to reveal an area with the title SOAP 1.1. This area shows how to create an XML file that feeds MWS the inputs that it needs, with the inputs entered as elements in the XML.
The text in that figure is the entirety of the SOAP text that MWS needs, but you needn't put all that in your file, as PowerShell automatically inserts everything up to and including the SOAPAction… line.
To build the SOAP XML file, copy everything from onward, as seen here, into Notepad:
Next, you'll supply values for the five inputs. For example, notice
You'll deliver the query via Invoke-Webrequest, but SOAP requests must normally be POSTed, not GETed. You must also tell Invoke-Webrequest to send the Payments.xml file and, as a side effect of POSTing rather than GETing, you've got to tell Invoke-Webrequest what sort of returned data to expect (text and XML, in this case). This will do it all, storing the result in $Result:
$URI = " http://www.webservicex.net/mortgage.asmx?WSDL"
$result = (iwr $URI –infile payments.xml –contentType "text/xml" –method POST)
SOAP services return their answers in a SOAP-style XML text that you can find in $Result.Content. Take a look at the SOAP XML result by typing
$result.content
You'll see some unformatted XML, and amidst it you'll see your payment amount:
…1222.5429342838054 …
Once again, this means that you'll need PowerShell to pluck out one bit of text (the payment) from a specific element (
$SOAP = $Result.Content
To get a better look at the XML, save $SOAP into a file and open it with almost any Web browser. You'll get a nicely indented view of the XML so that you know exactly what kind of data this service offers. (Just don't use Edge, which seems XML-deaf at this writing.) Then, define the Xpath query that will pluck out the one TotalPayment element, as I described in an earlier article:
$xpathfilter = "//*[local-name()='TotalPayment']"
Next, do the Select-XML to capture the element:
$Element = Select-XML –content $SOAP –xpath $xpathfilter
Type $Element, and you'll just see that there are three attributes: node (which contains your data), path, and pattern. Type $Element.node, and you'll see that there is just one attribute, #text, which contains your payment amount. You can get it all in one line by appending .node and .'#text' —recall that you need the single quotes because although XML understands "#text", PowerShell just sees everything after an octothorpe as a comment:
$Payment = $Element.Node.'#text'
Just think: If everyone had known PowerShell and Invoke-Webrequest between 1999 and 2008, the housing crisis might never have happened! That's neat, but I could live without having to build XML files, and I bet you could too, so don’t miss my coverage of Web service proxies next time!