How to get a child value with XPath - xpath

I have this xml
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<loginResponse xmlns="http://www.tedial.com/3rdparty/"
xmlns:ns2="http://www.tedial.com/apiextension/">
<session>1C7AE89A-73BF-01E9-9D3F-0010007FFF00</session>
</loginResponse>
</S:Body>
</S:Envelope>
I was trying so many combinations but I am unable to get the session value. Can you help me?
I tried //S:Envelope//S:Body//ns2:loginResponse//ns2:session with no luck

You used a wrong namespace on the session element. The default namespace of loginResponse - xmlns="http://www.tedial.com/3rdparty/" - is inherited to the session element. You have to use the same namespace as
with loginResponse which you - erroneously - assigned the ns2 namespace. So define a third namespace prefix for http://www.tedial.com/3rdparty/ - here I used third - and use that for loginResponse and session:
/S:Envelope/S:Body/third:loginResponse/third:session

Try this:
//S:Envelope//S:Body/loginResponse/session/text()
ns2 prefix not needed.

I got it working now. The problem was happening in SoapUI. For some reason Soap UI automatically uses namespaces for the default namespaces starting with ns1. In my case this Xpath expression worked fine:
//S:Envelope//S:Body//ns1:loginResponse//ns1:session

Related

Issue on Camel route - parsing XML tags

I have a complex camel route, which starts with an initialization route, which tries to set the headers with the info from the XML used as input.
I wonder how the route is not being able to parse the XML content, using XPath.
Before calling the route, I print the xml information in my java JUNIT, and it prints correctly, with all xml tags.
So I know the information is being sent as I am expecting.
But that route, which should set the headers using XPath, returns empty to any expression I try to use! I even used a XPath tool to assist me (https://codebeautify.org/Xpath-Tester), to check if was some xpath coding mistake, but I get the results I want from there.
So, let's suppose, I have an XML as:
<bic:Test>
<bic:context>
<bic:memberCode>GOOGLE</bic:memberCode>
</bic:context>
</bic:Test>
So, with the line below:
<setHeader headerName="myHeader">
<xpath resultType="java.lang.String">//<anyTag>/text()</xpath>
</setHeader>
or
<setHeader headerName="myHeader">
<xpath resultType="java.lang.String">//<anyTag></xpath>
</setHeader>
I will see the header with empty content.
I tried so many different things, that finally I decided to print the all the content, using an XPath expression as /.
It will print only the content ("GOOGLE"), not the tags.
Could you please assist me?
Thank you in advance!
This is probably a namespace related issue.
You have to define the bic namespace in the camel context and then use it in the xpath expression.
Have a look at the documentation in https://github.com/apache/camel/blob/master/camel-core/src/main/docs/xpath-language.adoc and particularly in the example of "Using XML configuration"
Also look at "Namespace auditing to aid debugging" for further information about debugging namespace related issues in camel.

Execution of xpath failed in Mulesoft

My Mulesoft process is making a call to SuccessFactors API. The /LOGIN call results in a response like this.
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<loginResponse xmlns="urn:sfobject.sfapi.successfactors.com" xmlns:ns2="urn:fault.sfapi.successfactors.com">
<result>
<sessionId>9A95*******A2631B8E820894CA.ps8bsfapi52t</sessionId>
<msUntilPwdExpiration>9223372036854775807</msUntilPwdExpiration>
</result>
</loginResponse>
</S:Body>
</S:Envelope>
I've the following name spaces declared in my namespace manager
<mulexml:namespace-manager>
<mulexml:namespace prefix="S" uri="http://schemas.xmlsoap.org/soap/envelope/"/>
<mulexml:namespace prefix="ns2" uri="urn:fault.sfapi.successfactors.com"/>
<mulexml:namespace prefix="" uri="urn:sfobject.sfapi.successfactors.com"/>
</mulexml:namespace-manager>
I want to read the sessionId into a mule session variable.
<set-session-variable variableName="SESSION" value="#[xpath('//S:Envelope/S:Body/loginResponse/result/sessionId').text]" doc:name="Get Session from Login"/>
But, upon execution I end up in this
<faultstring>Execution of the expression "xpath('//S:Envelope/S:Body/loginResponse/result/sessionId').text" failed. (org.mule.api.expression.ExpressionRuntimeException).</faultstring>
The XPath checks out well on any other tool but for Mulesoft.
Use XPATH with * as namespace, so you dont need to bother about namespace.
#[xpath('//*:Envelope/*:Body/*:loginResponse/*:result/*:sessionId').text]
xpath is deprecated new version of mule.
Update:
#[xpath3('//*:Envelope/*:Body/*:loginResponse/*:result/*:sessionId')]
Hope this helps.

How can i get this value with XPATH in JMeter

I have a webservice response as such :
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<FileResponse xmlns="http://xxx.x.sx.be">
<id>090150e080249d09</id>
</FileResponse>
</soap:Body>
</soap:Envelope>
I am trying to extract the value of "id" but i can't seem to figure out the right query. I used an online generator which provided :
/soap:Envelope[#xmlns:soap="http://www.w3.org/2003/05/soap-envelope"]/soap:Body/FileResponse[#xmlns="http://xxx.x.sx.be"]/id/text()
But it doesn't seem to work in Jmeter as the response is always null.
I found this to be the answer : //*[local-name() = 'id']
Your test for the namespace is invalid. Xpath queries do not support this.
Instead you will need to JMeter to pass in the namespaces declarations along with the xpath query. I dont know how JMeter does that but I can give you an xpath expression that may work around it.
//*[local-name()='FileResponse']/*[local-name()="id"]/text()
The xpath will test the name of the node and ignoring the namespaces. Its not recomended practice to test without namespaces and could be slow but it'll work.

Trying to parse xml with nokogiri and ruby

I am trying to parse the xml below to get the email address out. I can get the messageid but I think having the a: in front is enabling me to use xpath. Not sure how to pull out the email address. I am trying
xml.xpath("//s:Body/Discover/request/EmailAddress").children.text.to_s
and
xml.xpath("//s:Body/Discover/EmailAddress").children.text.to_s
if i do xml.xpath("//s:Body").children.text.to_s i get the email and the version with all the newlines and tabs but i do not want to parse the email out if i do not have to.
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">test url</a:Action>
<a:MessageID>mid</a:MessageID>
<a:ReplyTo>
<a:Address>test url</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">test url</a:To>
</s:Header>
<s:Body>
<Discover xmlns="test url">
<request xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<EmailAddress>bob#xml.com</EmailAddress>
<RequestVersion>1.0</RequestVersion>
</request>
</Discover>
</s:Body>
</s:Envelope>
The test url is preventing Nokogiri's Xpath from catching on to your namespacing within s:Body. Try simply
email = xml.xpath("//s:Body").first.to_xml.scan(/<EmailAddress>([^<]+)/)[0][0]
The Discover element (and its children) are in a different namespace, and you need to specify this in your query. The second argument to the xpath method is a hash where you can associate prefixes used in the query with namespace urls. Have a look at the section on namespaces in the Nokogiri tutorial.
With Nokogiri, if you don’t specify a namespace hash it will automatically register any namespaces defined on the root node for you. In this case that is the a prefix for http://www.w3.org/2005/08/addressing and the s prefix for http://www.w3.org/2003/05/soap-envelope. This is why your query for //s:Body works. The namespace declaration for Discover isn’t on the root, so you have to register it yourself.
When you provide your own namespace hash Nokogiri doesn’t add those defined on the root, so you will also need to include any of those used in your query.
In your case the following will find the EmailAddress node. The actual prefix you used doesn’t matter (here I’ve chosen t) as long as the URI matches).
xml.xpath('//s:Body/t:Discover/t:request/t:EmailAddress',
's' => "http://www.w3.org/2003/05/soap-envelope",
't' => "test url")

Webapi put parameter from body requires xml to contain xmlns

I'm hoping this is an easy question. I haven't made a public api using webapi or a restful service before. So I have noticed that when creating a Put or Post method that use a complex object parameter the xml sent in the body is required to contain namespace info. For example.
public HttpResponseMessage Put(Guid vendortoken, [FromBody] ActionMessage message)
{
if (message == null)
return Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed,
"actionmessage must be provided in request body.");
return Request.CreateResponse(HttpStatusCode.OK);
}
For message to come back not null my request has to look like this.
<ActionMessage
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/IntegrationModels">
<Message i:type="NewAgreement">
<AgreementGuid>3133b145-0571-477e-a87d-32f165187783</AgreementGuid>
<PaymentMethod>Cash</PaymentMethod>
</Message>
<Status>0</Status>
</ActionMessage>
the key here of course is the xmlns. On one hand the namespace is pretty generic so I feel like it shouldn't be an issue for vendors to provide, on the other hand should they really need to? If not how can I fix this so message will come back populated if they leave the name space out?
ah if only I could make them all use json :(
The namespace is significant in XML. If you want to remove it, what you can do is to change your ActionMessage class, to annotate it with the appropriate attribute (in your case, I'm assuming it would be the [DataContract(Namespace="")]), and that should remove the need for the namespace in the input (actually, after making that change using the namespace would be an error, so please consider the implications if you already have clients using your API out there).

Resources