Loop through xml elements in handlebars template #529

Closed
opened 2025-12-29 08:29:31 +01:00 by adam · 12 comments
Owner

Originally created by @rmeshksar on GitHub (Jul 18, 2023).

Originally assigned to: @StefH on GitHub.

I have a request with XML body. In the response template, I would like to loop through some of the elements of the request and add new elements to the response.
XPath.SelectNodes helpers returns a string and I cannot use {{#each method on it.

Wondering if there is any way to do it?

Maybe adding a new Handlebars helper?

Originally created by @rmeshksar on GitHub (Jul 18, 2023). Originally assigned to: @StefH on GitHub. I have a request with XML body. In the response template, I would like to loop through some of the elements of the request and add new elements to the response. XPath.SelectNodes helpers returns a string and I cannot use {{#each method on it. Wondering if there is any way to do it? Maybe adding a new Handlebars helper?
adam added the feature label 2025-12-29 08:29:31 +01:00
adam closed this issue 2025-12-29 08:29:31 +01:00
Author
Owner

@StefH commented on GitHub (Jul 19, 2023):

The SelectNodes does always return a string, which is not very usable.

I'll update https://github.com/Handlebars-Net/Handlebars.Net.Helpers to return a list which can be used in an each.

@StefH commented on GitHub (Jul 19, 2023): The `SelectNodes` does always return a string, which is not very usable. I'll update https://github.com/Handlebars-Net/Handlebars.Net.Helpers to return a list which can be used in an `each`.
Author
Owner

@StefH commented on GitHub (Jul 19, 2023):

https://github.com/Handlebars-Net/Handlebars.Net.Helpers/pull/80

@StefH commented on GitHub (Jul 19, 2023): https://github.com/Handlebars-Net/Handlebars.Net.Helpers/pull/80
Author
Owner

@StefH commented on GitHub (Jul 19, 2023):

@rmeshksar
I've updated the https://github.com/Handlebars-Net/Handlebars.Net.Helpers

So for this XML:

<?xml version='1.0' standalone='no'?>
<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:ns=""http://www.Test.nl/XMLHeader/10"">
   <soapenv:Header>
      <ns:TestHeader>
         <ns:HeaderVersion>10</ns:HeaderVersion>
      </ns:TestHeader>
   </soapenv:Header>
   <soapenv:Body>
      <req>
         <TokenIdLijst>
            <TokenId>0000083256</TokenId>
            <TokenId>0000083259</TokenId>
         </TokenIdLijst>
      </req>
   </soapenv:Body>
</soapenv:Envelope>;

And this C# code:

[Fact]
    public void SelectNodes_InEachLoop()
    {
        // Arrange
        var request = new
        {
            body = MiniTestSoapMessage
        };

        var expression = "{{#each (XPath.SelectNodes body \"//*[local-name()='TokenId']/text()\")}}\r\n{{this}}\r\n{{/each}}";
        var action = _handlebarsContext.Compile(expression);

        // Act
        var result = action(request);

        // Assert
        result.Should().Be("0000083256\r\n0000083259\r\n");
    }

Returns this:
"0000083256\r\n0000083259\r\n"

I think this is what you need?
Can you comment ?

@StefH commented on GitHub (Jul 19, 2023): @rmeshksar I've updated the https://github.com/Handlebars-Net/Handlebars.Net.Helpers So for this XML: ``` xml <?xml version='1.0' standalone='no'?> <soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:ns=""http://www.Test.nl/XMLHeader/10""> <soapenv:Header> <ns:TestHeader> <ns:HeaderVersion>10</ns:HeaderVersion> </ns:TestHeader> </soapenv:Header> <soapenv:Body> <req> <TokenIdLijst> <TokenId>0000083256</TokenId> <TokenId>0000083259</TokenId> </TokenIdLijst> </req> </soapenv:Body> </soapenv:Envelope>; ``` And this C# code: ``` csharp [Fact] public void SelectNodes_InEachLoop() { // Arrange var request = new { body = MiniTestSoapMessage }; var expression = "{{#each (XPath.SelectNodes body \"//*[local-name()='TokenId']/text()\")}}\r\n{{this}}\r\n{{/each}}"; var action = _handlebarsContext.Compile(expression); // Act var result = action(request); // Assert result.Should().Be("0000083256\r\n0000083259\r\n"); } ``` Returns this: `"0000083256\r\n0000083259\r\n"` I think this is what you need? Can you comment ?
Author
Owner

@rmeshksar commented on GitHub (Jul 19, 2023):

This is exactly what I was looking for. Thanks for the quick response.

For now I did something by splitting the string and loop through that but I will use this much much better approach when it is released.

{{#each (String.Split (String.Replace (XPath.SelectNodes request.body '//TokenIdLijst/TokenId') "/TokenId>" "/TokenId>*******") "*******")}}

{{this}}

{{/each}}
@rmeshksar commented on GitHub (Jul 19, 2023): This is exactly what I was looking for. Thanks for the quick response. For now I did something by splitting the string and loop through that but I will use this much much better approach when it is released. ``` {{#each (String.Split (String.Replace (XPath.SelectNodes request.body '//TokenIdLijst/TokenId') "/TokenId>" "/TokenId>*******") "*******")}} {{this}} {{/each}} ```
Author
Owner

@rmeshksar commented on GitHub (Jul 19, 2023):

I also would like to ask another question here:
XPath.Evaluate returns an object and not string.
It is working fine if I use it directly in the template as ToString method returns the Value.

But I cannot use it with another string function like Uppercase.

What do you suggest?

@rmeshksar commented on GitHub (Jul 19, 2023): I also would like to ask another question here: XPath.Evaluate returns an object and not string. It is working fine if I use it directly in the template as ToString method returns the Value. But I cannot use it with another string function like Uppercase. What do you suggest?
Author
Owner

@StefH commented on GitHub (Jul 19, 2023):

I can add a method EvaluateToString ?

@StefH commented on GitHub (Jul 19, 2023): I can add a method `EvaluateToString` ?
Author
Owner

@rmeshksar commented on GitHub (Jul 19, 2023):

That would be great.
Evaluate can return an array. In fact I think what is returns is IEnumerable<XPathItem>.

Evaluate("<x><a id=\"1\"></a></x>", "//a/@id").ToString().Dump(); // <-- 1
Evaluate("<x><a id=\"1\"></a><a id=\"2\"></a></x>", "//a/@id").ToString().Dump(); // <-- 1, 2
@rmeshksar commented on GitHub (Jul 19, 2023): That would be great. Evaluate can return an array. In fact I think what is returns is IEnumerable\<XPathItem\>. ```csharp Evaluate("<x><a id=\"1\"></a></x>", "//a/@id").ToString().Dump(); // <-- 1 Evaluate("<x><a id=\"1\"></a><a id=\"2\"></a></x>", "//a/@id").ToString().Dump(); // <-- 1, 2 ```
Author
Owner

@rmeshksar commented on GitHub (Jul 19, 2023):

Maybe also a ToString() helper is a good addition to the helpers.

@rmeshksar commented on GitHub (Jul 19, 2023): Maybe also a ToString() helper is a good addition to the helpers.
Author
Owner

@StefH commented on GitHub (Jul 19, 2023):

EvaluateToString has been added, see PR.

ToString() helper is a good addition to the helpers.
yes I thought on that, but this requires a change in many helpers, so for now I'll skip this.

@StefH commented on GitHub (Jul 19, 2023): EvaluateToString has been added, see PR. > ToString() helper is a good addition to the helpers. yes I thought on that, but this requires a change in many helpers, so for now I'll skip this.
Author
Owner

@StefH commented on GitHub (Jul 19, 2023):

In the next days I will create a new NuGet for Handlebars.Net.Helpers and I'll include this in WireMock.Net

@StefH commented on GitHub (Jul 19, 2023): In the next days I will create a new NuGet for Handlebars.Net.Helpers and I'll include this in WireMock.Net
Author
Owner

@rmeshksar commented on GitHub (Jul 20, 2023):

This is amazing. Thanks

@rmeshksar commented on GitHub (Jul 20, 2023): This is amazing. Thanks
Author
Owner

@StefH commented on GitHub (Jul 20, 2023):

https://github.com/WireMock-Net/WireMock.Net/pull/976

@StefH commented on GitHub (Jul 20, 2023): https://github.com/WireMock-Net/WireMock.Net/pull/976
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net#529