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.
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:
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
*/
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" NewSign1="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" NewSign1="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" NewSign1="test" test="test attrib value">666</cubicle> <manager> <name>Edmund Bertram</name> <extension>2391</extension> <extension>0</extension> </manager> </employee> </abc>
*****
*/
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>
*****
*/
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>
*****
*/
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
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
*/
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
*****
*/
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;
}