Bookmark and Share

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I thought your script yesterday was pretty cool, but there is a problem with it. Retrieving the weather from a script is awesome; however, I need to know which cities are available. If I want to know the weather in Sydney, Australia (your example), I am all set. I’m sure you can see this coming: I do not live in Sydney and therefore the script is useless. How about displaying a list of available cities so that I can figure out how to use the script?

-- NR

Hey, Scripting Guy! AnswerHello NR,

I am listening to the Travelling Wilburys on my new Zune HD. It is an absolutely gorgeous day outside—deep blue cloudless skies and a temperature of 69 degrees Fahrenheit (20.5 degrees Celsius). I have opened all the windows in my scripting house, and I am reclining in my large leather scripting chair checking the scripting e-mail sent to scripter@microsoft.com on my Windows 7 scripting laptop. I have a fresh pot of scripting English Breakfast tea, lemon grass, and cinnamon stick. It is a perfect way to enjoy the mellow Charlotte, North Carolina, weather after the weeklong deluge gifted to the area by tropical storm Ida. NR, you are right about the practicality of knowing the weather in Sydney, Australia. Whereas I might dream of heading back to Australia, with the realities of the current budget crunch, I probably will not make it back to Australia before 2011. Therefore, I better see if I can check out the weather report for Charlotte, North Carolina.

NR, the Get-InternationalCities.ps1 script uses the globalweather Web service and the GetCitiesByCountry method to return a list of available cities. The complete Get-InternationalCities.ps1 script follows.

Get-InternationalCities.ps1

$country = "united states"
$URI = "http://www.webservicex.net/globalweather.asmx?wsdl"
$Proxy = New-WebServiceProxy -uri $URI -namespace WebServiceProxy
$countries = [xml]$proxy.GetCitiesByCountry($country)
$countries.NewDataSet.Table | Sort-Object -Property city |
Select-Object -Property city

The first thing the Get-InternationalCities.ps1 script does is assign a value for the $country variable. The value of the $country variable is used to retrieve the list of cities. This is shown here:

$country = "united states"

After the country has been set for the script, you need to assign the path to the globalweather Web Service Definition Language (WSDL) to the $URI variable. The WSDL is an XML document that describes the service offering. Because the WSDL string is a Uniform Resource Locator (URL), you can open it directly in Internet Explorer and look for methods and properties described by the WSDL. The following image illustrates this:

Image of methods and properties described by the WSDL


After you assign the path to the $URI variable, you can use the New-WebServiceProxy cmdlet to create a Web service proxy that allows you to connect and to retrieve information from the globalweather Web service. The returned object is a special webserviceproxy object that is created from the Web service that is specified in the $URI variable. The members of the WebServiceProxy.GlobalWeather object are shown here:

   TypeName: WebServiceProxy.GlobalWeather

Name                                 MemberType Definition                                             
----                                 ---------- ----------                                             
Disposed                             Event      System.EventHandler Disposed(System.Object, System.Ev...
GetCitiesByCountryCompleted          Event      WebServiceProxy.GetCitiesByCountryCompletedEventHandl...
GetWeatherCompleted                  Event      WebServiceProxy.GetWeatherCompletedEventHandler GetWe...
Abort                                Method     System.Void Abort()                                    
BeginGetCitiesByCountry              Method     System.IAsyncResult BeginGetCitiesByCountry(string Co...
BeginGetWeather                      Method     System.IAsyncResult BeginGetWeather(string CityName, ...
CancelAsync                          Method     System.Void CancelAsync(System.Object userState)       
CreateObjRef                         Method     System.Runtime.Remoting.ObjRef CreateObjRef(type requ...
Discover                             Method     System.Void Discover()                                 
Dispose                              Method     System.Void Dispose()                                  
EndGetCitiesByCountry                Method     string EndGetCitiesByCountry(System.IAsyncResult asyn...
EndGetWeather                        Method     string EndGetWeather(System.IAsyncResult asyncResult)  
Equals                               Method     bool Equals(System.Object obj)                         
GetCitiesByCountry                   Method     string GetCitiesByCountry(string CountryName)          
GetCitiesByCountryAsync              Method     System.Void GetCitiesByCountryAsync(string CountryNam...
GetHashCode                          Method     int GetHashCode()                                      
GetLifetimeService                   Method     System.Object GetLifetimeService()                     
GetType                              Method     type GetType()                                          
GetWeather                           Method     string GetWeather(string CityName, string CountryName) 
GetWeatherAsync                      Method     System.Void GetWeatherAsync(string CityName, string C...
InitializeLifetimeService            Method     System.Object InitializeLifetimeService()              
ToString                             Method     string ToString()                                      
AllowAutoRedirect                    Property   System.Boolean AllowAutoRedirect {get;set;}            
ClientCertificates                   Property   System.Security.Cryptography.X509Certificates.X509Cer...
ConnectionGroupName                  Property   System.String ConnectionGroupName {get;set;}           
Container                            Property   System.ComponentModel.IContainer Container {get;}      
CookieContainer                      Property   System.Net.CookieContainer CookieContainer {get;set;}  
Credentials                          Property   System.Net.ICredentials Credentials {get;set;}         
EnableDecompression                  Property   System.Boolean EnableDecompression {get;set;}          
PreAuthenticate                      Property   System.Boolean PreAuthenticate {get;set;}              
Proxy                                Property   System.Net.IWebProxy Proxy {get;set;}                  
RequestEncoding                      Property   System.Text.Encoding RequestEncoding {get;set;}        
Site                                 Property   System.ComponentModel.ISite Site {get;set;}            
SoapVersion                          Property   System.Web.Services.Protocols.SoapProtocolVersion Soa...
Timeout                              Property   System.Int32 Timeout {get;set;}                        
UnsafeAuthenticatedConnectionSharing Property   System.Boolean UnsafeAuthenticatedConnectionSharing {...
Url                                  Property   System.String Url {get;set;}                           
UseDefaultCredentials                Property   System.Boolean UseDefaultCredentials {get;set;}        
UserAgent                            Property   System.String UserAgent {get;set;}             

The name webserviceproxy comes from the value we specified for the namespace parameter with the New-WebServiceProxy cmdlet. This is seen here:

$URI = "http://www.webservicex.net/globalweather.asmx?wsdl"
$Proxy = New-WebServiceProxy -uri $URI -namespace WebServiceProxy

The properties of the new Web service proxy are displayed by printing the value stored in the $Proxy variable as shown here:

PS C:\Users\ed.NWTRADERS> $proxy


SoapVersion                          : Default
AllowAutoRedirect                    : False
CookieContainer                      :
ClientCertificates                   : {}
EnableDecompression                  : False
UserAgent                            : Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protoco
                                       l 2.0.50727.4927)
Proxy                                :
UnsafeAuthenticatedConnectionSharing : False
Credentials                          :
UseDefaultCredentials                : False
ConnectionGroupName                  :
PreAuthenticate                      : False
Url                                  : http://www.webservicex.net/globalweather.asmx
RequestEncoding                      :
Timeout                              : 100000
Site                                 :
Container                            :

Once the WebServiceProxy.GlobalWeather object is created, the GetCitiesByCountry method is called. The Get-Member cmdlet can be used to provide a clue to the input required by the GetCitiesByCountry method (although it would seem rather obvious that the method wants a string that represents the country to query). This is shown here:

PS C:\Users\ed.NWTRADERS> $Proxy | Get-Member -Name GetCitiesByCountry


   TypeName: WebServiceProxy.GlobalWeather

Name               MemberType Definition                                  
----               ---------- ----------                                   
GetCitiesByCountry Method     string GetCitiesByCountry(string CountryName)

The data that is returned by the GetCitiesByCountry method is in the form of a data set with tables that represent each city/country combination. This is seen here:

PS C:\Users\ed.NWTRADERS> $Proxy.GetCitiesByCountry("mexico")
<NewDataSet>
  <Table>
    <Country>Mexico</Country>
    <City>Acapulco / G. Alvarez</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Aerop. Internacional Monterrey, N. L.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Aguascalientes, Ags.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Bahias De Huatulco</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Cuernavaca, Mor.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Ciudad Del Carmen</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Culiacan, Sin.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Chetumal, Q. Roo</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Santa Rosalia, B. C. S.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Campeche, Camp.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Ciudad Juarez International</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Chihuahua International Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Ciudad Victoria Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Cozumel Civ / Mil</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Durango Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Tepic, Nay.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Don Miguel / Guadalaj</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Guaymas International Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Hermosillo, Son.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Colima</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Saltillo, Coah.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Los Mochis Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Del Bajio / Leon</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>La Paz International Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Loreto, B. C. S.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Matamoros International</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Aerop. Internacional Merida, Yuc</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Mexicali International Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Morelia New</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Minatitlan</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Monclova, Coah.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Mexico City / Licenci</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Monterrey / Gen Maria</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Mazatlan / G. Buelna</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Nuevo Laredo International</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Oaxaca / Xoxocotlan</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Puebla, Pue.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Piedras Negras, Coah.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Uruapan / Gen Rayon</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Puerto Vallarta / Lic</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Puerto Escondido</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Queretaro, Qro.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Reynosa International Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>San Jose Del Cabo</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>San Luis Potosi, S. L. P.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Torreon, Coah.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Tuxtla Gutierrez, Chis.</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Tijuana International Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Tulancingo</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Tampico / Gen Fj Mina</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Toluca / Jose Maria</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Tapachula</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Cancun International Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Villahermosa</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Gen. Heriberto Jara</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Zacatecas Airport</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Ixtapa-Zihuatanejo</City>
  </Table>
  <Table>
    <Country>Mexico</Country>
    <City>Manzanillo International</City>
  </Table>
</NewDataSet>

Because of the way the list of cities returns, it is necessary to retrieve the tables that contain the data. The tables are pipelined to the Sort-Object cmdlet where the cities are sorted in alphabetical order. The cities are then selected by using the Select-Object cmdlet. This is shown here:

$countries = [xml]$proxy.GetCitiesByCountry($country)

$countries.NewDataSet.Table | Sort-Object -Property city |

Select-Object -Property city

When the Get-InternationalCities.ps1 script runs inside the Windows PowerShell ISE, the following results are seen:

Image of results of running the script

 

Well, NR, as you can see, XML provides a great way to organize data and to easily retrieve properties of objects. Join us tomorrow as XML Week continues.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
 

Ed Wilson and Craig Liebendorfer, Scripting Guys