How To Convert JSON File To XML format In UFT in VBScript way

April 02, 2018

image credit:https://www.pexels.com/photo/
auto-automobile-car-chrome-461824/
So long, we were testing webservices using XM format. Traditional frameworks are written is such a way that it can handle XML request and response.The current framework was working fine until the recent upgradation of few services to JSON. As the request type is JSON. The response also what we get is JSON. In few cases, the input file is XML, but output is pure JSON. Tests are failing due to this format change. The possible solution is to reach out to developer to get an XML response. The developer may or may not agree on this aspect as we are moving forward towards JSON. The another solution is to upgrade our framework to handle JSON response.

To get a solution, I started googling about the topic.There were many solution given but not in VBScript. So it was very tough to handle the JSON format. So I thought to design a parser on my own.
While further searching in stackoverflow , I found a reply from Stephen Quan. he has come up with an excellent lightweight pure VBscript way to parse JSON to XML.
His solution is given below:

Function JSONtoXML(jsonText)
  Dim idx, max, ch, mode, xmldom, xmlelem, xmlchild, name, value

  Set xmldom = CreateObject("Microsoft.XMLDOM")
  xmldom.loadXML "<xml/>"
  Set xmlelem = xmldom.documentElement

  max = Len(jsonText)
  mode = 0
  name = ""
  value = ""
  While idx < max
    idx = idx + 1
    ch = Mid(jsonText, idx, 1)
    Select Case mode
    Case 0 ' Wait for Tag Root
      Select Case ch
      Case "{"
        mode = 1
      End Select
    Case 1 ' Wait for Attribute/Tag Name
      Select Case ch
      Case """"
        name = ""
        mode = 2
      Case "{"
        Set xmlchild = xmldom.createElement("tag")
        xmlelem.appendChild xmlchild
        xmlelem.appendchild xmldom.createTextNode(vbCrLf)
        xmlelem.insertBefore xmldom.createTextNode(vbCrLf), xmlchild
        Set xmlelem = xmlchild
      Case "["
        Set xmlchild = xmldom.createElement("tag")
        xmlelem.appendChild xmlchild
        xmlelem.appendchild xmldom.createTextNode(vbCrLf)
        xmlelem.insertBefore xmldom.createTextNode(vbCrLf), xmlchild
        Set xmlelem = xmlchild
      Case "}"
        Set xmlelem = xmlelem.parentNode
      Case "]"
        Set xmlelem = xmlelem.parentNode
      End Select
    Case 2 ' Get Attribute/Tag Name
      Select Case ch
      Case """"
        mode = 3
      Case Else
        name = name + ch
      End Select
    Case 3 ' Wait for colon
      Select Case ch
      Case ":"
        mode = 4
      End Select
    Case 4 ' Wait for Attribute value or Tag contents
      Select Case ch
      Case "["
        Set xmlchild = xmldom.createElement(name)
        xmlelem.appendChild xmlchild
        xmlelem.appendchild xmldom.createTextNode(vbCrLf)
        xmlelem.insertBefore xmldom.createTextNode(vbCrLf), xmlchild
        Set xmlelem = xmlchild
        name = ""
        mode = 1
      Case "{"
        Set xmlchild = xmldom.createElement(name)
        xmlelem.appendChild xmlchild
        xmlelem.appendchild xmldom.createTextNode(vbCrLf)
        xmlelem.insertBefore xmldom.createTextNode(vbCrLf), xmlchild
        Set xmlelem = xmlchild
        name = ""
        mode = 1
      Case """"
        value = ""
        mode = 5
      Case " "
      Case Chr(9)
      Case Chr(10)
      Case Chr(13)
      Case Else
        value = ch
        mode = 7
      End Select
    Case 5
      Select Case ch
      Case """"
        xmlelem.setAttribute name, value
        mode = 1
      Case "\"
        mode = 6
      Case Else
        value = value + ch
      End Select
    Case 6
      value = value + ch
      mode = 5
    Case 7
      If Instr("}], " & Chr(9) & vbCr & vbLf, ch) = 0 Then
        value = value + ch
      Else
        xmlelem.setAttribute name, value
        mode = 1
        Select Case ch
        Case "}"
          Set xmlelem = xmlelem.parentNode
        Case "]"
          Set xmlelem = xmlelem.parentNode
        End Select
      End If
    End Select
  Wend

  Set JSONtoXML = xmlDom
End Function
His working principle was o walk through JSON String and turn that to Microsoft XML DOM document.From there he used Microsoft XML API including xpath queries to pluck ot any values.This solution was working for a welformatted JSON file. So the modification , I have done further:
Step-1: I made sure the response is stored in a file called Response.JSON from the service.
Step-2: Implement the below code to read the file:

responseFilePath="C:\Test\Response.JSON"
// this is the path from where we need to read the file.
OutputPath="C:\Test\"
// This path is where we will store the output XML file.
Set objFso=CreateObject("Scripting.FileSystemObject")
Set ObjTextFile=objFso.openTextFile(responseFilePath,1)
sContent=ObjTextFile.ReadAll();
// this is to read the whole file at one go.
Step-3:Modify his code

Function JSONtoXML(jsonText,OutputPath)
  Dim idx, max, ch, mode, xmldom, xmlelem, xmlchild, name, value

  Set xmldom = CreateObject("Microsoft.XMLDOM")
  xmldom.loadXML "<xml/>"
  Set xmlelem = xmldom.documentElement

  max = Len(jsonText)
  mode = 0
  name = ""
  value = ""
  While idx < max
    idx = idx + 1
    ch = Mid(jsonText, idx, 1)
    Select Case mode
    Case 0 ' Wait for Tag Root
      Select Case ch
      Case "{"
        mode = 1
      End Select
    Case 1 ' Wait for Attribute/Tag Name
      Select Case ch
      Case """"
        name = ""
        mode = 2
      Case "{"
        Set xmlchild = xmldom.createElement("tag")
        xmlelem.appendChild xmlchild
        xmlelem.appendchild xmldom.createTextNode(vbCrLf)
        xmlelem.insertBefore xmldom.createTextNode(vbCrLf), xmlchild
        Set xmlelem = xmlchild
      Case "["
        Set xmlchild = xmldom.createElement("tag")
        xmlelem.appendChild xmlchild
        xmlelem.appendchild xmldom.createTextNode(vbCrLf)
        xmlelem.insertBefore xmldom.createTextNode(vbCrLf), xmlchild
        Set xmlelem = xmlchild
      Case "}"
        Set xmlelem = xmlelem.parentNode
      Case "]"
        Set xmlelem = xmlelem.parentNode
      End Select
    Case 2 ' Get Attribute/Tag Name
      Select Case ch
      Case """"
        mode = 3
      Case Else
        name = name + ch
      End Select
    Case 3 ' Wait for colon
      Select Case ch
      Case ":"
        mode = 4
      End Select
    Case 4 ' Wait for Attribute value or Tag contents
      Select Case ch
      Case "["
        Set xmlchild = xmldom.createElement(name)
        xmlelem.appendChild xmlchild
        xmlelem.appendchild xmldom.createTextNode(vbCrLf)
        xmlelem.insertBefore xmldom.createTextNode(vbCrLf), xmlchild
        Set xmlelem = xmlchild
        name = ""
        mode = 1
      Case "{"
        Set xmlchild = xmldom.createElement(name)
        xmlelem.appendChild xmlchild
        xmlelem.appendchild xmldom.createTextNode(vbCrLf)
        xmlelem.insertBefore xmldom.createTextNode(vbCrLf), xmlchild
        Set xmlelem = xmlchild
        name = ""
        mode = 1
      Case """"
        value = ""
        mode = 5
      Case " "
      Case Chr(9)
      Case Chr(10)
      Case Chr(13)
      Case Else
        value = ch
        mode = 7
      End Select
    Case 5
      Select Case ch
      Case """"
        xmlelem.setAttribute name, value
        mode = 1
      Case "\"
        mode = 6
      Case Else
        value = value + ch
      End Select
    Case 6
      value = value + ch
      mode = 5
    Case 7
      If Instr("}], " & Chr(9) & vbCr & vbLf, ch) = 0 Then
        value = value + ch
      Else
        xmlelem.setAttribute name, value
        mode = 1
        Select Case ch
        Case "}"
          Set xmlelem = xmlelem.parentNode
        Case "]"
          Set xmlelem = xmlelem.parentNode
        End Select
      End If
    End Select
  Wend

  xmlDom.Save OutputPath&"Response.xml"
End Function

You Might Also Like

0 comments