Example Scripts for XML Queries

This topic provides guidelines and sample scripts that can be run to illustrate XML Queries.

This topic includes:

Query string expressions

To comply with the XML parser engine follow these guidelines:

  • If your nodes include namespaces, you must include them in the XPath query expression.

  • If your XPath includes nodes with the default namespace, you must use the wildcard notation "*". For details, see Default Namespaces and the example below.

Full node name example

The following example shows a query expression for a node that uses a namespace. It includes the full name of each node with its namespace.

Copy code
char *xml_namespace =
    "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\">"
        "<s:Header>"
            "<a:Action s:mustUnderstand=\"1\">http://tempuri.org/ICalculator/AddResponse</a:Action>"
            "<a:RelatesTo>urn:uuid:d8200b8b-90dc-4dcb-8ebc-d4aa5eaa65b3</a:RelatesTo>"
        "</s:Header>"
        "<s:Body>"
            "<r:AddResponse xmlns:r=\"http://tempuri.org/\">"
                "<r:AddResult>75</r:AddResult>"
            "</r:AddResponse>"
        "</s:Body>"
    "</s:Envelope>";

Action()
{
    // Find adding result from xml_namespace string
    int find_cnt;    
    lr_save_string(xml_namespace, "XML_Namespace");
    
    find_cnt = lr_xml_find("XML={XML_Namespace}",
        "Query=/s:Envelope/s:Body/r:AddResponse/r:AddResult", 
        "Value=75", 
        LAST );    
    lr_output_message("Found Adding Result: %d", find_cnt);

 

Default namespaces

If you define a default namespace, make sure to use the wildcard (*) in the expression. For example:

Copy code
char *xml_default_namespace =
    "<acme_org xmlns=\"http://www.w3.org/1999/xhtml\">"
        "<employee level=\"manager\">John Smith"
            "<cubicle>227</cubicle>"
        "</employee>"
    "</acme_org>";

Action()
{
    // Extract Employ fragment from xml_default_namespace
    lr_save_string(xml_default_namespace, "XML_Default_Namespace");

    lr_xml_extract("XML={XML_Default_Namespace}",
          "XMLFragmentParam=Result", 
          "Query=/*[local-name()\='acme_org']/*[local-name()\='employee']",
          LAST );
    lr_output_message(lr_eval_string("Employee extracted: {Result}"));

    return 0;
}

Query expressions for a default namespace that appear in older Vuser scripts might not include the wildcard (*), and will therefore cause the script to fail on replay. You can convert these query expressions to the updated format that includes the wildcard (*). To convert a query expression, in VuGen, right-click the query expression in the script and select Xpath Convert from the context menu.

Run the examples

This section describes how to run the samples and view the results.

To run the examples:

  • Open VuGen

  • From the main menu choose File > New

  • Choose Web Services Vuser from the Protocol Selection. Click OK.

  • Click on the "Action" action in the left-hand frame. The Action page appears.

  • Copy the sample script and paste into the Action page, overwriting the code.

  • To see the results of the queries (the ResultParam value) select Vuser > RunTime Settings and navigate to Log > Log Options > Extended Log and Parameter Substitution. The value will appear in VuGen's Execution Log window.

  • Run the Vuser

Example 1 - Executing queries

This example demonstrates queries using lr_xml_get_values.

The function lr_xml_get_values executes queries on the string xml_input. The results of each query are stored in the parameter Result.

#include "as_web.h"

/* The XML Data */
char *xml_input=
"<acme_org>"
     " <accounts_dept>"
          "<employee>"
               " <name>Kevin Sharp</name>"
               "<cubicle>227</cubicle>"
               "<extension>2145</extension>"
          "</employee>"
     "</accounts_dept>"
     "<engineering_dept>"
          "<employee>"
               "<name>John Smith</name>"
               "<cubicle>372</cubicle>"
               "<extension>2970</extension>"
          "</employee>"
          "<employee level=\"manager\">"
               "<name>Sue Jones</name>"
               "<extension>2375</extension>"
          "</employee>"
     "</engineering_dept>"
"</acme_org>";

Action() {

    int query_number = 1;

// Save data as parameter

    lr_save_string(xml_input, "XML_Input_Param");

    /* Query 1: Find the first employee's name

        (To find the names of all employees

        see Multiple Query Matching)    */

    lr_xml_get_values("XML={XML_Input_Param}",

        "ValueParam=Result",

        "Query=/acme_org/*/employee/name",

        LAST );

    /* Query 2: Find the first extension number one

        or more levels deep */

    lr_xml_get_values("XML={XML_Input_Param}",

        "ValueParam=Result",

        "Query=//extension",

        LAST );

    /* Query 3: Find the name of the manager

        of the engineering department. */

    lr_xml_get_values("XML={XML_Input_Param}",

        "ValueParam=Result",

"Query=/acme_org/engineering_dept/employee[@level=\"manager\"]/name",

        LAST );

    /* Query 4: Find the name of an employee

    whose extension number is 2970 */

    lr_xml_get_values("XML={XML_Input_Param}",

        "ValueParam=Result",

        "Query=/acme_org/*/employee[extension=\"2970\"]/name",

        LAST );

    return 0;

}

Example: Output from Execution Log Window:
Action.c(33): Saving Parameter "Result = Kevin Sharp"
Action.c(33): "lr_xml_get_values" was successful, 1 match processed
Action.c(37): Saving Parameter "Result = 2145"
Action.c(37): "lr_xml_get_values" was successful, 1 match processed
Action.c(41): Saving Parameter "Result = Sue Jones"
Action.c(41): "lr_xml_get_values" was successful, 1 match processed
Action.c(46): Saving Parameter "Result = John Smith"
Action.c(46): "lr_xml_get_values" was successful, 1 match processed

Example 2 - Examples of common actions

This example demonstrates a wide variety of XML functions and expressions.

To run this example, paste the example into the Action section of a Web Services Vuser script.

Under Deleting elements, there is an example of how to Delete element by a specific attribute value and Delete the first Sign attribute.

Under Replacing and inserting elements, there are samples to show how to Replace all "sign" attributes with an XML fragment, Replace all "sign" attributes with a parameter set, Insert an attribute to the root, and Insert a child in all elements using a parameter.

There is one example of how to Get a fragment.

Under Verify the presence of values in the XML string, you can see Finding the first occurrence, Try to find a partial string, Finding a partial string with regular expressions, Finding a complete string that is not the first occurrence, and Specifying the occurrence

Under Value related functions, there is an example of how to Get attribute values and Set attribute values.

#include "as_web.h"

/*

Example XML segment is stored in buffer pxml

*/

char* pxml =

     "<abc>"

         "<employee>"

             "<name>Thomas Bertram</name>"

             "<cubicle sign=\"Amateur Theater Club\">"

                "227</cubicle>"

             "<extension>2145</extension>"

             "<manager>"

                 "<name>Lady Maria Bertram</name>"

                 "<extension>2375</extension>"

                 "<extension>0</extension>"

             "</manager>"

         "</employee>"

         "<employee>"

             "<name>Henry Crawford</name>"

             "<cubicle sign=\"Fidelity\">227</cubicle>"

             "<extension>2794</extension>"

             "<manager>"

                 "<name>Admiral Crawford</name>"

                 "<extension>2309</extension>"

                 "<extension>0</extension>"

             "</manager>"

         "</employee>"

         "<employee>"

             "<name>Fanny Price</name>"

             "<cubicle sign=\"Marry my cousin\""

                " test=\"test attrib value\">666</cubicle>"

             "<manager>"

                 "<name>Edmund Bertram</name>"

                 "<extension>2391</extension>"

                 "<extension>0</extension>"

             "</manager>"

         "</employee>"

     "</abc>";

Action()

{

int find_cnt;

// save XML string into parameter

lr_save_string( pxml, "ParamXml" );

    /*

     Deleting elements

    */

    /*Back to top

    Delete element by a specific attribute value

    */

lr_xml_delete("Xml={ParamXml}",

        "Query=//cubicle[@sign=\"Fidelity\"]",

        "ResultParam=Result",

        LAST

);

//Action.c(59): "lr_xml_delete" was successful, 1 match processed

/* Delete by specific Sign value:

***********

Input:

    ...

    "<employee>"

         "<name>Henry Crawford</name>"

         "<cubicle sign=\"Fidelity\">227</cubicle>"

         "<extension>2794</extension>"

        ...

     "</employee>"

Output:

    Note that Henry's cubicle has been deleted

...

<employee><name>Henry Crawford</name> <extension>2794</extension>

...

</employee>    *****

*/

    /* Back to top

    Delete the first "Sign" attribute

    */

lr_xml_delete("Xml={ParamXml}",

        "Query=//cubicle/@sign",

        "ResultParam=Result",

        "SelectAll=yes",

        LAST

);

//Action.c(75): "lr_xml_delete" was successful, 3 matches processed

/* Delete First Sign :

    ***********

Input:

"<abc>"

         "<employee>"

         "<name>Thomas Bertram</name>"

         "<cubicle sign=\"Amateur Theater Club\">"

            "227</cubicle>"

         "<extension>2145</extension>"

Output:

    Note that Sir Thomas's cubicle no longer has a sign.

<abc> <employee> <name>Thomas Bertram</name> <cubicle>227</cubicle> <extension>2145</extension>

...

    *****

*/

    /* Back to top

    Replacing and inserting elements

    */

    /*

    Replace all "sign" attributes with an XML fragment

    */

lr_xml_replace( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "ResultParam=Result",

    "XmlFragment="

        "NewSign=\"Marry\" NewSign1=\"test\"",

        "SelectAll=yes",

    LAST

);

//Action.c(100): "lr_xml_replace" was successful, 3 matches processed

lr_message(lr_eval_string

    ("/* Replace sign elements:\n***********\n{Result}\n******/"));

/* Replace sign elements:

***********

<abc> <employee> <name>Thomas Bertram</name> <cubicle NewSign="Marry&quot; NewSign1=&quot;test">227</cubicle> <extension>2145</extension> <manager> <name>Lady Maria Bertram</name> <extension>2375</extension> <extension>0</extension> </manager> </employee> <employee> <name>Henry Crawford</name> <cubicle NewSign="Marry&quot; NewSign1=&quot;test">227</cubicle> <extension>2794</extension> <manager> <name>Admiral Crawford</name> <extension>2309</extension> <extension>0</extension> </manager> </employee> <employee> <name>Fanny Price</name> <cubicle NewSign="Marry&quot; NewSign1=&quot;test" test="test attrib value">666</cubicle> <manager> <name>Edmund Bertram</name> <extension>2391</extension> <extension>0</extension> </manager> </employee> </abc>

*****

*/

    /*Back to top

    Replace all sign attributes with a parameter set

    */

lr_save_string

    ( "sign= \"The First New Sign\"", "NewSign_1" );

lr_save_string

    ( "sign= \"The Second New Sign\"", "NewSign_2" );

lr_save_string

    ( "sign= \"The Third New Sign\"", "NewSign_3" );

lr_xml_replace( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "ResultParam=Result",

    "XmlFragmentParam=NewSign",

    "SelectAll=yes",

    LAST

);

lr_message(lr_eval_string

    ("/* Replace sign attributes:\n***********\n{Result}\n*****\n*/"));

/* Replace sign attributes:

***********

<abc> <employee> <name>Thomas Bertram</name> <cubicle sign="The First New Sign">227</cubicle> <extension>2145</extension> <manager> <name>Lady Maria Bertram</name> <extension>2375</extension> <extension>0</extension> </manager> </employee> <employee> <name>Henry Crawford</name> <cubicle sign="The Second New Sign">227</cubicle> <extension>2794</extension> <manager> <name>Admiral Crawford</name> <extension>2309</extension> <extension>0</extension> </manager> </employee> <employee> <name>Fanny Price</name> <cubicle test="test attrib value" sign="The Third New Sign">666</cubicle> <manager> <name>Edmund Bertram</name> <extension>2391</extension> <extension>0</extension> </manager> </employee> </abc>

*****

*/

    /*Back to top

     Insert an attribute to the root

"abc" is the root, so the insertion will be outside all the child elements

    */

lr_xml_insert("Xml={ParamXml}",

    "Query=/abc",

    "ResultParam=Result",

    "Position=attribute",

    "XmlFragment=typeAttr=\"good\"",

    LAST

);

//Action.c(118): "lr_xml_insert" was successful, 1 match processed

lr_message(lr_eval_string

    ("/* Insert root attribute:\n***********\n{Result}\n*****\n*"));

/* Insert root attribute:

***********

<abc> <employee> <name>Thomas Bertram</name> <cubicle sign= ... <employee> <name>Fanny Price</name> ... </employee>typeAttr="good"</abc>

*****

*/

    /* Back to top

    Insert a child in all elements using a parameter

        Only one parameter, ParamComputer_2, is defined.

        For the other undefined elements, "{ParamComputer_n}" is

        inserted.

        */

lr_save_string

    ("<computer>ferrari</computer>",

    "ParamComputer_2");

lr_xml_insert("Xml={ParamXml}",

    "Query=//employee/manager",

    "ResultParam=Result",

    "XmlFragmentParam=ParamComputer",

    "SelectAll=yes",

    "Position=child",

    LAST

);

//Action.c(140): "lr_xml_insert" was successful, 3 matches processed

lr_message(lr_eval_string

    ("/* Parameter insertion:\n***********\n{Result}\n*****\n*/"));

/* Parameter insertion:

***********

<abc> <employee> <name>Thomas Bertram</name> <cubicle sign="Amateur Theater Club">227</cubicle> <extension> 2145 </extension> <manager> <name>Lady Maria Bertram</name> <extension> 2375 </extension> <extension>0</extension>{ParamComputer_1}</manager> </employee> <employee> <name>Henry Crawford</name> <cubicle sign="Fidelity"> 227</cubicle> <extension>2794</extension> <manager> <name>Admiral Crawford</name> <extension>2309</extension> <extension>0</extension> <computer>ferrari</computer> </manager> </employee> <employee> <name>Fanny Price</name> <cubicle test="test attrib value" sign="Marry my cousin">666</cubicle> <manager> <name>Edmund Bertram</name> <extension>2391</extension> <extension>0</extension>{ParamComputer_3}</manager> </employee> </abc>

*****

*/

    /* Back to top

    Get a fragment

    */

lr_xml_extract( "Xml={ParamXml}",

    "Query=//cubicle[@sign=\"Fidelity\"]",

    "XMLFragmentParam=Result",

    LAST

);

//Action.c(158): "lr_xml_extract" was successful, 1 match processed

lr_message(lr_eval_string

    ("/* Result:\n***********\n{Result}\n*****\n*"));

/* Result:

    ***********

    <cubicle sign="Fidelity">227</cubicle>

    *****

    */    

    /*Back to top

     Verify the presence of values in the XML string

    */

    /*

    Finding the first occurrence

    This is the first occurrence, so the default

    "SelectAll=no does not prevent the find from working */

find_cnt = lr_xml_find( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "Value=Amateur Theater Club",

    LAST

);

//Action.c(177): "lr_xml_find" was successful, 1 match processed

lr_message

    ("sign = Amateur Theater Club: Found %d matches", find_cnt);

    /*

    sign = Amateur Theater Club: Found 1 matches

    */

    /* Back to top

    Try to find a partial string

    The complete string is "Marry my cousin".

    lr_xml_find will not find the partial string "Marry"

    as a literal value */

find_cnt = lr_xml_find( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "Value=Marry",

    "SelectAll=yes",

    "NotFound=Continue",

    LAST

);

/*

Action.c(189): Error: no matches were found for the specified query [class:CLrXmlScriptFunc]

Action.c(189): Error: "lr_xml_find" execution failed

Action.c(189): Continuing after error in Vuser script.

*/

    /* Back to top

     Finding a partial string with regular expressions

        To find a partial string, you can use

        regular expressions. Here we find "Marry" at

        the beginning of the value */

find_cnt = lr_xml_find( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "Value=^Marry",

    "SelectAll=yes",

    "UseRegExp=yes",

    LAST

);

//Action.c(204): "lr_xml_find" was successful, 1 match processed

lr_message

    ("sign = ^Marry: Found %d matches", find_cnt);

    //sign = ^Marry: Found 1 matches

    /* Here we find "my cousin" at the end of the

        value */

find_cnt = lr_xml_find( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "Value=my cousin$",

    "SelectAll=yes",

    "UseRegExp=yes",

    LAST

);

// Action.c(215): "lr_xml_find" was successful, 1 match processed

lr_message("sign = my cousin$: Found %d matches", find_cnt);

    //sign = my cousin$: Found 1 matches

    /* Here we find "my" anywhere except the beginning or

        end of the value */

find_cnt = lr_xml_find( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "Value=.+my.+",

    "SelectAll=yes",

    "UseRegExp=yes",

    LAST

);

lr_message("sign = .+my.+: Found %d matches", find_cnt);

//sign = .+my.+: Found 1 matches

    /*Back to top

     Finding a complete string that is not the first occurrence

        lr_xml_find will find the entire string, but unless

        SelectAll=yes is specified, it will only find the

        first occurrence */

find_cnt = lr_xml_find( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "Value=Marry my cousin",

    "NotFound=Continue",

    LAST

);

/*

Action.c(237): Error: no matches were found for the specified query [class:CLrXmlScriptFunc]

Action.c(237): Error: "lr_xml_find" execution failed

Action.c(237): Continuing after error in Vuser script.

*/

lr_message

("sign = Marry my cousin (SelectAll default = no): Found %d matches", find_cnt);

    /*

    sign = Marry my cousin (SelectAll default = no): Found 0 matches

    */

    /* Try the same query with SelectAll=yes */

find_cnt = lr_xml_find( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "Value=Marry my cousin",

    "SelectAll=yes",

    LAST

);

//Action.c(248): "lr_xml_find" was successful, 1 match processed

lr_message

("sign = Marry my cousin (SelectAll=Yes): Found %d matches", find_cnt);

/*

sign = Marry my cousin (SelectAll=Yes): Found 1 matches

*/

    /* Back to top

    Specifying the occurrence

        Without specifying SelectAll=yes, lr_xml_find will

        still find a specified employee occurrence, [3].

        Note that "Query=//cubicle[3]/@sign" will not work.

        "cubicle[3]" would look for the third cubicle under

        any employee.

     */

find_cnt = lr_xml_find( "Xml={ParamXml}",

    "Query=//employee[3]/cubicle/@sign",

    "Value=Marry my cousin",

    LAST

);

// Action.c(287): "lr_xml_find" was successful, 1 match processed

lr_message

    ("Third employee, sign = Marry my cousin (SelectAll default = no): Found %d matches", find_cnt);

    /*

    Third employee, sign = Marry my cousin (SelectAll default = no): Found 1 matches

    */

    /*Back to top

     Value related functions

        Value functions make no changes in the

        XML structure, but change values

    */

    /*

    Get attribute values

    This example returns the first occurrence */

lr_xml_get_values( "Xml={ParamXml}",

    "Query=//cubicle/@sign",

    "ValueParam=ResultValue",

    LAST

);

//Action.c(265): "lr_xml_get_values" was successful, 1 match processed

lr_message (lr_eval_string

("*/\n\n/* Get sign values:\n***********\n{ResultValue}\n*****\n*/\n/*"));

    /* Get sign values:

    ***********

    Amateur Theater Club

    *****

    */

    /*Back to top

     Set attribute values

    */

    

/*

Example of common error:

This is common mistake when trying replace the value of an attribute.

Note that if you ran this query:

lr_xml_set_values( "Xml={ParamXml}",

    "Query=//cubicle[@sign=\"Marry my cousin\"]",

    "Value=Do not marry Henry",

    "ResultParam=Result",

    LAST

);

It would find the element whose sign is "Marry my cousin",

which is

<employee><name>Fanny Price</name>

    <cubicle sign="Marry my cousin"

        test="test attrib value">666

    </cubicle>

and replace the value, "666", with the phrase

"Do not marry Henry"

This would be the result:

<employee><name>Fanny Price</name>

    <cubicle test="test attrib value"

        sign="Marry my cousin">Do not marry Henry

    </cubicle>

The intent is to replace the value of the sign attribute.

Use the format in the query below:

"Query=//cubicle[@sign=\"Marry my cousin\"]/@sign"

This means, find the sign attribute of the element whose

sign attribute value is "Marry my cousin".

The following command replaces the value of the attribute, and not of the element.

*/

lr_xml_set_values("Xml={ParamXml}",

    "Query=//cubicle[@sign=\"Marry my cousin\"]/@sign",

    "Value=Do not marry Henry",

    "ResultParam=Result",

    LAST

);

//Action.c(313): "lr_xml_set_values" was successful, 1 match processed

lr_message(lr_eval_string

("*/\n\n/* Do not marry Henry:\n***********\n{Result}\n*****\n*/\n/*"));

/* Do not marry Henry:

***********

<abc> <employee> <name>Thomas Bertram</name> <cubicle sign="Amateur Theater Club">227</cubicle> <extension>2145</extension> <manager> <name>Lady Maria Bertram</name> <extension>2375</extension> <extension>0</extension> </manager> </employee> <employee> <name>Henry Crawford</name> <cubicle sign="Fidelity">227</cubicle> <extension>2794</extension> <manager> <name>Admiral Crawford</name> <extension>2309</extension> <extension>0</extension> </manager> </employee> <employee> <name>Fanny Price</name> <cubicle test="test attrib value" sign="Do not marry Henry">666</cubicle> <manager> <name>Edmund Bertram</name> <extension>2391</extension> <extension>0</extension> </manager> </employee> </abc>

*****

*/

    return 0;

}

Back to top