XPath JMeter Assertion : Error "prefix must resolve to a namespace" - xpath

I am trying to use JMeter XPath Assertion on a tag value as below with XPath assertion command:
//m:CurrencyNameResul/text() = Pounds
Webservice Response:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<m:CurrencyNameResponse xmlns:m="http://www.oorsprong.org/websamples.countryinfo">
<m:CurrencyNameResult>Pounds</m:CurrencyNameResult>
</m:CurrencyNameResponse>
</soap:Body>
</soap:Envelope>
I am getting error
prefix must resolve to a namespace
and after referring to JMeter manual below:
NAMESPACES As a work-round for namespace limitations of the Xalan XPath parser implementation on which JMeter is based, you can provide a Properties file which contains mappings for the namespace prefixes:
prefix1=Full Namespace 1
prefix2=Full Namespace 2
…
You reference this file in jmeter.properties file using the property:
xpath.namespace.config
I don't get it, so my questions are:
what should be the content of Properties file?
where to put its path?

Here is how to proceed:
Create in jmeter/bin folder a file named namespaces.properties containing:
m=http://www.oorsprong.org/websamples.countryinfo
In user.properties set:
xpath.namespace.config=namespaces.properties
Finally fix your assertion to contain:
//m:CurrencyNameResult = 'Pounds'
And check "Use Namespaces"
To end up with:

You can amend your XPath query to use name() function like:
(//*[name() = 'm:CurrencyNameResult'])/text()
and you will not have to mess up with amending properties, restarting JMeter, etc.
Moreover if you go for local-name() function instead you will not have to include the namespace prefix into your query:
(//*[local-name() = 'CurrencyNameResult'])/text()
More information:
XPath language specification
Using the XPath Extractor in JMeter
XPath Tutorial

Related

JMeter after load XML files from a directory how to pass variables to the each XML body?

let say I have multiple XLMs files in folder and use jp#gc Directory Listing upload the files. so how do I pass variables to body xmls?
<Address>
<Address1>${address}</Address1>
<City>${city}</City>
<State>${state}</State>
<ZipOrPostalCode>${zip}</ZipOrPostalCode>
<Country>USA</Country>
</Address>
I tried to use jsr223- preprocessor but not success
Use __FileToString() and __eval() functions combination like:
${__eval(${__FileToString(${filename},,)})}
where filename is the variable from the Directory Listing Config
See Apache JMeter Functions - An Introduction article for more information on JMeter Functions concept

Spring Spel XPATH Expression for Namespace but no prefix

Issue: Trying to build the correct XPATH using SpEL xpath to correlate on a the "Name" tag value where the root tag has a namespace but no prefix.
Error: Unexpected token. Expected 'rparen())' but was 'identifier'
It's complaining about & #39; where I am trying to make a single quote for the xpath evaluation.
XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns="http://www.foo.com">
<id></id>
<Name>test</Name>
</root>
Spring Config
<aggregator
id="agg1"
input-channel="requestChannel"
output-channel="outputChannel"
discard-channel="garbageCanChannel"
ref="blah"
method="combine"
expire-groups-upon-completion="true"
correlation-strategy-expression="#xpath(payload, '//*[local-name()]='Name'/text()')"
release-strategy="blah"
release-strategy-method="timeToRelease"
send-partial-result-on-expiry="false"
send-timeout="60000"
group-timeout="60000"
/>
Update:
So after downloading spring source and tracing the issue. It's seem that during the tokenization execution in the method below, Spring is treating the "Name" as a identifier instead of as part of the string literal. At least this is the difference between a working instance and a failing instance.Most likely i'm not escaping it correctly.
Class:InternalSpelExpressionParser.java
Method:doParseExpression
this.expressionString = "#xpath(payload, '//*[local-name()=Name]')"//This works
[[HASH(#)](0,1), [IDENTIFIER:xpath](1,6), [LPAREN(()](6,7), [IDENTIFIER:payload](7,14), [COMMA(,)](14,15), [LITERAL_STRING:'//*[local-name()=Name]'](16,45), [RPAREN())](45,46)]
this.expressionString = "#xpath(payload, '//*[local-name()='Name']')"//Thisfails
[[HASH(#)](0,1), [IDENTIFIER:xpath](1,6), [LPAREN(()](6,7), [IDENTIFIER:payload](7,14), [COMMA(,)](14,15), [LITERAL_STRING:'//*[local-name()='](16,35), [IDENTIFIER:Name](35,44), [LITERAL_STRING:']'](44,47), [RPAREN())](47,48)]
Solution:
...
correlation-strategy-expression="#xpath(payload, '//*[local-name()=''Name'']/text()')"
Correct String Literal:
-You can see that it is now correct because the tokenization process is putting everything within the string literal token.
[[HASH(#)](0,1), [IDENTIFIER:xpath](1,6), [LPAREN(()](6,7), [IDENTIFIER:payload](7,14), [COMMA(,)](14,15), [LITERAL_STRING:'//*[local-name()=''Name'']/text()'](16,56), [RPAREN())](56,57)]
Additional Debug Notes:
When pulling out the spring git here:
https://github.com/spring-projects/spring-framework
Take all of the projects.
At the root is "import=into-eclipse.bat" or "import-into-idea" that I did not see. You can execute that to fully build and check-out everything you need locally and import the projects so you can trace a issue.
Your expression as posted will produces invalid XPath. It should have closing square bracket just before /text() instead :
'//*[local-name()='Name']/text()'
Or maybe using double single-quotes to escape, as suggested here :
'//*[local-name()=''Name'']/text()'

XPATH Error : Unable to evaluate expression

I have an xml like this as mentioned below. I am trying to obtain value for Cardnumber using following expression.
XPATH :
paymentService/ns0:submit/ns0:order/ns0:paymentDetails/ns0:VISA-SSL/cardNumber
But it's giving me error. Can any1 guide me on this?
<?xml version="1.0" encoding="UTF-8"?>
<paymentService version="1.0">
<ns0:submit xmlns:ns0="http://www.tibco.com/ns/no_namespace_schema_location/Payment/PaymentProcessors/WorldPay_CC/SharedResources/Schemas/paymentService_v1.dtd">
<ns0:order>
<description>description</description>
<amount value="500" currencyCode="EUR" exponent="2"/>
<ns0:paymentDetails>
<ns0:VISA-SSL>
<cardNumber>00009875083428500</cardNumber>
<expiryDate>
<date month="02" year="2008"/>
</expiryDate>
<cardHolderName>test</cardHolderName>
</ns0:VISA-SSL>
<session shopperIPAddress="192.165.22.35" id=""/>
</ns0:paymentDetails>
<shopper>
<browser>
<acceptHeader>text/html</acceptHeader>
<userAgentHeader>mozilla 5.0</userAgentHeader>
</browser>
</shopper>
</ns0:order>
</ns0:submit>
</paymentService>
Thanks
Your xmlns:ns0 is misplaced, and (think of this way) because ns0 is defined after <ns0:submit> tag, ns0:submit is "undefined" and thus the parse error.
Edit:
If you need to use this XPath in PHP, you'll either have to declare the namespace before use:
<?xml version="1.0" encoding="UTF-8"?>
<paymentService version="1.0" xmlns:ns0="http://www.tibco.com/ns/no_namespace_schema_location/Payment/PaymentProcessors/WorldPay_CC/SharedResources/Schemas/paymentService_v1.dtd">
<ns0:submit>
Or register the namespace before evaluating your XPath (Thanks to #MiMo for pointing out):
$xml->registerXPathNamespace("ns0","http://www.tibco.com/ns/no_namespace_schema_location/Payment/PaymentProcessors/WorldPay_CC/SharedResources/Schemas/paymentService_v1.dtd");
Also add a slash before your XPATH:
/paymentService/ns0:submit/ns0:order/ns0:paymentDetails/ns0:VISA-SSL/cardNumber
Live demo with declaration first or Live demo with namespace registration (both are demonstrated in PHP).
The problem is the node
<paymentService version="1.0">
Since this is not ended you have to comment it or end it properly.
If you comment that try out with this XPATH
/ns0:submit/ns0:order/ns0:paymentDetails/ns0:VISA-SSL/cardNumber
You need to register the namespace before evaluating the XPath:
$xml->registerXPathNamespace('ns0', 'http://www.tibco.com/ns/no_namespace_schema_location/Payment/PaymentProcessors/WorldPay_CC/SharedResources/Schemas/paymentService_v1.dtd');
where $xml is a SimpleXMLElement variable containing your XML.
Your XPath needs to start with / as per Passerby answer:
/paymentService/ns0:submit/ns0:order/ns0:paymentDetails/ns0:VISA-SSL/cardNumber

How to get Property Transfer in SoapUI testcase to work?

I'm trying to transfer a value from the response of one WS call to the request of another using SoapUI's Transfer Property TestStep.
First WS response:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header/>
<soapenv:Body>
<ns5:PSResponse xmlns:ns5="http://www.ab.com/abonline/service/PaymentService/1.0/" xmlns:ns6="http://www.ab.com/abonline/service/CustomerCard/1.0/" xmlns:ns7="https://secure.incab.se/DTServerModuleService/v1">
<ns5:abTransactionReference>1085-0</ns5:abTransactionReference>
<ns5:status>0</ns5:status>
</ns5:PSResponse>
</soapenv:Body>
</soapenv:Envelope>
Parsing the property works fine using an expression like:
declare namespace ns5="http://www.ab.com/abnline/service/PaymentService/1.0/"
//ns5:abTransactionReference
The next request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://www.ab.com/abonline/service/PaymentService/1.0/">
<soapenv:Header/>
<soapenv:Body>
<UpdatePaymentRequest>
<abTransactionReference>30</abTransactionReference>
... ...
I try inserting the property into the next request using:
//abTransactionReference
Gives me: [Missing match for Target XPath [//abTransactionReference]]
I also tried a full xpath:
declare namespace soapenv="http://schemas.xmlsoap.org/soap/envelope/"
//soapenv:Envelope/soapenv:Body/UpdatePaymentRequest/abTransactionReference
...resulting in similar error.
it seems you should set the default namespace to http://www.ab.com/... as well
You cannot use "" for the namespace definition. For example, in the case above >>
declare namespace soapenv="http://schemas.xmlsoap.org/soap/envelope/"
should be
declare namespace soapenv='http://schemas.xmlsoap.org/soap/envelope/';
Try to add XPath Assertions to UpdatePaymentRequest request message. Click on the Declare button on the XPath Match Configuration dialog and you will see what prefix soapUI uses for 'http://www.ab.com/abonline/service/PaymentService/1.0/' namespace. I think it will be like:
declare namespace soapenv='http://schemas.xmlsoap.org/soap/envelope/';
declare namespace ns1='http://www.ab.com/abonline/service/PaymentService/1.0/';
(see http://testautomationnoob.blogspot.com.by/2013/12/xpath-in-soapui-part-1-xpath-assertions.html). Then there is no need to have XPath Assertions - you can remove it. So, use "ns1" prefix in your xpath. In the end you will have the following xpath:
declare namespace soapenv='http://schemas.xmlsoap.org/soap/envelope/';
declare namespace ns1='http://www.ab.com/abonline/service/PaymentService/1.0/';
/soapenv:Envelope/soapenv:Body/ns1:UpdatePaymentRequest/ns1:abTransactionReference

Nokogiri/Xpath namespace query

I'm trying to pull out the dc:title element using an xpath. I can pull out the metadata using the following code.
doc = <<END
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0">
<metadata xmlns:dc="URI">
<dc:title>title text</dc:title>
</metadata>
</package>
END
doc = Nokogiri::XML(doc)
# Awesome this works!
puts '//xmlns:metadata'
puts doc.xpath('//xmlns:metadata')
# => <metadata xmlns:dc="URI"><dc:title>title text</dc:title></metadata>
As you can see the above appears to work correctly. However I don't seem to be able to get the title information from this node tree, all of the below fail.
puts doc.xpath('//xmlns:metadata/title')
# => nil
puts doc.xpath('//xmlns:metadata/dc:title')
# => ERROR: `evaluate': Undefined namespace prefix
puts doc.xpath('//xmlns:dc:title')
# => ERROR: 'evaluate': Invalid expression: //xmlns:dc:title
Could someone please explain how namespaces should be used in an xpath with the above xml doc.
All namespaces need to be registered when parsing. Nokogiri automatically registers namespaces on the root node. Any namespaces that are not on the root node you have to register yourself. This should work:
puts doc.xpath('//dc:title', 'dc' => "URI")
Alternately, you can remove namespaces altogether. Only do this if you are certain there will be no conflicting node names.
doc.remove_namespaces!
puts doc.xpath('//title')
With properly registered prefix opf for 'http://www.idpf.org/2007/opf' namespace URI, and dc for 'URI', you need:
/*/opf:metadata/dc:title
Note: xmlns and xml are reserved prefixes that can't be bound to any other namespace URI than the built-in 'http://www.w3.org/2000/xmlns/' and 'http://www.w3.org/XML/1998/namespace'.
As an alternative to explicitly constructing a hash of namespace URIs, you can retrieve the namespace definitions from the xml element where they're defined.
Using your example:
# First grab the metadata node, because that's where "dc" is defined.
metadata = doc.at_xpath('//xmlns:metadata')
# Pass metadata's namespaces as the resolver.
metadata.at_xpath('dc:title', metadata.namespaces)
Note that the second xpath could've also been:
doc.at_xpath('//dc:title', metadata.namespaces).to_s
But why search from the root when you have a nearer ancestor? Also, you should consider the namespace-defining element plus its children as the "scope" of the namespace. Searching a limited scope is less confusing and avoids subtle bugs.

Resources