Ushani
Ushani

Reputation: 1209

How to give multiple namespaces of salesforce in xpath

I have a response like below which I got from salesforce. I need to use xpath to retrieve the ProfileId.

<queryResponse xmlns="urn:partner.soap.sforce.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.partner.soap.sforce.com">
   <result xsi:type="QueryResult">
      <done>true</done>
      <queryLocator xsi:nil="true"/>
      <records xsi:type="sf:sObject">
         <sf:type>User</sf:type>
         <sf:Id xsi:nil="true"/>
         <sf:Username>[email protected]</sf:Username>
         <sf:ProfileId>00e90000001aVwiAAE</sf:ProfileId>
         <sf:Name>user</sf:Name>
         <sf:LastName>test</sf:LastName>
         <sf:Email>[email protected]</sf:Email>
      </records>
      <size>1</size>
   </result>
</queryResponse>

I used an online xpath generator. It gave me the below xpath. But it seems to be wrong.

/queryResponse[@xmlns="urn:partner.soap.sforce.com"]/result[@xsi:type="QueryResult"]/records[@xsi:type="sf:sObject"]/sf:ProfileId/text()

Upvotes: 0

Views: 108

Answers (1)

har07
har07

Reputation: 89315

The XPath generator that you used seems didn't handle default namespace properly. Normally you need to declare a prefix (details of this step varies for different XPath processors), say d, referencing the default namespace URI which is "urn:partner.soap.sforce.com". Then use that prefix to reference elements in that namespace (wrapped for readability) :

/d:queryResponse
/d:result[@xsi:type="QueryResult"]
/d:records[@xsi:type="sf:sObject"]
/sf:ProfileId
/text()

demo

It is possible to create a pure XPath that works the same as the previous XPath, but it will be too complex. To give you the taste of it, the following is almost equivalent to part of the previous XPath (starting from /d:records down) :

//*[local-name()='records' and namespace-uri()='urn:partner.soap.sforce.com']
   [@*[
        namespace-uri()='http://www.w3.org/2001/XMLSchema-instance' and 
        local-name()='type' and 
        .="sf:sObject"
    ]]
 /*[local-name()='ProfileId' and namespace-uri()='urn:sobject.partner.soap.sforce.com']
 /text()

There are many other possible XPath expressions to get ProfileId from such XML structure, one of the simplest, without knowing how to properly declare namespace prefix using your XPath processor, would be as follows :

//*[name()='sf:ProfileId']/text()

The above will return element where tag name equals 'sf:ProfileId' anywhere within the XML document.

Upvotes: 1

Related Questions