raymercb
raymercb

Reputation: 11

How to build xpath using namespaces and conditions

Using this xml:

<?xml version="1.0" encoding="UTF-8"?>
<actionResponse>
   <responses>
       <response>
           <data></data>
           <details>
               <requestId>1</requestId>
           </details>
           <errors>
               <error>
                   <msg>Message 1</msg>
               </error>
               <error>
                   <msg>Message 2</msg>
               </error>
           </errors>
       </response>
       <response>
           <data></data>
           <details>
               <requestId>2</requestId>
           </details>
           <errors>
               <error>
                   <msg>Message 1</msg>
               </error>
               <error>
                   <msg>Message 2</msg>
               </error>
           </errors>
       </response>
   </responses>
</actionResponse>

I can play with xpath(s) like these:

//response[details/requestId=1]/errors/error/msg[text()="Message 1"] //response[details/requestId=2]/errors/error/msg[text()="Message 1"] //response[details/requestId=1]/errors/error/msg[text()="Message 2"]

In other words, I can get a message from an specific request. The problem is trying to do the same when the xml has namespaces. I can not find a way to do the same with this one:

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope
   xmlns:env="http://www.w3.org/2003/05/soap-envelope">
   <env:Body>
       <actionResponse
           xmlns="http://www.sample.com/namespaces/SOAP">
           <responses>
               <response>
                   <data></data>
                   <details>
                       <requestId>1</requestId>
                   </details>
                   <errors>
                       <error>
                           <msg>Message 1</msg>
                       </error>
                       <error>
                           <msg>Message 2</msg>
                       </error>
                   </errors>
               </response>
               <response>
                   <data></data>
                   <details>
                       <requestId>2</requestId>
                   </details>
                   <errors>
                       <error>
                           <msg>Message 1</msg>
                       </error>
                       <error>
                           <msg>Message 2</msg>
                       </error>
                   </errors>
               </response>
           </responses>
       </actionResponse>
   </env:Body>
</env:Envelope>

Upvotes: 0

Views: 82

Answers (2)

raymercb
raymercb

Reputation: 11

Playing a little more with xpaths, this solution fits more in my case, thanks!

//*[local-name()='response']/*[local-name()='details']/*[local-name()='requestId'][text()="1"]/../../*[local-name()='errors']/*[local-name()='error']/*[local-name()='msg'][text()="Message 1"]

Upvotes: 0

MiMo
MiMo

Reputation: 11953

The XPath would be:

//soap:response[soap:details/soap:requestId=1]/soap:errors/soap:error/soap:msg[text()="Message 1"]

and you have to tell you XPath processor that the soap prefix corresponds to http://www.sample.com/namespaces/SOAP.

How to do this depends on the processor you are using. For example in C# / .NET you would use a XmlNamespaceManager, see this example

Upvotes: 1

Related Questions