-1

I am trying to match request body in my wiremock.net mock service and send specific response back, only when 'code' tag contains value of '01.23.45.678.910'.

here is the xml:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope" 
                  xmlns:v1="some-url" 
                  xmlns:com="some-url">
    <soapenv:Body>
      <v1:TestRequest>
         <v1:RequestParameters>
            <com:requestorDN>tst</com:requestorDN>
            <com:requestID>ece8c518-669e-4a17-840b-62ff4c047f04</com:requestID>
            <com:useSoapFaults>1</com:useSoapFaults>
         </v1:RequestParameters>
         <v1:code>01.23.45.678.910</v1:code>
      </v1:TestRequest>
   </soapenv:Body>
</soapenv:Envelope>

and here is the query, which has no effect:

/*:Envelope/*:Body/*:TestRequest/*:code[.='01.23.45.678.910']

how can I do this matching correctly?

Siebe Jongebloed
  • 3,906
  • 2
  • 14
  • 19
tabsandze
  • 23
  • 3
  • I think you need to use `/*[local-name()='Envelope']/*...` etc. if you want to ignore the namespace – Xerillio Jul 29 '22 at 07:29
  • The XML in your example is not "namespace wellformed". It uses namespace prefixes which are not associated with any namespace URI. There are missing namespace declarations for the `soapenv`, `v1`, and `com` prefixes. – Conal Tuohy Jul 29 '22 at 08:14
  • Does this answer helps you: https://stackoverflow.com/a/56779690/3710053 – Siebe Jongebloed Jul 29 '22 at 08:26
  • @SiebeJongebloed I think asterisks('*') provided in my example solves that problem – tabsandze Jul 29 '22 at 08:36
  • If your XPath version can handle that, your XPath should work – Siebe Jongebloed Jul 29 '22 at 09:15
  • Note that this question refers to [WireMock.Net](https://github.com/WireMock-Net/WireMock.Net) which could handle the xpath query differently. I'll take a look... – Stef Heyenrath Jul 29 '22 at 12:42
  • turns out the problem was in source code, rather than the matcher or wiremock. this query //*:code[.='01.23.45.678.910'] as well as the one above worked just fine. my bad. – tabsandze Jul 29 '22 at 19:39

2 Answers2

0

WireMock's documentation gives an example of how to bind XML namespace prefixes to XML namespace URIs, so that you can write an XPath expression using those namespace prefixes.

https://wiremock.org/docs/request-matching/

If you need to be able to select elements based on their namespace in addition to their name you can declare the prefix to namespace URI mappings and use them in your XPath expression:

Java:

.withRequestBody(matchingXPath("/stuff:outer/more:inner[.=111]")   
.withXPathNamespace("stuff", "http://stuff.example.com")   
.withXPathNamespace("more", "http://more.example.com"))

JSON:

{   "request": {
    ...
    "bodyPatterns" : [ {
      "matchesXPath" : "/stuff:outer/more:inner[.=111]",
      "xPathNamespaces" : {
        "stuff" : "http://stuff.example.com",
        "more"  : "http://more.example.com"
      }
    } ]
    ...   },   ... }
Conal Tuohy
  • 2,561
  • 1
  • 8
  • 15
  • Most XPath APIs do provide some way to declare namespace bindings, and I'd always recommend seeking it out in the documentation, and using it, rather than using `local-name(.)` or similar hacks where you ignore the namespace. – Conal Tuohy Jul 29 '22 at 13:54
-2

As @Xerillio correctly pointed out you need to use local-name() function to ignore namespaces. And to match the xml tag value you can use text() function. You also can take advantage of node selector with wildcard //* which selects nodes in the document from the current node that match the selection no matter where they are .

Following xpath query worked for me :

//*[local-name()='v1:code' and text()='01.23.45.678.910']