I'm trying to virtualize an XML-based API using WireMock and generate a JSON response using wiremock standalone jar. The requirement is to copy a tag value from the XML request payload to the JSON response using XPath. However, I'm facing issues with the XPath expressions I've tried so far, and I'm not able to get it to work correctly.
Here's a dummy example to illustrate my scenario: Sample Request Payload (XML):
`<Envelope
xmlns="http://www.example.com/Envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<SourceID>SOURCE_ID</SourceID>
<Timestamp>2024年07月01日T16:27:26Z</Timestamp>
</Header>
<Body>
<Record>
<Metadata>
<Key>
<Name>RequestNumber</Name>
<Value>REQ12345</Value>
</Key>
</Metadata>
</Record>
</Body>
</Envelope>`
Sample Response Payload (JSON):
`{
"event": {
"source": "example",
"type": "example_event",
"timestamp": "2024年07月01日T16:27:26Z",
"payload": {
"requestNumber": "REQ12345"
}
}
}`
Problem:
I'm getting an UncheckedExecutionException in WireMock, indicating an issue with the XPath expression. Despite trying various XPath expressions, the correct value is not being extracted and placed into the JSON response.
Request for Help: Can anyone guide me on the correct way to extract the value from the XML request payload using XPath in WireMock? Any insights or examples would be greatly appreciated.
XPath Expressions I've Tried:
{{{xpath request.body '//Key[Name="RequestNumber"]/Value/text()'}}}
{{{xpath request.body '//*[local-name()="Key"]//*[local-name()="Name" and text()="RequestNumber"]/*[local-name()="Value"]/text()'}}}
{{{xpath request.body '/*[local-name()="Envelope"]/*[local-name()="Body"]/*[local-name()="Record"]/*[local-name()="Metadata"]/*[local-name()="Key"]/*[local-name()="Name"][text()="RequestNumber"]/following-sibling::*[local-name()="Value"]/text()'}}}
-
I suggest you try Beeceptor's XML mocking as well. It natively converts an XML payload to a JSON object, for processing in the template engine. This is from their documentation.ankitjaininfo– ankitjaininfo2024年12月16日 09:03:26 +00:00Commented Dec 16, 2024 at 9:03
1 Answer 1
I think you are spot on with some of your xPath expressions. For example, this one should work as far as I can tell -
//Key[Name="RequestNumber"]/Value/text(). I think the main issue is the escaping of quotes etc. To make this
easier I separated out the response into a separate file and used the assign helper to hold the xpath expression.
That way I don't have to worry about all the escaping of quotes etc.
My json stub mapping looks like this:
{
"request": {
"url": "/xml-to-json",
"method": "POST"
},
"response": {
"status": 200,
"bodyFileName": "response.txt",
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"transformers": [
"response-template"
]
}
}
My response.txt file looks like this
{{#assign 'xpathExpression'}}//Key[Name="RequestNumber"]/Value/text(){{/assign}}
{
"event": {
"source": "example",
"type": "example_event",
"timestamp": "2024年07月01日T16:27:26Z",
"payload": {
"requestNumber": "{{xPath request.body xpathExpression}}"
}
}
}
Given the request you specified in your question:
<Envelope
xmlns="http://www.example.com/Envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<SourceID>SOURCE_ID</SourceID>
<Timestamp>2024年07月01日T16:27:26Z</Timestamp>
</Header>
<Body>
<Record>
<Metadata>
<Key>
<Name>RequestNumber</Name>
<Value>REQ12345</Value>
</Key>
</Metadata>
</Record>
</Body>
</Envelope>
You should see a response that looks like the following when you make the request to the stub:
{
"event": {
"source": "example",
"type": "example_event",
"timestamp": "2024年07月01日T16:27:26Z",
"payload": {
"requestNumber": "REQ12345"
}
}
}
You can find more docs on the xPath helper here - https://wiremock.org/docs/response-templating/#xpath-helpers
You can find information on the assign helper here - https://wiremock.org/docs/response-templating/#number-and-assignment-helpers
This example was build using WireMock version 3.8.0
Comments
Explore related questions
See similar questions with these tags.