5
\$\begingroup\$

Student list of 50 students and a teacher list of 3 teachers.

Section XML as the output where each teacher is assigned to a section, and up to 20 students are assigned in that section.

Need to loop on each teacher element, and for each teacher element, loop on the student name from 1-20, than for 2nd teacher, students 21-40 etc.

The following is working code. However, feeling that there could be better groovified way to get 20 students for a teacher

def students = """<Students>
    <name> st name 1</name>
    <name> st name 2</name>
    <name> st name 3</name>
    <name> st name 4</name>
    <name> st name 5</name>
    <name> st name 6</name>
    <name> st name 7</name>
    <name> st name 8</name>
    <name> st name 9</name>
    <name> st name 10</name>
    <name> st name 11</name>
    <name> st name 12</name>
    <name> st name 13</name>
    <name> st name 14</name>
    <name> st name 15</name>
    <name> st name 16</name>
    <name> st name 17</name>
    <name> st name 18</name>
    <name> st name 19</name>
    <name> st name 20</name>
    <name> st name 21</name>
    <name> st name 22</name>
    <name> st name 23</name>
    <name> st name 24</name>
    <name> st name 25</name>
    <name> st name 26</name>
    <name> st name 27</name>
    <name> st name 28</name>
    <name> st name 29</name>
    <name> st name 30</name>
    <name> st name 31</name>
    <name> st name 32</name>
    <name> st name 33</name>
    <name> st name 34</name>
    <name> st name 35</name>
    <name> st name 36</name>
    <name> st name 37</name>
    <name> st name 38</name>
    <name> st name 39</name>
    <name> st name 40</name>
    <name> st name 41</name>
    <name> st name 42</name>
    <name> st name 43</name>
    <name> st name 44</name>
    <name> st name 45</name>
    <name> st name 46</name>
    <name> st name 47</name>
    <name> st name 48</name>
    <name> st name 49</name>
    <name> st name 50</name>
</Students>"""

def teachers = """<Teachers>
    <name> Teacher name 1</name>
    <name> Teacher name 2</name>
    <name> Teacher name 3</name>
</Teachers>"""


def getData  = { xml, elementName ->
    def parseXml = new XmlSlurper().parseText(xml)
    parseXml.'**'.findAll { it.name() == elementName }
}

def teacherNodes = getData( teachers, 'name')
def studentNodes = getData( students, 'name')

def sublist (data, start, end) {
    start == 0 ? data.take(end) : data.drop(start).take(end-start)
}

def incrementBy = 20
def startStudents = 0
def endStundents = incrementBy 
def builder = new groovy.xml.StreamingMarkupBuilder()
builder.encoding = 'UTF-8'
def xml = builder.bind {
    mkp.xmlDeclaration() 
    Assignments {
        teacherNodes.eachWithIndex { teacherNode, index ->          
            Section {
                id (index+1)
                teacher (teacherNode.text())
                studentList {
                    sublist(studentNodes, startStudents, endStundents).each { studentNode ->
                        name (studentNode.text())
                    }
                }               
            }
            startStudents = endStundents
            endStundents += incrementBy
        }       
    }
}

println groovy.xml.XmlUtil.serialize(xml)
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I like the code already. If you want to get rid of the increments you could

  • use studentNodes.collate(20) to create chunks of length 20
  • zip teachers and students together. In Groovy the zip function equivalent is [list1, list2].transpose().
def groups = [teacherNodes*.text(), studentNodes*.text().collate(20)].transpose().collectEntries()

def builder = new groovy.xml.StreamingMarkupBuilder()
builder.encoding = 'UTF-8'
def xml = builder.bind {
    mkp.xmlDeclaration()
    Assignments {
        groups.eachWithIndex { teacherName, studentNames, index ->
            Section {
                id (index+1)
                teacher teacherName
                studentList {
                    studentNames.each { name it }
                }
            }
        }
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.