display fields value in the form of array in groovy

420 views Asked by At

I've a method in groovy inside strategy.groovy file as shown below:

strategy.groovy file (snippets of code inside strategy,groovy file):

Element strategy = createStrategyElement(rootStrategy, ctx) 
println("strategy 31: "+strategy);
root.addNewNode(strategy)

private createStrategyElement(rootStrategy, ctx) {
    
    Element strategy = new DefaultElement("strategy")

    strategy.addElement("players_o.player_id_s").text = rootstrategy.players_o.item.component.player_id_s  != null ? rootstrategy.players_o.item.component.player_id_s : ""
    strategy.addElement("players_o.first_name_s").text = rootstrategy.players_o.item.component.first_name_s  != null ? rootstrategy.players_o.item.component.first_name_s : ""
    strategy.addElement("players_o.last_name_s").text = rootstrategy.players_o.item.component.last_name_s  != null ? rootstrategy.players_o.item.component.last_name_s : ""
    
    println("Value of strategy at line#146 "+strategy)
    return strategy
}

The above groovy code displays the o/p in the following fashion:

players_o.first_name_s: (2) ['[David, Lionel]', '[David, Lionel]']
players_o.player_id_s: (2) ['[5, 7]', '[5, 7]']
players_o.last_name_s: (2) ['[Beckham, Messi]', '[Beckham, Messi]']

Problem Statement:

I am wondering what changes I need to do in the Groovy code (strategy.groovy file) above so that it displays the result (in the form of array) in the following fashion (desired o/p):

{
    "item": [
        {
            "talent_id_s": "5",
            "first_name_s": "David",
            "last_name_s": "Beckham"
        },
        {
            "talent_id_s": "7",
            "first_name_s": "Lionel",
            "last_name_s": "Messi"
        }
    ]
}

This is what I have tried but more changes need to be done in order to achieve the desired o/p.

private createStrategyElement(rootStrategy, ctx) {

    Element strategy = new DefaultElement("strategy")
    def players = []
    players = rootStrategy.players_o
    
    for(Element current: players.item) {
        strategy.addElement("players_o.player_id_s").text = rootstrategy.players_o.item.component.player_id_s  != null ? rootstrategy.players_o.item.component.player_id_s : ""
        strategy.addElement("players_o.first_name_s").text = rootstrategy.players_o.item.component.first_name_s  != null ? rootstrategy.players_o.item.component.first_name_s : ""
        strategy.addElement("players_o.last_name_s").text = rootstrategy.players_o.item.component.last_name_s  != null ? rootstrategy.players_o.item.component.last_name_s : ""
    }
return strategy
}
2

There are 2 answers

2
Jose Ross On

Here is a short explanation on how Crafter CMS handles XML:

The XML descriptor of your content will look something like this

<players_o>
  <item>
    <component>
      <player_id_s>...</player_id_s>
      <first_name_s>...</first_name_s>
      <last_name_s>...</last_name_s>
    </component>
  <item>
  <item>
    ...
  </item>
</players_o>

and when you execute and expression like

rootstrategy.players_o.item.component.player_id_s

Groovy will actually evaluate it as an XPath selector, so it will return all nodes matching the path. This will flatten the structure and that is why the result doesn't look as you expect.

So to solve your issue you should navigate the structure using a for loop or Groovy collection methods, something like this:

// for every player item
for (player : rootstrategy.players_o.item) {
   // create an element
   def playerElement = new DefaultElement("player")

   // add the properties that you want
   playerElement.addElement("player_id").text = player.component.player_id_s

   // do something with the new playerElement ...
}

That way you will preserve the original structure of the XML.

2
Kaus2b On

You are not using the loop variable at all. Try this if it works:

private createStrategyElement(rootStrategy, ctx) {

Element strategy = new DefaultElement("strategy")
def players = []
players = rootStrategy.players_o

for(Element current: players.item) {
    strategy.addElement("players_o.player_id_s").text = current.component.player_id_s ?: ""
    strategy.addElement("players_o.first_name_s").text = current.component.first_name_s ?: ""
    strategy.addElement("players_o.last_name_s").text = current.component.last_name_s ?: ""
}
return strategy
}

Note: I added the Elvis operator for simplification