0

My XML looks like is

<?xml version="1.0" encoding="UTF-8"?>
<TimeAccount>
  <TimeAccount>
    <accountType>CMSV</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>36218</userId>
    <timeAccountDetails/>
  </TimeAccount>
  <TimeAccount>
    <accountType>CMSV</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc222</userId>
    <timeAccountDetails/>
  </TimeAccount>
  <TimeAccount>    
    <accountType>PTOS</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc111</userId>
    <timeAccountDetails>
      <TimeAccountDetail>       
        <bookingAmount>176</bookingAmount>
        <bookingType>MANUAL_ADJUSTMENT</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>        
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>
      <TimeAccountDetail>        
        <bookingAmount>-8</bookingAmount>      
        <bookingType>EMPLOYEE_TIME</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>      
    </timeAccountDetails>
  </TimeAccount>
  <TimeAccount>
    <accountType>PTOS</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc222</userId>
    <timeAccountDetails>
      <TimeAccountDetail>        
        <bookingAmount>256</bookingAmount>        
        <bookingType>MANUAL_ADJUSTMENT</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>   
      <TimeAccountDetail>
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>        
    </timeAccountDetails>
  </TimeAccount>
  <TimeAccount>
    <bookingStartDate>2021-01-01T00:00:00.000</bookingStartDate>
    <accountType>LOA</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc111</userId>
    <timeAccountDetails>
      <TimeAccountDetail>
        <bookingAmount>40</bookingAmount>        
        <bookingType>MANUAL_ADJUSTMENT</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>        
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>       
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>      
    </timeAccountDetails>
  </TimeAccount>
  <TimeAccount>
    <bookingStartDate>2021-01-01T00:00:00.000</bookingStartDate>
    <accountType>LOA</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc222</userId>
    <timeAccountDetails>
      <TimeAccountDetail>
        <bookingAmount>40</bookingAmount>        
        <bookingType>MANUAL_ADJUSTMENT</bookingType>        
      </TimeAccountDetail>
    </timeAccountDetails>
  </TimeAccount>
</TimeAccount>

I need to add a new node for each employee record when account Type is PTOS and subnode is MANUAL_ADJUSTMENT, I wrote below code which works for single employee record, how should I loop for all employee records.

def ptoNode =    xml.TimeAccount.find { it.accountType.text() == 'PTOS' }
     if(ptoNode !=null)
     {
def detailNode =    ptoNode.timeAccountDetails.TimeAccountDetail.find { it.bookingType.text() == 'MANUAL_ADJUSTMENT' }
    if(detailNode != null)
    {
        ptosHours = detailNode.bookingAmount.text()
        ptoNode.appendNode('newPTONode', null, ptosHours.toString() )
     }
     }
  1. above code works only for 1st employee (abc111), how to do it for each employee node?

  2. I need to add all hours (bookingAmount) sub nodes with booking type EMPLOYEE_TIME with in employee node and create node like above at employee header level, I am able to do it for one EMPLOYEE_TIME record (same like above) but could not recursively add all subnodes. how to achieve it?

  3. How to loop through XML document at high level and detail level in groovy script?

Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
  • use `findAll{...}` instead of `find{...}` – daggett Apr 05 '21 at 20:26
  • Thank you for your quick response. I get below error when I use findAll in place of find java.lang.NoSuchMethodException: No signature of method: java.util.ArrayList.text() is applicable for argument types: () values: [] Possible solutions: get(int), get(int), set(int, java.lang.Object), set(int, java.lang.Object), getAt(int), getAt(java.util.Collection) – Pradeep Bondla Apr 05 '21 at 20:41
  • Can it be possible to write a .each and then if (condition) like in loop in java loop (header node) { if (condition) //accoutType == PTOS loop (child node) { if (condition) //booking type == EMPLOYEE_TIME } above is possible in groovy? if yes, could you please share how? – Pradeep Bondla Apr 05 '21 at 20:49
  • find "question is answered" button to get next answer ;) https://stackoverflow.com/questions/65526399/groovy-script-code-to-append-xml-node-taking-15-hours-for-6k-employee-records – daggett Apr 05 '21 at 21:14
  • I still can't see "question is answered" button on that previous question :) sorry. May be with this discussion it will show up :) – Pradeep Bondla Apr 05 '21 at 22:29
  • finally, with the help of blog I answered previous thread. I had to click grayed out check mark beside your answer. Could you please answer current question :) – Pradeep Bondla Apr 05 '21 at 22:49

1 Answers1

1
def xml=new XmlParser().parseText('''<?xml version="1.0" encoding="UTF-8"?>
<TimeAccount>
  <TimeAccount>
    <accountType>CMSV</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>36218</userId>
    <timeAccountDetails/>
  </TimeAccount>
  <TimeAccount>
    <accountType>CMSV</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc222</userId>
    <timeAccountDetails/>
  </TimeAccount>
  <TimeAccount>    
    <accountType>PTOS</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc111</userId>
    <timeAccountDetails>
      <TimeAccountDetail>       
        <bookingAmount>176</bookingAmount>
        <bookingType>MANUAL_ADJUSTMENT</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>        
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>
      <TimeAccountDetail>        
        <bookingAmount>-8</bookingAmount>      
        <bookingType>EMPLOYEE_TIME</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>      
    </timeAccountDetails>
  </TimeAccount>
  <TimeAccount>
    <accountType>PTOS</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc222</userId>
    <timeAccountDetails>
      <TimeAccountDetail>        
        <bookingAmount>256</bookingAmount>        
        <bookingType>MANUAL_ADJUSTMENT</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>   
      <TimeAccountDetail>
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>        
    </timeAccountDetails>
  </TimeAccount>
  <TimeAccount>
    <bookingStartDate>2021-01-01T00:00:00.000</bookingStartDate>
    <accountType>LOA</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc111</userId>
    <timeAccountDetails>
      <TimeAccountDetail>
        <bookingAmount>40</bookingAmount>        
        <bookingType>MANUAL_ADJUSTMENT</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>        
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>        
      </TimeAccountDetail>
      <TimeAccountDetail>       
        <bookingAmount>-8</bookingAmount>        
        <bookingType>EMPLOYEE_TIME</bookingType>       
      </TimeAccountDetail>      
    </timeAccountDetails>
  </TimeAccount>
  <TimeAccount>
    <bookingStartDate>2021-01-01T00:00:00.000</bookingStartDate>
    <accountType>LOA</accountType>
    <bookingEndDate>2021-12-31T00:00:00.000</bookingEndDate>
    <userId>abc222</userId>
    <timeAccountDetails>
      <TimeAccountDetail>
        <bookingAmount>40</bookingAmount>        
        <bookingType>MANUAL_ADJUSTMENT</bookingType>        
      </TimeAccountDetail>
    </timeAccountDetails>
  </TimeAccount>
</TimeAccount>
''')


xml.TimeAccount.findAll{it.accountType.text()=='PTOS'}.each{ptoNode->
    ptoNode.timeAccountDetails.TimeAccountDetail.find{ it.bookingType.text() == 'MANUAL_ADJUSTMENT' }?.with{detailNode->
       ptosHours = detailNode.bookingAmount.text()
       ptoNode.appendNode('newPTONode', null, ptosHours )
    }
}
println groovy.xml.XmlUtil.serialize(xml)

daggett
  • 26,404
  • 3
  • 40
  • 56
  • Thank you @daggett, that worked perfectly. what is the use of "?.with" in place of ".each"? I will mark this question answered shortly. – Pradeep Bondla Apr 06 '21 at 14:27
  • `getX().with{x-> x.f1() }` the same as `x = getX(); x.f1(); `, `getX()?.with{x-> x.f1() }` the same as `x = getX(); if(x){ x.f1(); }`. `with:` https://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/Object.html#with(groovy.lang.Closure) `safe access:` https://groovy-lang.org/operators.html#_safe_navigation_operator – daggett Apr 06 '21 at 14:40
  • Thank yo so much. – Pradeep Bondla Apr 06 '21 at 14:51