I am trying to implement a simple loop in SOAP UI 4.6.1. According to the documentation the 'Conditional Goto' step should allow me to evaluate a XPath expression against the previous response.
For given response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:GetVeryImportantDetailsResponse xmlns:ns2="http://www.bigcompany.com/XYZ/VeryImportantService/V1">
<Status Reason="You did everything wrong again" Code="nok"/>
</ns2:GetVeryImportantDetailsResponse>
</soap:Body>
</soap:Envelope>
I want to jump to another step if Code equals 'nok'. Unfortunately I cannot achieve this in any way. Some examples:
exists("//Status/Code[text() = 'nok']") -> true
exists("//Status/Code[text() = 'ok']") -> true
exists(//Status/Code[text() = "nok"]) -> false
exists(//Status/Code[text() = "ok"]) -> false
starts-with("//Status/Code", 'nok') -> false
starts-with("//Status/Code", 'ok') -> false
starts-with(//Status/Code, 'nok') -> false
starts-with(//Status/Code, 'ok') -> false
Is this a bug in SOAP UI or am I doing something wrong?
You're doing it wrong - your XPath syntax is wrong.
Try: exists(//Status[#Code = 'nok']).
Related
I am unable to fetch the correct xpath for the below schema. Any help would be great
> <soapenv:Envelope
> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
> xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> <soapenv:Header>
> <ns1:ABC soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
> soapenv:mustUnderstand="0" xmlns:ns1="http://ABCT.XYZ.com">
> <ns2:type xmlns:ns2="http://ABC.XYZ.com/header">response</ns2:type>
> <ns3:service xmlns:ns3="http://ABC.XYZ.com/header">
> <ns3:name>ABCT2 Client</ns3:name>
> <ns3:version>1.0.0</ns3:version>
> </ns3:service>
> <ns4:originator xmlns:ns4="http://ABC.XYZ.com/header">ABCT20</ns4:originator>
> <ns5:businessProcessName xmlns:ns5="http://ABC.XYZ.com/header">whaaiaia</ns5:businessProcessName>
> <ns6:requestDateTime xmlns:ns6="http://ABC.XYZ.com/header">2022-06-23T14:02:59.995Z</ns6:requestDateTime>
> <ns7:sourceSystemTransactionId xmlns:ns7="http://ABC.XYZ.com/header">77888877</ns7:sourceSystemTransactionId>
> <ns8:user xmlns:ns8="http://ABC.XYZ.com/header">
> <ns8:id>bbb</ns8:id>
> <ns8:group>ccc</ns8:group>
> </ns8:user>
> <ns9:transactionReference xmlns:ns9="http://ABC.XYZ.com/header">b65787</ns9:transactionReference>
> <ns10:result xmlns:ns10="http://ABC.XYZ.com/header">
> <ns10:status>success</ns10:status>
> <ns10:provider>PQR</ns10:provider>
> </ns10:result>
> </ns1:ABC> </soapenv:Header>
I need to get the success response tag.
Your current edit is better, but it's still not well-formed. I've taken your current data and removed all the > from the start of each line and added the missing </soapenv:Envelope> closing tag to produce this well-formed XML document:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<ns1:ABC soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xmlns:ns1="http://ABCT.XYZ.com">
<ns2:type xmlns:ns2="http://ABC.XYZ.com/header">response</ns2:type>
<ns3:service xmlns:ns3="http://ABC.XYZ.com/header">
<ns3:name>ABCT2 Client</ns3:name>
<ns3:version>1.0.0</ns3:version>
</ns3:service>
<ns4:originator xmlns:ns4="http://ABC.XYZ.com/header">ABCT20</ns4:originator>
<ns5:businessProcessName xmlns:ns5="http://ABC.XYZ.com/header">whaaiaia</ns5:businessProcessName>
<ns6:requestDateTime xmlns:ns6="http://ABC.XYZ.com/header">2022-06-23T14:02:59.995Z</ns6:requestDateTime>
<ns7:sourceSystemTransactionId xmlns:ns7="http://ABC.XYZ.com/header">77888877</ns7:sourceSystemTransactionId>
<ns8:user xmlns:ns8="http://ABC.XYZ.com/header">
<ns8:id>bbb</ns8:id>
<ns8:group>ccc</ns8:group>
</ns8:user>
<ns9:transactionReference xmlns:ns9="http://ABC.XYZ.com/header">b65787</ns9:transactionReference>
<ns10:result xmlns:ns10="http://ABC.XYZ.com/header">
<ns10:status>success</ns10:status>
<ns10:provider>PQR</ns10:provider>
</ns10:result>
</ns1:ABC>
</soapenv:Header>
</soapenv:Envelope>
There are a number of ways you could query for the "success" response flag contained in the status element: e.g. here's one:
//*[local-name()='status' and namespace-uri()='http://ABC.XYZ.com/header']
That expression evaluates to the status element containing the text "success". If you just want to check if the status is successful, you could use this XPath expression instead:
//*[local-name()='status' and namespace-uri()='http://ABC.XYZ.com/header']='success'
That will return the boolean value true.
Note you could query for the status element with an XPath like this:
//ns1:status
... or
//ns1:status='success'
... but first you will need to bind the ns1 prefix to the namespace URI http://ABC.XYZ.com/header, and how you would do that depends on what software you are using to evaluate the XPath. Using the local-name() and namespace-uri() functions is a way to query for the element with a particular namespaced name, but without having to do that binding.
I try to parse savon's response as nokokiri document
c = Savon.client(wsdl: 'http://test.fedresurs.ru/MessageService/WebService.svc?wsdl', digest_auth: ['demowebuser', 'Ax!761BN'], namespace: "http://tempuri.org/", namespace_identifier: :tem, log: true)
r = c.call(:get_trade_messages, message: {'tem:startFrom' => DateTime.now-1})
r.doc.search("TradePlace")
and it returns an empty array.
What I'm doing wrong? May be I should deal somehow with namespaces? But, how?. Examples, that I found in nokogiri documentation use Xpath, not search. And even with Xpath it returns an empty array.
XML-response:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetTradeMessagesResponse xmlns="http://tempuri.org/">
<GetTradeMessagesResult>
<TradePlace INN="7606055642" Name="Первая электронная площадка " Site="1torgi.ru " OwnerName="ООО "Промтех"">
<TradeList>
<Trade ID_External="ЗКОФЦП-17136" ID_EFRSB="653476">
<MessageList>
<TradeMessage ID="4851134"/>
<TradeMessage ID="4851135"/>
</MessageList>
</Trade>
</TradeList>
</TradePlace>
</GetTradeMessagesResult>
</GetTradeMessagesResponse>
</s:Body>
</s:Envelope>
You can use Nokogiri to break apart the XML response.
A (now nofunctional) example is this:
doc = Nokogiri::XML(response.to_hash[:get_quote_response][:get_quote_result])
print doc.to_xml(indent: 2)
print "Date : ", doc.at_css("Date").text, "\n"
print "Last price: ", doc.at_css("Last").text
are more complete example in my pastebin https://pastebin.com/W0RUuaHU. The WebserviceX was unfortunately discontinued.
As I expected the answer was in namespace, code below works fine:
r.doc.search("a|TradePlace", {"a" => "http://tempuri.org/"})
Given the following XML:
<?xml version="1.0" encoding="UTF-8" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<WFContext xmlns="http://service.wellsfargo.com/entity/message/2003/" soapenv:actor="" soapenv:mustUnderstand="0">
<messageId>cci-sf-dev14.wellsfargo.com:425a9286:14998ac6245:-7e1e</messageId>
<sessionId>425a9286:14998ac6245:-7e1d</sessionId>
<sessionSequenceNumber>1</sessionSequenceNumber>
<creationTimestamp>2014-11-10T00:14:49.243-08:00</creationTimestamp>
<invokerId>cci-sf-dev14.wellsfargo.com</invokerId>
<activitySourceId>P7</activitySourceId>
<activitySourceIdType>FNC</activitySourceIdType>
<hostName>cci-sf-dev14.wellsfargo.com</hostName>
<billingAU>05426</billingAU>
<originatorId>287586861901211</originatorId>
<originatorIdType>ECN</originatorIdType>
<initiatorId>GTST0793</initiatorId>
<initiatorIdType>ACF2</initiatorIdType>
</WFContext>
</soapenv:Header>
<soapenv:Body>
<getCustomerInformation xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/getCustomerInformation/2012/05/">
<initiatorInformation xmlns="http://service.wellsfargo.com/provider/ecpr/shared/common/2011/11/">
<channelInfo>
<initiatorCompanyNbr xmlns="http://service.wellsfargo.com/entity/message/2003/">114</initiatorCompanyNbr>
</channelInfo>
</initiatorInformation>
<custNbr xmlns="http://service.wellsfargo.com/entity/party/2003/">287586861901211</custNbr>
<customerViewList xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/getCustomerInformationCommon/2012/05/">
<customerView>
<customerViewType>GENERAL_INFORMATION_201205</customerViewType>
<preferences>
<generalInformationPreferences201205 xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/common/2012/05/">
<formattedNameIndicator xmlns="">true</formattedNameIndicator>
<includeTaxCertificationIndicator xmlns="">true</includeTaxCertificationIndicator>
</generalInformationPreferences201205>
</preferences>
</customerView>
<customerView>
<customerViewType>SEGMENT_LIST</customerViewType>
</customerView>
<customerView>
<customerViewType>LIMITED_PROFILE_REQUIRED_DATA</customerViewType>
</customerView>
<customerView>
<customerViewType>INDIVIDUAL_CUSTOMER_GENERAL_INFORMATION_201205</customerViewType>
<preferences>
<individualGeneralInformationPreferences xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/common/2012/05/">
<includeMinorIndicator xmlns="">true</includeMinorIndicator>
</individualGeneralInformationPreferences>
</preferences>
</customerView>
</customerViewList>
</getCustomerInformation>
</soapenv:Body>
</soapenv:Envelope>
I am trying to access the getCustomerInformation tag using relative XPath in VBScript.
XMLDataFile = "C:\testReqfile.xml"
Set xmlDoc = XMLUtil.CreateXML()
xmlDoc.LoadFile(XMLDataFile)
Print xmlDoc.ToString
'xmlDoc.AddNamespace "ns","xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/"
Set childrenObj = xmlDoc.ChildElementsByPath("//*[contains(#xmlns,'getCustomerInformation')]")
msgbox childrenObj.Count
But is failing to return a node.
Your XPath expression does not work because xmlns as in
<getCustomerInformation xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/getCustomerInformation/2012/05/">
is a default namespace, not an attribute. Therefore, it cannot be accessed with #xmlns.
But it seems you do not have to rely on the namespace at all, because the element name ("getCustomer Information") is telling already. To bypass the problem of those elements being in a namespace, use local-name() to select elements by their name.
Set childrenObj = xmlDoc.ChildElementsByPath("//*[local-name() = 'getCustomerInformation']")
As #Mathias Müller already explained in his answer, xmlns defines a namespace and can thus not be accessed like a regular attribute. I don't have experience with XmlUtil, but in standard VBScript you could select the node(s) like this:
Set xml = CreateObject("Msxml2.DOMDocument.6.0")
xml.async = False
xml.load "C:\path\to\your.xml"
If xml.ParseError Then
WScript.Echo xml.ParseError.Reason
WScript.Quit 1
End If
'define a namespace alias "ns"
uri = "http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/getCustomerInformation/2012/05/"
xml.setProperty "SelectionNamespaces", "xmlns:ns='" & uri & "'"
'select nodes using the namespace alias
Set nodes = xml.SelectNodes("//ns:getCustomerInformation")
I'm trying to make what appears to be a pretty straight forward SOAP request, one that works in SoapUI but when I execute my Ruby code, I get a 'raise_soap_and_http_errors!' Exception executing request.
Here's the code - the document referenced in wsdl_path works in SOAPUI to make the authenticate request.
require 'savon'
wsdl_path = 'XXXX_soap_interface.wsdl'
client = Savon.client(
:wsdl => wsdl_path,
:ssl_verify_mode => :none,
:raise_errors => true, # false if you don't want to see exceptions
pretty_print_xml: true)
response = client.call(
:authenticate,
message: {:partnerName => 'XXXX', :userName => 'xxxxxx', :password => 'xxxxx'}
)
puts response
The error I get back is:
savon/response.rb:85:in `raise_soap_and_http_errors!': (SOAP-
ENV:Server) Exception executing request (Savon::SOAPFault)
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/savon-2.4.0/lib/savon/response.rb:14:in `initialize'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/savon-2.4.0/lib/savon/operation.rb:64:in `new'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/savon-2.4.0/lib/savon/operation.rb:64:in `create_response'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/savon-2.4.0/lib/savon/operation.rb:55:in `call'
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/savon-2.4.0/lib/savon/client.rb:36:in `call'
from xxx_soap.rb:15:in `<main>'
I'm running Ruby 1.9, anyone have any ideas on what would make this work?
edit: The wsdl_path variable, when used to create the Savon client, works. I'm able to create the client and also execute client.operations and successfully get back the operations from the SOAP service. Only the request is failing.
edit: After adding the helpful logging code from below, I am getting this back:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:common="urn:xxx-com:cloud:common"
xmlns:finsvc="urn:xxx-com:cloud:finsvc"
xmlns:finsvc-13-6-0="urn:xxx-com:cloud:finsvc:13.6.0">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring>Exception executing request</faultstring>
<detail>
<operationResult>
<errorCode>101</errorCode>
<errorMessage>SOAP error 44 (SOAP 1.1 fault: SOAP-ENV:Client [no subcode] "Validation constraint violation: occurrence v
iolation in element 'userName'" Detail: [no detail] )</errorMessage>
</operationResult>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
No matter what order I put the parameters in or if I use camelcase or not, the first parameter specified in message throws the above error.
Switch on logging with
client = Savon.client(
...
log: true,
loglevel: :debug,
pretty_print_xml: true)
and share the output if you can't find the problem.
If the problem still exists then you should go the standard way:
Get SoapUI
create a valid call which you can execute successfully
based on that - write a Ruby script (not Ruby on Rails!!) which creates a valid request
integrate that code into your Rails (or whatever project).
So this all turned out to be issues in the wsdl document where fields that were required were not stated as so, but the response from the service did not reveal this.
wsdl_path should be a full URL, like http://domain.name/.../soap.wsdl.
I have some Erlang code and Emacs is telling me that I have "Unbalanced parenthesis", but I can't figure what is wrong... Here is the code:
receive
{connect, Client} ->
NewPid = spawn_link(fun() -> game_loop(0,0)),
Client ! NewPid,
handle_connect()
end.
The error is at the row starting with NewPid...
You forgot the end after game_loop(0,0) in order to correctly completely define an anonymous function. The snippet should therefore look as follows:
receive
{connect, Client} ->
NewPid = spawn_link(fun() -> game_loop(0,0) end),
Client ! NewPid,
handle_connect()
end.