Working With XML Files From Scripts

Applies to TestComplete 15.45, last modified on December 01, 2022

You can store various test data in XML files. For example, an XML file can store the name of a control, over which TestComplete will simulate user actions, and input values. You can also use XML files to store data between test runs.

Approaches to Working With XML Files in TestComplete

To work with XML files in TestComplete, you can use the following objects:

  • XML DOM objects. You can use these objects to work with any XML file. Working with these objects requires more efforts and knowledge of XML DOM. However, we suggest that you use these objects to work with XML files.

  • The TestComplete Storages object. You use the methods and properties of this object to write data to and read it from XML files. However, this object works only with XML files created with the Storage.XML method (such files have a specific format, they include sections, subsections and options). For more information on this, see Section Object. If you try to open an XML file that has another format by using the Storage.XML method, an error will occur.

Using XML DOM Objects

To work with arbitrary XML files, you can use XML DOM objects. These objects provide a COM interface to each element and attribute of the XML document. All interactions with XML files are done through Microsoft XML Core Services (MSXML):

  1. To start working with XML files, create a COM object:

    JavaScript

      // If you have MSXML 4:
      var Doc = getActiveXObject("Msxml2.DOMDocument.4.0");
      // If you have MSXML 6:
      var Doc = getActiveXObject("Msxml2.DOMDocument.6.0");

    JScript

      // If you have MSXML 4:
      var Doc = Sys.OleObject("Msxml2.DOMDocument.4.0");
      // If you have MSXML 6:
      var Doc = Sys.OleObject("Msxml2.DOMDocument.6.0");

    Python

    # If you have MSXML 4: 
    Doc = Sys.OleObject["Msxml2.DOMDocument.4.0"]
    # If you have MSXML 6: 
    Doc = Sys.OleObject["Msxml2.DOMDocument.6.0"]

    VBScript

      ' If you have MSXML 4:
      Set Doc = Sys.OleObject("Msxml2.DOMDocument.4.0")
      ' If you have MSXML 6:
      Set Doc = Sys.OleObject("Msxml2.DOMDocument.6.0")

    DelphiScript

    var 
      Doc;
    begin
      ...
      // If you have MSXML 4:
      Doc := Sys.OleObject('Msxml2.DOMDocument.4.0');
      // If you have MSXML 6:
      Doc := Sys.OleObject('Msxml2.DOMDocument.6.0');

    C++Script, C#Script

      // If you have MSXML 4:
      var Doc = Sys["OleObject"]("Msxml2.DOMDocument.4.0");
      // If you have MSXML 6:
      var Doc = Sys["OleObject"]("Msxml2.DOMDocument.6.0");

  2. Load data from a file you want to process:

    JavaScript, JScript

    Doc.load("C:\\Data.xml");

    Python

    Doc.load("C:\\Data.xml")

    VBScript

    Call Doc.load("C:\Data.xml")

    DelphiScript

    Doc.load('C:\Data.xml');

    C++Script, C#Script

    Doc["load"]("C:\\Data.xml");

    Note: When loading XML files with a document type declaration, you may face the "DTD is prohibited" error. If it happens, modify your script and add a string that will disable the ProhibitDTD property of the created COM object:

    JavaScript, JScript

    Doc.setProperty("ProhibitDTD", false);

    Python

    Doc.setProperty("ProhibitDTD",False)

    VBScript

    Call Doc.setProperty("ProhibitDTD", False)

    DelphiScript

    Doc.setProperty('ProhibitDTD', False);

    C++Script, C#Script

    Doc["setProperty"]("ProhibitDTD", false);

  3. After the file is loaded, you can start processing it in a way you need. You can find examples of some of the most common tasks below.

Information on XML DOM Objects

To find more information on XPath expressions and XML DOM objects, as well as on their methods and properties, see the corresponding documentation in the MSDN library:

Examples

In this topic, all examples work with the Data.xml file located in the root folder of the C drive. The file should contain the following code:

Data.xml

<?xml version="1.0"?>
<controls>
    <control id="1">
        <type>TextEdit</type>
        <name>Text1</name>
        <value>My string</value>
    </control>
    <control id="2">
        <type>Button</type>
        <name>Btn1</name>
        <value>OK</value>
    </control>
    <control id="3">
        <type>TextEdit</type>
        <name>Text2</name>
        <value>My string</value>
    </control>
    <control xmlns="CheckBoxes">
        <type>CheckBox</type>
        <name>CheckBox1</name>
        <value>True</value>
    </control>
    <control xmlns="Button2">
        <type>Button</type>
        <name>Btn2</name>
        <value>Cancel</value>
    </control>
</controls>

This file has the root node "controls" that has five subnodes. Each subnode has three nodes: type, name and value. The last two nodes also have a namespace specified.

Example 1: Opening XML Files

The following code shows how to open an XML file and parse it.

JavaScript

function TestXMLDOM()
{
  var Doc, Node, s;
  
  // Create a COM object
  // If you have MSXML 4:
  Doc = getActiveXObject("Msxml2.DOMDocument.4.0");
  // If you have MSXML 6:
  Doc = getActiveXObject("Msxml2.DOMDocument.6.0");

  Doc.async = false;
  
  // Load data from a file
  // We use the file created earlier
  Doc.load("C:\\Data.xml");
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if(Doc.parseError.errorCode != 0)
  {
    s = "Reason:\t" + Doc.parseError.reason + "\n" +
        "Line:\t" + aqConvert.VarToStr(Doc.parseError.line) + "\n" +
        "Pos:\t" + aqConvert.VarToStr(Doc.parseError.linePos) + "\n" +
        "Source:\t" + Doc.parseError.srcText;
    // Post an error to the log and exit
    Log.Error("Cannot parse the document.", s);
    return;
  }
  
  // Obtain the node
  Node = Doc.documentElement;
 
  // Process the node
  ProcessNode(Node);
}

function ProcessNode(ANode)
{
  var FID, Attrs, i, Attr, ChildNodes;
  
  // Create a log folder for each node and activate the folder
  FID = Log.CreateFolder(ANode.nodeName);
  Log.PushLogFolder(FID);

  // If the node value is not null, output it
  if( aqObject.GetVarType(ANode.nodeValue) != 1)
    Log.Message("Value: " + aqConvert.VarToStr(ANode.nodeValue));
       
  // Process the node's attributes
  
  // Exclude helper nodes from processing
  if( ANode.nodeName.charAt(0) != "\#")
  {
    // Obtain the attribute collection and
    // output the attributes to the log
    Attrs = ANode.attributes;
    for(i = 0; i < Attrs.length; i++)
    {
      Attr = Attrs.item(i);
      Log.Message("Attr " + Attr.nodeName + ": " + Attr.nodeValue);
    }
  }
    
  // Obtain the collection of child nodes
  ChildNodes = ANode.childNodes;
  // Processes each node of the collection
  for(i = 0; i < ChildNodes.length; i++)
     ProcessNode(ChildNodes.item(i));
  
  // Close the log folder
  Log.PopLogFolder();
}

JScript

function TestXMLDOM()
{
  var Doc, Node, s;
  
  // Create a COM object
  // If you have MSXML 4:
  Doc = Sys.OleObject("Msxml2.DOMDocument.4.0");
  // If you have MSXML 6:
  Doc = Sys.OleObject("Msxml2.DOMDocument.6.0");

  Doc.async = false;
  
  // Load data from a file
  // We use the file created earlier
  Doc.load("C:\\Data.xml");
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if(Doc.parseError.errorCode != 0)
  {
    s = "Reason:\t" + Doc.parseError.reason + "\n" +
        "Line:\t" + aqConvert.VarToStr(Doc.parseError.line) + "\n" +
        "Pos:\t" + aqConvert.VarToStr(Doc.parseError.linePos) + "\n" +
        "Source:\t" + Doc.parseError.srcText;
    // Post an error to the log and exit
    Log.Error("Cannot parse the document.", s);
    return;
  }
  
  // Obtain the node
  Node = Doc.documentElement;
 
  // Process the node
  ProcessNode(Node);
}

function ProcessNode(ANode)
{
  var FID, Attrs, i, Attr, ChildNodes;
  
  // Create a log folder for each node and activate the folder
  FID = Log.CreateFolder(ANode.nodeName);
  Log.PushLogFolder(FID);

  // If the node value is not null, output it
  if( aqObject.GetVarType(ANode.nodeValue) != 1)
    Log.Message("Value: " + aqConvert.VarToStr(ANode.nodeValue));
       
  // Process the node's attributes
  
  // Exclude helper nodes from processing
  if( ANode.nodeName.charAt(0) != "\#")
  {
    // Obtain the attribute collection and
    // output the attributes to the log
    Attrs = ANode.attributes;
    for(i = 0; i < Attrs.length; i++)
    {
      Attr = Attrs.item(i);
      Log.Message("Attr " + Attr.nodeName + ": " + Attr.nodeValue);
    }
  }
    
  // Obtain the collection of child nodes
  ChildNodes = ANode.childNodes;
  // Processes each node of the collection
  for(i = 0; i < ChildNodes.length; i++)
     ProcessNode(ChildNodes.item(i));
  
  // Close the log folder
  Log.PopLogFolder();
}

Python

def TestXMLDOM(): 
  # Create a COM object 
  # If you have MSXML 4: 
  Doc = Sys.OleObject["Msxml2.DOMDocument.4.0"]
  # If you have MSXML 6: 
  Doc = Sys.OleObject["Msxml2.DOMDocument.6.0"]

  Doc.async = False
  
  # Load data from a file
  # We use the file created earlier
  Doc.load("C:\\Data.xml")
  
  # Report an error, if, for instance, the markup or file structure is invalid 
  if Doc.parseError.errorCode != 0:
    s = "Reason:\t" + Doc.parseError.reason + "\n" + "Line:\t" + aqConvert.VarToStr(Doc.parseError.line) + "\n" + "Pos:\t" + aqConvert.VarToStr(Doc.parseError.linePos) + "\n" + "Source:\t" + Doc.parseError.srcText
    # Post an error to the log and exit
    Log.Error("Cannot parse the document.", s)
    return

  # Obtain the node
  Node = Doc.documentElement
 
  # Process the node
  ProcessNode(Node)

def ProcessNode(ANode):

  # Create a log folder for each node and activate the folder 
  FID = Log.CreateFolder(ANode.nodeName)
  Log.PushLogFolder(FID)

  # If the node value is not null, output it 
  if aqObject.GetVarType(ANode.nodeValue) != 0 and aqObject.GetVarType(ANode.nodeValue) != 1:
    Log.Message("Value: " + aqConvert.VarToStr(ANode.nodeValue))
       
  # Process the node's attributes
  
  # Exclude helper nodes from processing
  if ANode.nodeName[0] != "#":
    # Obtain the attribute collection and 
    # output the attributes to the log
    Attrs = ANode.attributes
    for i in range(Attrs.length):
      Attr = Attrs.item[i]
      Log.Message("Attr " + Attr.nodeName + ": " + Attr.nodeValue)
    
  # Obtain the collection of child nodes
  ChildNodes = ANode.childNodes
  # Processes each node of the collection
  for i in range(ChildNodes.length):
     ProcessNode(ChildNodes.item[i])
  
  # Close the log folder
  Log.PopLogFolder()

VBScript

Sub TestXMLDOM
  ' Create a COM object
  ' If you have MSXML 4:
  Set Doc = Sys.OleObject("Msxml2.DOMDocument.4.0")
  ' If you have MSXML 6:
  Set Doc = Sys.OleObject("Msxml2.DOMDocument.6.0")

  Doc.async = False
  
  ' Load data from a file
  ' We use the file created earlier
  Call Doc.load("C:\Data.xml")
  
  ' Report an error, if, for instance, the markup or file structure is invalid
  If Doc.parseError.errorCode <> 0 Then
    s = "Reason:" + Chr(9) + Doc.parseError.reason + Chr(13) + Chr(10) + _
        "Line:" + Chr(9) + CStr(Doc.parseError.line) + Chr(13) + Chr(10) + _
        "Pos:" + Chr(9) + CStr(Doc.parseError.linePos) + Chr(13) + Chr(10) + _
        "Source:" + Chr(9) + Doc.parseError.srcText
    ' Post an error to the log and exit
    Call Log.Error("Cannot parse the document.", s)
    Exit Sub
  End If
  
  ' Obtain the node
  Set Node = Doc.documentElement
 
  ' Process the node
  Call ProcessNode(Node)
End Sub

Sub ProcessNode(ANode)
  ' Create a log folder for each node and activate the folder
  FID = Log.CreateFolder(ANode.nodeName)
  Log.PushLogFolder FID

  ' If the node value is not null, output it
  If aqObject.GetVarType(ANode.nodeValue) <> 1 Then
    Log.Message "Value: " + ANode.nodeValue
  End If
  
   ' Process the node's attributes
  If Left(ANode.nodeName, 1) <> "#" Then ' Exclude helper nodes from processing
    ' Obtain the attribute collection and
    ' output the attributes to the log
    Set Attrs = ANode.attributes
    For i = 0 To Attrs.length - 1
      Set Attr = Attrs.item(i)
      Log.Message "Attr " + Attr.nodeName + ": " + Attr.nodeValue
    Next
  End If
    
  ' Obtain the collection of child nodes
  Set ChildNodes = ANode.childNodes
  ' Processes each node of the collection
  For i = 0 to ChildNodes.length - 1
     ProcessNode ChildNodes.item(i)
  Next
  
  ' Close the log folder
  Log.PopLogFolder
End Sub

DelphiScript

procedure ProcessNode(ANode : OleVariant); forward;

procedure TestXMLDOM;
var
  Doc, Node, s : OleVariant;
begin
  // Create a COM object
  // If you have MSXML 4:
  Doc := Sys.OleObject('Msxml2.DOMDocument.4.0');
  // If you have MSXML 6:
  Doc := Sys.OleObject('Msxml2.DOMDocument.6.0');

  Doc.async := False;
  
  // Load data from a file
  // We use the file created earlier
  Doc.load('C:\Data.xml');
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if Doc.parseError.errorCode <> 0 then
  begin
    s := 'Reason:' + #9 + Doc.parseError.reason + #13#10 +
         'Line:' + #9 + aqConvert.VarToStr(Doc.parseError.line) + #13#10 +
         'Pos:' + #9 + aqConvert.VarToStr(Doc.parseError.linePos) + #13#10 +
         'Source:' + #9 + Doc.parseError.srcText;
    // Post an error to the log and exit
    Log.Error('Cannot parse the document.', s);
    Exit;
  end;
  
  // Obtain the node
  Node := Doc.documentElement;
 
  // Process the node
  ProcessNode(Node);
end;

procedure ProcessNode(ANode : OleVariant);
var
  FID, s, Attrs, Attr, i, ChildNodes : OleVariant;
begin
  // Create a log folder for each node and activate the folder
  FID := Log.CreateFolder(ANode.nodeName);
  Log.PushLogFolder(FID);

  // If the node value is not nil, output it
  if aqObject.GetVarType(ANode.nodeValue) <> 1 then
    Log.Message('Value: ' + aqConvert.VarToStr(ANode.nodeValue));
  
  
  // Process the node's attributes
  s := Copy(ANode.nodeName, 1, 1);
  if s <> '#' then // Exclude helper nodes from processing
  begin
    // Obtain the attribute collection and
    // output the attributes to the log
    Attrs := ANode.attributes;
    for i := 0 to Attrs.length - 1 do
    begin
      Attr := Attrs.item[i];
      Log.Message('Attr ' + Attr.nodeName + ': ' + Attr.nodeValue);
    end;
  end;
    
  // Obtain the collection of child nodes
  ChildNodes := ANode.childNodes;
  // Processes each node of the collection
  for i := 0 to ChildNodes.length - 1 do
    ProcessNode(ChildNodes.item[i]);
  
  // Close the log folder
  Log.PopLogFolder();
end;

C++Script, C#Script

function TestXMLDOM()
{
  var Doc, Node, s;
  
  // Create a COM object
  // If you have MSXML 4:
  Doc = Sys["OleObject"]("Msxml2.DOMDocument.4.0");
  // If you have MSXML 6:
  Doc = Sys["OleObject"]("Msxml2.DOMDocument.6.0");

  Doc["async"] = false;
  
  // Load data from a file
  // We use the file created earlier
  Doc["load"]("C:\\Data.xml");
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if(Doc["parseError"]["errorCode"] != 0)
  {
    s = "Reason:\t" + Doc["parseError"]["reason"] + "\n" +
        "Line:\t" + aqConvert["VarToStr"](Doc["parseError"]["line"]) + "\n" +
        "Pos:\t" + aqConvert["VarToStr"](Doc["parseError"]["linePos"]) + "\n" +
        "Source:\t" + Doc["parseError"]["srcText"];
    // Post an error to the log and exit
    Log["Error"]("Cannot parse the document.", s);
    return;
  }
  
  // Obtain the node
  Node = Doc["documentElement"];
 
  // Process the node
  ProcessNode(Node);
}

function ProcessNode(ANode)
{
  var FID, Attrs, i, Attr, ChildNodes;
  
  // Create a log folder for each node and activate the folder
  FID = Log["CreateFolder"](ANode["nodeName"]);
  Log["PushLogFolder"](FID);

  // If the node value is not null, output it
  if( aqObject["GetVarType"](ANode["nodeValue"]) != 1)
    Log["Message"]("Value: " + aqConvert["VarToStr"](ANode["nodeValue"]));
       
  // Process the node's attributes
  
  // Exclude helper nodes from processing
  if( ANode["nodeName"]["charAt"](0) != "\#")
  {
    // Obtain the attribute collection and
    // output the attributes to the log
    Attrs = ANode["attributes"];
    for(i = 0; i < Attrs["length"]; i++)
    {
      Attr = Attrs["item"](i);
      Log.Message("Attr " + Attr["nodeName"] + ": " + Attr["nodeValue"]);
    }
  }
    
  // Obtain the collection of child nodes
  ChildNodes = ANode["childNodes"];
  // Processes each node of the collection
  for(i = 0; i < ChildNodes["length"]; i++)
     ProcessNode(ChildNodes["item"](i));
  
  // Close the log folder
  Log["PopLogFolder"]();
}

In this example, the TestXML procedure creates a new XML DOM Document object via COM and loads data from the Data.xml file. When loading, the XML parser validates the document. The script also checks the result of the validation using the parseError object. If the file has been loaded successfully, the test obtains the root node and passes it to the ProcessNode routine for processing.

The ProcessNode routine posts the node’s name and value to the log (if the node does not contain a value, the value is not posted). Then the routine processes the node's attributes and child nodes.

Example 2: Using XPath Expressions to Parse XML Files

To parse XML files with DOM objects, you can also use XPath expressions. This will allow you to easily get a list of needed nodes without parsing the whole document. The following code shows how you can get a collection of nodes and process subnodes.

JavaScript

function TestWithXPath()
{
  var Doc, s, Nodes, ChildNodes, i, Node;
  
  // Create a COM object
  // If you have MSXML 4:
  Doc = getActiveXObject("Msxml2.DOMDocument.4.0");
  // If you have MSXML 6:
  Doc = getActiveXObject("Msxml2.DOMDocument.6.0");

  Doc.async = false;
  
  // Load data from a file
  // We use the file created earlier
  Doc.load("C:\\Data.xml");
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if(Doc.parseError.errorCode != 0)
  {
    s = "Reason:\t" + Doc.parseError.reason + "\n" +
        "Line:\t" + aqConvert.VarToStr(Doc.parseError.line) + "\n" +
        "Pos:\t" + aqConvert.VarToStr(Doc.parseError.linePos) + "\n" +
        "Source:\t" + Doc.parseError.srcText;
    // Post an error to the log and exit
    Log.Error("Cannot parse the document.", s);
    return;
  }
  
  // Use an XPath expression to obtain a list of "control" nodes
  Nodes = Doc.selectNodes("//control");
  
  // Process the node
  for(i = 0; i < Nodes.length; i++)
  {
    // Get the node from the collection of the found nodes
    Node = Nodes.item(i);
    // Get child nodes
    ChildNodes = Node.childNodes;
    // Output two child nodes to the log
    Log.Message(ChildNodes.item(1).text + ": " + ChildNodes.item(2).text);
  }
}

JScript

function TestWithXPath()
{
  var Doc, s, Nodes, ChildNodes, i, Node;
  
  // Create a COM object
  // If you have MSXML 4:
  Doc = Sys.OleObject("Msxml2.DOMDocument.4.0");
  // If you have MSXML 6:
  Doc = Sys.OleObject("Msxml2.DOMDocument.6.0");

  Doc.async = false;
  
  // Load data from a file
  // We use the file created earlier
  Doc.load("C:\\Data.xml");
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if(Doc.parseError.errorCode != 0)
  {
    s = "Reason:\t" + Doc.parseError.reason + "\n" +
        "Line:\t" + aqConvert.VarToStr(Doc.parseError.line) + "\n" +
        "Pos:\t" + aqConvert.VarToStr(Doc.parseError.linePos) + "\n" +
        "Source:\t" + Doc.parseError.srcText;
    // Post an error to the log and exit
    Log.Error("Cannot parse the document.", s);
    return;
  }
  
  // Use an XPath expression to obtain a list of "control" nodes
  Nodes = Doc.selectNodes("//control");
  
  // Process the node
  for(i = 0; i < Nodes.length; i++)
  {
    // Get the node from the collection of the found nodes
    Node = Nodes.item(i);
    // Get child nodes
    ChildNodes = Node.childNodes;
    // Output two child nodes to the log
    Log.Message(ChildNodes.item(1).text + ": " + ChildNodes.item(2).text);
  }
}

Python

def TestWithXPath():

  # Create a COM object 
  # If you have MSXML 4: 
  Doc = Sys.OleObject["Msxml2.DOMDocument.4.0"]
  # If you have MSXML 6: 
  Doc = Sys.OleObject["Msxml2.DOMDocument.6.0"]

  Doc.async = False
  
  # Load data from a file
  # We use the file created earlier
  Doc.load("C:\\Data.xml")
  
  # Report an error, if, for instance, the markup or file structure is invalid 
  if Doc.parseError.errorCode != 0:
    s = "Reason:\t" + Doc.parseError.reason + "\n" + "Line:\t" + aqConvert.VarToStr(Doc.parseError.line) + "\n" + "Pos:\t" + aqConvert.VarToStr(Doc.parseError.linePos) + "\n" + "Source:\t" + Doc.parseError.srcText
    # Post an error to the log and exit
    Log.Error("Cannot parse the document.", s)
    return
  
  # Use an XPath expression to obtain a list of "control" nodes 
  Nodes = Doc.selectNodes("//control")
  
  # Process the node
  for i in range(Nodes.length):
    # Get the node from the collection of the found nodes 
    Node = Nodes.item[i]
    # Get child nodes 
    ChildNodes = Node.childNodes
    # Output two child nodes to the log
    Log.Message(ChildNodes.item[1].text + ": " + ChildNodes.item[2].text)

VBScript

Sub TestWithXPath
  ' Create a COM object
  ' If you have MSXML 4:
  Set Doc = Sys.OleObject("Msxml2.DOMDocument.4.0")
  ' If you have MSXML 6:
  Set Doc = Sys.OleObject("Msxml2.DOMDocument.6.0")

  Doc.async = False
  
  ' Load data from a file
  ' We use the file created earlier
  Call Doc.load("C:\Data.xml")
  
  ' Report an error, if, for instance, the markup or file structure is invalid
  If Doc.parseError.errorCode <> 0 Then
    s = "Reason:" + Chr(9) + Doc.parseError.reason + _
        "Line:" + Chr(9) + CStr(Doc.parseError.line) + Chr(13) + Chr(10) + _
        "Pos:" + Chr(9) + CStr(Doc.parseError.linePos) + Chr(13) + Chr(10) + _
        "Source:" + Chr(9) + Doc.parseError.srcText
    ' Post an error to the log and exit
    Call Log.Error("Cannot parse the document.", s)
    Exit Sub
  End If
  
  ' Use an XPath expression to obtain a list of "control" nodes
  Set Nodes = Doc.selectNodes("//control")
  
  ' Process the node
  For i = 0 to Nodes.length - 1
    ' Get the node from the collection of the found nodes
    Set Node = Nodes.item(i)
    ' Get child nodes
    Set ChildNodes = Node.childNodes
    ' Output two child nodes to the log
    Call Log.Message(ChildNodes.item(1).text + ": " + ChildNodes.item(2).text)
  Next 
End Sub

DelphiScript

procedure TestWithXPath;
var
  Doc, s, Nodes, ChildNodes, i, Node : OleVariant;
begin
  // Create a COM object
  // If you have MSXML 4:
  Doc := Sys.OleObject('Msxml2.DOMDocument.4.0');
  // If you have MSXML 6:
  Doc := Sys.OleObject('Msxml2.DOMDocument.6.0');

  Doc.async := false;
  
  // Load data from a file
  // We use the file created earlier
  Doc.load('C:\Data.xml');
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if Doc.parseError.errorCode <> 0 then
  begin
    s := 'Reason:' + #9 + Doc.parseError.reason + #13#10 +
         'Line:' + #9 + aqConvert.VarToStr(Doc.parseError.line) + #13#10 +
         'Pos:' + #9 + aqConvert.VarToStr(Doc.parseError.linePos) + #13#10 +
         'Source:' + #9 + Doc.parseError.srcText;
    // Post an error to the log and exit
    Log.Error('Cannot parse the document.', s);
    Exit;
  end;
  
  // Use an XPath expression to obtain a list of "control" nodes
  Nodes := Doc.selectNodes('//control');
  
  // Process the node
  for i := 0 to Nodes.length - 1 do
  begin
    // Get the node from the collection of the found nodes
    Node := Nodes.item(i);
    // Get child nodes
    ChildNodes := Node.childNodes;
    // Output two child nodes to the log
    Log.Message(ChildNodes.item(1).text + ': ' + ChildNodes.item(2).text);
  end;
end;

C++Script, C#Script

function TestWithXPath()
{
  var Doc, s, Nodes, ChildNodes, i, Node;
  
  // Create a COM object
  // If you have MSXML 4:
  Doc = Sys["OleObject"]("Msxml2.DOMDocument.4.0");
  // If you have MSXML 6:
  Doc = Sys["OleObject"]("Msxml2.DOMDocument.6.0");

  Doc["async"] = false;
  
  // Load data from a file
  // We use the file created earlier
  Doc["load"]("C:\\Data.xml");
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if(Doc["parseError"]["errorCode"] != 0)
  {
    s = "Reason:\t" + Doc["parseError"]["reason"] + "\n" +
        "Line:\t" + aqConvert["VarToStr"](Doc["parseError"]["line"]) + "\n" +
        "Pos:\t" + aqConvert["VarToStr"](Doc["parseError"]["linePos"]) + "\n" +
        "Source:\t" + Doc["parseError"]["srcText"];
    // Post an error to the log and exit
    Log["Error"]("Cannot parse the document.", s);
    return;
  }
  
  // Use an XPath expression to obtain a list of "control" nodes
  Nodes = Doc["selectNodes"]("//control");
  
  // Process the node
  for(i = 0; i < Nodes["length"]; i++)
  {
    // Get the node from the collection of the found nodes
    Node = Nodes["item"](i);
    // Get child nodes
    ChildNodes = Node["childNodes"];
    // Output two child nodes to the log
    Log["Message"](ChildNodes["item"](1)["text"] + ": " + ChildNodes["item"](2)["text"]);
  }
}

The code above is very similar to the previous example. The only difference is that we call the selectNodes method and pass it an XPath expression. The method returns a collection of the requested objects. Then we parse the collection.

Example 3: Parsing Nodes With Namespaces

The previous examples do not return nodes that have a namespace. The code below shows how to get a node with a namespace and process its child nodes.

JavaScript

function TestWithXPath()
{
  var Doc, s, Nodes, ChildNodes, i, Node;
  
  // Create a COM object
  // If you have MSXML 4:
  Doc = getActiveXObject("Msxml2.DOMDocument.4.0");
  // If you have MSXML 6:
  Doc = getActiveXObject("Msxml2.DOMDocument.6.0");

  Doc.async = false;
  
  // Load data from a file
  // We use the file created earlier
  Doc.load("C:\\Data.xml");
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if(Doc.parseError.errorCode != 0)
  {
    s = "Reason:\t" + Doc.parseError.reason + "\n" +
        "Line:\t" + aqConvert.VarToStr(Doc.parseError.line) + "\n" +
        "Pos:\t" + aqConvert.VarToStr(Doc.parseError.linePos) + "\n" +
        "Source:\t" + Doc.parseError.srcText;
    // Post an error to the log and exit
    Log.Error("Cannot parse the document.", s);
    return;
  }
  
  //Define the namespace of the node   
  Doc.setProperty('SelectionNamespaces', 'xmlns:a="CheckBoxes"');
  
  //Use an XPath expression to obtain a list of "control" nodes with the "Checkboxes" namespace
  Nodes = Doc.selectNodes("//a:control");
  
  // Process the node
  for(i = 0; i < Nodes.length; i++)
  {
    // Get the node from the collection of the found nodes
    Node = Nodes.item(i);
    // Get child nodes
    ChildNodes = Node.childNodes;
    // Output two child nodes to the log
    Log.Message(ChildNodes.item(1).text + ": " + ChildNodes.item(2).text);
  }
}

JScript

function TestWithXPath()
{
  var Doc, s, Nodes, ChildNodes, i, Node;
  
  // Create a COM object
  // If you have MSXML 4:
  Doc = Sys.Ole.Object("Msxml2.DOMDocument.4.0");
  // If you have MSXML 6:
  Doc = Sys.Ole.Object("Msxml2.DOMDocument.6.0");

  Doc.async = false;
  
  // Load data from a file
  // We use the file created earlier
  Doc.load("C:\\Data.xml");
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if(Doc.parseError.errorCode != 0)
  {
    s = "Reason:\t" + Doc.parseError.reason + "\n" +
        "Line:\t" + aqConvert.VarToStr(Doc.parseError.line) + "\n" +
        "Pos:\t" + aqConvert.VarToStr(Doc.parseError.linePos) + "\n" +
        "Source:\t" + Doc.parseError.srcText;
    // Post an error to the log and exit
    Log.Error("Cannot parse the document.", s);
    return;
  }
  
  //Define the namespace of the node   
  Doc.setProperty('SelectionNamespaces', 'xmlns:a="CheckBoxes"');
  
  //Use an XPath expression to obtain a list of "control" nodes with the "Checkboxes" namespace
  Nodes = Doc.selectNodes("//a:control");
  
  // Process the node
  for(i = 0; i < Nodes.length; i++)
  {
    // Get the node from the collection of the found nodes
    Node = Nodes.item(i);
    // Get child nodes
    ChildNodes = Node.childNodes;
    // Output two child nodes to the log
    Log.Message(ChildNodes.item(1).text + ": " + ChildNodes.item(2).text);
  }
}

Python

def TestWithXPath():
 
  # Create a COM object 
  # If you have MSXML 4: 
  Doc = Sys.OleObject["Msxml2.DOMDocument.4.0"]
  # If you have MSXML 6: 
  Doc = Sys.OleObject["Msxml2.DOMDocument.6.0"]

  Doc.async = False
  
  # Load data from a file
  # We use the file created earlier
  Doc.load("C:\\Data.xml")
  
  # Report an error, if, for instance, the markup or file structure is invalid 
  if Doc.parseError.errorCode != 0:
    s = "Reason:\t" + Doc.parseError.reason + "\n" + "Line:\t" + aqConvert.VarToStr(Doc.parseError.line) + "\n" + "Pos:\t" + aqConvert.VarToStr(Doc.parseError.linePos) + "\n" + "Source:\t" + Doc.parseError.srcText
    # Post an error to the log and exit
    Log.Error("Cannot parse the document.", s)
    return
  
  # Define the namespace of the node   
  Doc.setProperty('SelectionNamespaces', 'xmlns:a="CheckBoxes"')
  
  # Use an XPath expression to obtain a list of "control" nodes with the "Checkboxes" namespace 
  Nodes = Doc.selectNodes("//a:control")
  
  # Process the node
  for i in range(Nodes.length):
    # Get the node from the collection of the found nodes 
    Node = Nodes.item(i)
    # Get child nodes 
    ChildNodes = Node.childNodes
    # Output two child nodes to the log
    Log.Message(ChildNodes.item(1).text + ": " + ChildNodes.item(2).text)

VBScript

Sub TestWithXPath
  ' Create a COM object
  ' If you have MSXML 4:
  Set Doc = Sys.OleObject("Msxml2.DOMDocument.4.0")
  ' If you have MSXML 6:
  Set Doc = Sys.OleObject("Msxml2.DOMDocument.6.0")

  Doc.async = False
  
  ' Load data from a file
  ' We use the file created earlier
  Call Doc.load("C:\Data.xml")
  
  ' Report an error, if, for instance, the markup or file structure is invalid
  If Doc.parseError.errorCode <> 0 Then
    s = "Reason:" + Chr(9) + Doc.parseError.reason + _
        "Line:" + Chr(9) + CStr(Doc.parseError.line) + Chr(13) + Chr(10) + _
        "Pos:" + Chr(9) + CStr(Doc.parseError.linePos) + Chr(13) + Chr(10) + _
        "Source:" + Chr(9) + Doc.parseError.srcText
    ' Post an error to the log and exit
    Call Log.Error("Cannot parse the document.", s)
    Exit Sub
  End If
  
  ' Define the namespace of the node
  Doc.setProperty "SelectionNamespaces", "xmlns:a='CheckBoxes'"
  
  ' Use an XPath expression to obtain a list of "control" nodes with the "Checkboxes" namespace
  Set Nodes = Doc.selectNodes("//a:control")
  
  ' Process the node
  For i = 0 to Nodes.length - 1
    ' Get the node from the collection of the found nodes
    Set Node = Nodes.item(i)
    ' Get child nodes
    Set ChildNodes = Node.childNodes
    ' Output two child nodes to the log
    Call Log.Message(ChildNodes.item(1).text + ": " + ChildNodes.item(2).text)
  Next 
End Sub

DelphiScript

procedure TestWithXPath;
var
  Doc, s, Nodes, ChildNodes, i, Node : OleVariant;
begin
  // Create a COM object
  // If you have MSXML 4:
  Doc := Sys.OleObject('Msxml2.DOMDocument.4.0');
  // If you have MSXML 6:
  Doc := Sys.OleObject('Msxml2.DOMDocument.6.0');

  Doc.async := false;
  
  // Load data from a file
  // We use the file created earlier
  Doc.load('C:\Data.xml');
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if Doc.parseError.errorCode <> 0 then
  begin
    s := 'Reason:' + #9 + Doc.parseError.reason + #13#10 +
         'Line:' + #9 + aqConvert.VarToStr(Doc.parseError.line) + #13#10 +
         'Pos:' + #9 + aqConvert.VarToStr(Doc.parseError.linePos) + #13#10 +
         'Source:' + #9 + Doc.parseError.srcText;
    // Post an error to the log and exit
    Log.Error('Cannot parse the document.', s);
    Exit;
  end;
  
  //Define the namespace of the node  
  Doc.setProperty('SelectionNamespaces', 'xmlns:a="CheckBoxes"');
  
  // Use an XPath expression to obtain a list of "control" nodes with the "Checkboxes" namespace
  Nodes := Doc.selectNodes('//a:control');
  
  // Process the node
  for i := 0 to Nodes.length - 1 do
  begin
    // Get the node from the collection of the found nodes
    Node := Nodes.item(i);
    // Get child nodes
    ChildNodes := Node.childNodes;
    // Output two child nodes to the log
    Log.Message(ChildNodes.item(1).text + ': ' + ChildNodes.item(2).text);
  end;
end;

C++Script, C#Script

function TestWithXPath()
{
  var Doc, s, Nodes, ChildNodes, i, Node;
  
  // Create a COM object
  // If you have MSXML 4:
  Doc = Sys["OleObject"]("Msxml2.DOMDocument.4.0");
  // If you have MSXML 6:
  Doc = Sys["OleObject"]("Msxml2.DOMDocument.6.0");

  Doc["async"] = false;
  
  // Load data from a file
  // We use the file created earlier
  Doc["load"]("C:\\Data.xml");
  
  // Report an error, if, for instance, the markup or file structure is invalid
  if(Doc["parseError"]["errorCode"] != 0)
  {
    s = "Reason:\t" + Doc["parseError"]["reason"] + "\n" +
        "Line:\t" + aqConvert["VarToStr"](Doc["parseError"]["line"]) + "\n" +
        "Pos:\t" + aqConvert["VarToStr"](Doc["parseError"]["linePos"]) + "\n" +
        "Source:\t" + Doc["parseError"]["srcText"];
    // Post an error to the log and exit
    Log["Error"]("Cannot parse the document.", s);
    return;
  }
  
  //Define the namespace of the node   
  Doc.setProperty('SelectionNamespaces', 'xmlns:a="CheckBoxes"');
  
  // Use an XPath expression to obtain a list of "control" nodes with the "Checkboxes" namespace
  Nodes = Doc["selectNodes"]("//a:control");
  
  // Process the node
  for(i = 0; i < Nodes["length"]; i++)
  {
    // Get the node from the collection of the found nodes
    Node = Nodes["item"](i);
    // Get child nodes
    ChildNodes = Node["childNodes"];
    // Output two child nodes to the log
    Log["Message"](ChildNodes["item"](1)["text"] + ": " + ChildNodes["item"](2)["text"]);
  }
}

The code above is very similar to the previous examples. In this example, we define the SelectionNamespaces property in the setProperty expression and pass it an XPath expression to process only the node with the specified namespace. Namespaces are case-sensitive.

Using the Storages Object

The code below demonstrates how to use the Storage object’s methods to store values in an XML file and read data from that file:

JavaScript, JScript

function StoragesSaveXML()
{
  var FileSection, Section;
  
  // Create an empty section
  FileSection = Storages.XML("");
  
  // Create a subsection and add options to it
  Section = FileSection.GetSubSection("Section1");
  Section.SetOption("Option1", 1); // Add an integer option
  Section.SetOption("Option2", aqDateTime.Now()); // Add Date/Time option
  Section.SetOption("Option3", "String1"); // Add string option
  
  // Another section and more options
  Section = FileSection.GetSubSection("Section2");
  Section.SetOption("Option1", 2);
  Section.SetOption("Option2", aqDateTime.Now());
  Section.SetOption("Option3", "String2");
  
  // One more section and more options
  Section = FileSection.GetSubSection("Section3");
  Section.SetOption("Option1", 3);
  Section.SetOption("Option2", aqDateTime.Now());
  Section.SetOption("Option3", "String3");
  
  // Save data to an XML file
  FileSection.SaveAs("C:\\Data.xml");
}

function StoragesLoadXML()
{
  var FileSection, Section, i, FID, Option1, Option2, Option3;
  
  // Load data from the XML file created by the previous StoragesSaveXML routine
  FileSection = Storages.XML("C:\\Data.xml");
  
  // Iterate through the sections and process values
  for(i = 0; i < FileSection.SectionCount; i++)
  {
    // Get a section
    Section = FileSection.GetSubSectionByIndex(i);

    // Create a folder ...
    FID = Log.CreateFolder(FileSection.GetSectionName(i));
    Log.PushLogFolder(FID);
    
    // ... and output data to the log
    Option1 = Section.GetOption("Option1", 0);
    Log.Message("Option1: " + aqConvert.VarToStr(Option1));
  
    Option2 = Section.GetOption("Option2", 0);
    Log.Message("Option2: " + aqConvert.VarToStr(Option2));
  
    Option3 = Section.GetOption("Option3", 0);
    Log.Message("Option3: " + aqConvert.VarToStr(Option3));
    
    // Close the folder
    Log.PopLogFolder();
  }
}

Python

def StoragesSaveXML():
  
  # Create an empty section
  FileSection = Storages.XML("")
  
  # Create a subsection and add options to it
  Section = FileSection.GetSubSection("Section1")
  Section.SetOption("Option1", 1) # Add an integer option
  Section.SetOption("Option2", aqDateTime.Now()) # Add Date/Time option
  Section.SetOption("Option3", "String1") # Add string option
  
  # Another section and more options
  Section = FileSection.GetSubSection("Section2")
  Section.SetOption("Option1", 2)
  Section.SetOption("Option2", aqDateTime.Now())
  Section.SetOption("Option3", "String2")
  
  # One more section and more options
  Section = FileSection.GetSubSection("Section3")
  Section.SetOption("Option1", 3)
  Section.SetOption("Option2", aqDateTime.Now())
  Section.SetOption("Option3", "String3")
  
  # Save data to an XML file
  FileSection.SaveAs("C:\\Data.xml")


def StoragesLoadXML():
  
  # Load data from the XML file created by the previous StoragesSaveXML routine
  FileSection = Storages.XML("C:\\Data.xml")
  
  # Iterate through the sections and process values
  for i in range(FileSection.SectionCount) :
    # Get a section
    Section = FileSection.GetSubSectionByIndex(i)

    # Create a folder ...
    FID = Log.CreateFolder(FileSection.GetSectionName(i))
    Log.PushLogFolder(FID)
    
    # ... and output data to the log
    Option1 = Section.GetOption("Option1", 0)
    Log.Message("Option1: " + aqConvert.VarToStr(Option1))
  
    Option2 = Section.GetOption("Option2", 0)
    Log.Message("Option2: " + aqConvert.VarToStr(Option2))
  
    Option3 = Section.GetOption("Option3", 0)
    Log.Message("Option3: " + aqConvert.VarToStr(Option3))
    
    # Close the folder 
    Log.PopLogFolder()

VBScript

Sub StoragesSaveXML
  ' Create an empty section
  Set FileSection = Storages.XML("")
  
  ' Create a subsection and add options to it
  Set Section = FileSection.GetSubSection("Section1")
  Section.SetOption "Option1", 1 ' Add an integer option
  Section.SetOption "Option2", aqDateTime.Now() ' Add Date/Time option
  Section.SetOption "Option3", "String1" ' Add string option
  
  ' Another section and more options
  Set Section = FileSection.GetSubSection("Section2")
  Section.SetOption "Option1", 2
  Section.SetOption "Option2", aqDateTime.Now()
  Section.SetOption "Option3", "String2"
  
  ' One more section and more options
  Set Section = FileSection.GetSubSection("Section3")
  Section.SetOption "Option1", 3
  Section.SetOption "Option2", aqDateTime.Now()
  Section.SetOption "Option3", "String3"
  
  ' Save data to an XML file
  FileSection.SaveAs("C:\Data.xml")
End Sub

Sub StoragesLoadXML
  ' Load data from the XML file created by the previous StoragesSaveXML routine
  Set FileSection = Storages.XML("C:\Data.xml")
  
  ' Iterate through the sections and process values
  For i = 0 to FileSection.SectionCount - 1
    ' Get a section
    Set Section = FileSection.GetSubSectionByIndex(i)

    ' Create a folder ...
    FID = Log.CreateFolder(FileSection.GetSectionName(i))
    Log.PushLogFolder FID
    
    ' ... and output data to the log
    Option1 = Section.GetOption("Option1", 0)
    Call Log.Message("Option1: " + aqConvert.VarToStr(Option1))
  
    Option2 = Section.GetOption("Option2", 0)
    Call Log.Message("Option2: " + aqConvert.VarToStr(Option2))
  
    Option3 = Section.GetOption("Option3", 0)
    Call Log.Message("Option3: " + aqConvert.VarToStr(Option3))
    
    ' Close the folder
    Log.PopLogFolder
  Next
     
End Sub

DelphiScript

procedure StoragesSaveXML();
var
  FileSection, Section : OleVariant;
begin
  // Create an empty section
  FileSection := Storages.XML('');
  
  // Create a subsection and add options to it
  Section := FileSection.GetSubSection('Section1');
  Section.SetOption('Option1', 1); // Add an integer option
  Section.SetOption('Option2', aqDateTime.Now()); // Add Date/Time option
  Section.SetOption('Option3', 'String1'); // Add string option
  
  // Another section and more options
  Section := FileSection.GetSubSection('Section2');
  Section.SetOption('Option1', 2);
  Section.SetOption('Option2', aqDateTime.Now());
  Section.SetOption('Option3', 'String2');
  
  // One more section and more options
  Section := FileSection.GetSubSection('Section3');
  Section.SetOption('Option1', 3);
  Section.SetOption('Option2', aqDateTime.Now());
  Section.SetOption('Option3', 'String3');
  
  // Save data to an XML file
  FileSection.SaveAs('C:\Data.xml');
end;

procedure StoragesLoadXML();
var
  FileSection, Section, i, FID, Option1, Option2, Option3 : OleVariant;
begin
  // Load data from the XML file created by the previous StoragesSaveXML routine
  FileSection := Storages.XML('C:\Data.xml');
  
  // Iterate through the sections and process values
  for i := 0 to FileSection.SectionCount - 1 do 
  begin
    // Get a section
    Section := FileSection.GetSubSectionByIndex(i);

    // Create a folder ...
    FID := Log.CreateFolder(FileSection.GetSectionName(i));
    Log.PushLogFolder(FID);
    
    // ... and output data to the log
    Option1 := Section.GetOption('Option1', 0);
    Log.Message('Option1: ' + aqConvert.VarToStr(Option1));
  
    Option2 := Section.GetOption('Option2', 0);
    Log.Message('Option2: ' + aqConvert.VarToStr(Option2));
  
    Option3 := Section.GetOption('Option3', 0);
    Log.Message('Option3: ' + aqConvert.VarToStr(Option3));
    
    // Close the folder
    Log.PopLogFolder();
  end;
end;

C++Script, C#Script

function StoragesSaveXML()
{
  var FileSection, Section;
  
  // Create an empty section
  FileSection = Storages["XML"]("");
  
  // Create a subsection and add options to it
  Section = FileSection["GetSubSection"]("Section1");
  Section["SetOption"]("Option1", 1); // Add an integer option
  Section["SetOption"]("Option2", aqDateTime["Now"]()); // Add Date/Time option
  Section["SetOption"]("Option3", "String1"); // Add string option
  
  // Another section and more options
  Section = FileSection["GetSubSection"]("Section2");
  Section["SetOption"]("Option1", 2);
  Section["SetOption"]("Option2", aqDateTime["Now"]());
  Section["SetOption"]("Option3", "String2");
  
  // One more section and more options
  Section = FileSection["GetSubSection"]("Section3");
  Section["SetOption"]("Option1", 3);
  Section["SetOption"]("Option2", aqDateTime["Now"]());
  Section["SetOption"]("Option3", "String3");
  
  // Save data to an XML file
  FileSection["SaveAs"]("C:\\Data.xml");
}

function StoragesLoadXML()
{
  var FileSection, Section, i, FID, Option1, Option2, Option3;
  
  // Load data from the XML file created by the previous StoragesSaveXML routine
  FileSection = Storages["XML"]("C:\\Data.xml");
  
  // Iterate through the sections and process values
  for(i = 0; i < FileSection["SectionCount"]; i++)
  {
    // Get a section
    Section = FileSection["GetSubSectionByIndex"](i);

    // Create a folder ...
    FID = Log["CreateFolder"](FileSection["GetSectionName"](i));
    Log["PushLogFolder"](FID);
    
    // ... and output data to the log
    Option1 = Section["GetOption"]("Option1", 0);
    Log["Message"]("Option1: " + aqConvert["VarToStr"](Option1));
  
    Option2 = Section["GetOption"]("Option2", 0);
    Log["Message"]("Option2: " + aqConvert["VarToStr"](Option2));
  
    Option3 = Section["GetOption"]("Option3", 0);
    Log["Message"]("Option3: " + aqConvert["VarToStr"](Option3));
    
    // Close the folder
    Log["PopLogFolder"]();
  }
}

The code above defines sections and options.

Note: If the format of the XML file you try to open with the Storage.XML method differs from the format supported by the Storage object’s methods, an error will occur.

See Also

Script Tests
Storages Object
Working With External Data Sources
About File Checkpoints

Highlight search results