2

I have the following code, which used to work perfectly, But now for somes reason, doesn't.

The XML I am reading is located at: https://forex.boi.org.il/currency.xml

The following code should parse the XMl and then save the USD/ILS exchange rate. As I say, it doesnt anymore, and I cant figure out whats wrong.

forexURL = "https://forex.boi.org.il/currency.xml"

getUSDRate = 0 
MyRate = 0 

Set xmlObj = Server.CreateObject("MSXML2.FreeThreadedDOMDocument")
xmlObj.async = False
xmlObj.setProperty "ServerHTTPRequest", True
xmlObj.Load(forexURL)
Set xmlList = xmlObj.getElementsByTagName("CURRENCY")
Set xmlObj = Nothing
x = 1
For Each xmlItem In xmlList

    response.write "<p>" &  xmlItem.childNodes(0).text
    response.write "<p>" &    xmlItem.childNodes(1).text
    response.write "<p>" &   xmlItem.childNodes(2).text
    response.write "<p>" &   xmlItem.childNodes(3).text
    response.write "<p>" &   xmlItem.childNodes(4).text
    response.write "<p>" &   xmlItem.childNodes(5).text
    response.write "<p>___________________<br />" & x & "</p>"

    if xmlItem.childNodes(2).text = "USD" then 
        MyRate = xmlItem.childNodes(4).text
        exit for
    end if 

    x = x +1

Next
Set xmlList = Nothing
3
  • "Doesn't work" is not an error description. You need to do a better job in analyzing the problem. Commented Apr 26, 2015 at 12:25
  • I guess you are right. This loop For Each xmlItem In xmlList doesn't event execute once. meaning it cannot find the CURRENCY tag. But it IS there Commented Apr 26, 2015 at 12:34
  • You don't do any error checking after you load the XML document. You are supposed to check the parseError property after an attempted load operation. Commented Apr 26, 2015 at 13:00

2 Answers 2

3

I suspect (wild guess ahead) changes to the way SSL is handled on the server side as the cause of your trouble. Maybe they disabled older, more insecure ciphers in response to recent SSL bugs.

Like @John notes - when you change from MSXML2.FreeThreadedDOMDocument (which loads version MSXML2 version 3) to explicitly load the more modern version 6 (MSXML2.FreeThreadedDOMDocument.6.0) then the download of the document succeeds.

That being said I've made a few changes to your code, mostly to be more readable and make it fail visibly when the document load fails for some reason.

Note

  • the use of XPath
  • a helper function GetText() in place of blindly indexing into child nodes
  • the parseError check to make LoadXmlDocument fail non-silently

.

Option Explicit

Dim usdRate, x, currencies, curr

Set currencies = LoadXmlDocument("https://forex.boi.org.il/currency.xml")
usdRate = GetText(currencies, "//CURRENCY[CURRENCYCODE = 'USD']/RATE")

x = 1
For Each curr In currencies.getElementsByTagName("CURRENCY")
    Response.Write "<p>" & GetText(curr, "NAME") & "</p>"
    Response.Write "<p>" & GetText(curr, "UNIT") & "</p>"
    Response.Write "<p>" & GetText(curr, "CURRENCYCODE") & "</p>"
    Response.Write "<p>" & GetText(curr, "COUNTRY") & "</p>"
    Response.Write "<p>" & GetText(curr, "RATE") & "</p>"
    Response.Write "<p>" & GetText(curr, "CHANGE") & "</p>"
    Response.Write "<p>___________________<br />" & x & "</p>"
    x = x + 1
Next
' ----------------------------------------------------------------------

' loads an XML document from a URL and returns it
Function LoadXmlDocument(url)
    Set LoadXmlDocument = CreateObject("MSXML2.FreeThreadedDOMDocument.6.0")
    LoadXmlDocument.async = False
    LoadXmlDocument.setProperty "ServerHTTPRequest", True
    LoadXmlDocument.setProperty "SelectionLanguage", "XPath"
    LoadXmlDocument.Load url
    If LoadXmlDocument.parseError <> 0 Then
        Err.Raise vbObjectError + 1, _
            "LoadXmlDocument", _
            "Cannot load " & url & " (" & LoadXmlDocument.parseError.reason & ")"
    End If
End Function

' finds the first node that matches the XPath and returns its text value
Function GetText(context, xpath)
    Dim node
    Set node = context.selectSingleNode(xpath)
    If node Is Nothing Then
        GetText = vbEmpty
    Else
        GetText = node.text
    End If
End Function
Sign up to request clarification or add additional context in comments.

3 Comments

i have been using this successfully since your answer. today i start getting an error: msxml6.dll error '80070005', Access is denied. - referring to the line LoadXmlDocument.Load url. I am guessing its a server permission error, but is there a way to make this code even more error friendly? Thanks
@kneidels The "Access is denied" may be caused by the remote server returning HTTP 401. When the server returns invalid XML, you will also get an error, two lines later. Bottom line is: LoadXmlDocument() can fail. Use On Error Resume Next when you call it and handle the error appropriately. Don't forget to set On Error Goto 0 immediately afterwards. Read blogs.msdn.com/b/ericlippert/archive/2004/08/19/… for an in-depth description of VBS error handling.
thank you. From your experience, if I can load the xml in a browser, but get the error via msxml - does this indicate a problem with the xml file, or the xml component?
3

I just tried this on my machine. Try replacing

Server.CreateObject("MSXML2.FreeThreadedDOMDocument")

with

Server.CreateObject("Msxml2.DomDocument.6.0")

Edit

Server.CreateObject("MSXML2.FreeThreadedDOMDocument.6.0") 

also seems to work

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.