groovyjmeterxml-parsingjsr223xmlslurper

How to dynamically create an XML object in the jmeter PreProcessor


Using Jmeter, I want to compose a dynamically-sized, XML object with dynamically-generated content having the structure as the one below in a JSR223 preprocessor:

<?xml version="1.0" encoding="UTF-8"?>
<aaa id1="TD00100" id2="005" date="2021-09-06T09:49:57.623Z" id3="Minoan007">
    <p>
        <pa outOfScope="false" inTransit="false" reqID="ID00001">
            <location arrivalDate="2021-09-20" code="ASD" departureDatetime="2021-09-20T11:00:00.000Z" scheduleNo="AB123">
            </location>
            <docs dob="1960-09-02" expiryDate="2031-09-13" gen="f" givenName="Test1" anotherCode="AB" anotherCode2="ABC" surname="John" docNr="100000001" docType="J">
            </docs>
        </pa>
        <pa eesetiasOutOfScope="false" inTransit="false" pReqID="ID00002">
            <location arrivalDate="2021-09-20" code="ASD" departureDatetime="2021-09-20T11:00:00.000Z" scheduleNo="AB123">
            </location>
            <docs dob="1960-09-02" expiryDate="2031-09-13" gen="m" givenName="Test2" anotherCode="AB" anotherCode2="ABC" surname="John" docNr="100000002" docType="J">
            </docs>
        </pa>
        <pa eesetiasOutOfScope="false" inTransit="false" pReqID="ID00003">
            <location arrivalDate="2021-09-20" code="ASD" departureDatetime="2021-09-20T11:00:00.000Z" scheduleNo="AB123">
            </location>
            <docs dob="1960-09-02" expiryDate="2031-09-13" gen="f" givenName="Test3" anotherCode="AB" anotherCode2="ABC" surname="John" docNr="100000003" docType="J">
            </docs>
        </pa>       
    </p>
</aaa>

I want to have a HTTP Sampler with a static body such as:

<?xml version="1.0" encoding="UTF-8"?>
<aaa id1="TD00100" id2="005" date="2021-09-06T09:49:57.623Z" id3="Minoan007">
    <p>
        ${xmlObject}
    </p>
</aaa>

And in the ${xmlObject} I want to put a custom-size XML object based on some variable and populate each <pa> </pa> object with some small part of the content differently (for example just increasing the id by 1 in each sub-xml object), based on some custom defined counter. Something like this example. Say I define a variable to be equal to 100: when the script runs it would generate an object with 100 sub-objects with this structure:

<pa .... reqID="ID00001">...</pa> objects
</pa>
<pa .... reqID="ID00002">...</pa> objects
</pa>
<pa .... reqID="ID00003">...</pa> objects
</pa>    

....n

<pa .... reqID="n">...</pa> objects
</pa>  

And then I just need to move it to a Jmeter variable with using vars.put and use it in my HTTP request.

I did something identical from the logic point of view for a JSON object using the JsonSlurper in the JSR223 Preprocessor. I just don't know what to use and how to use it to generate my custom XML object. Any help would be appreciated.


Solution

  • It took me a day, but I finally found the solution I needed. Leaving the code here in case it helps someone. Thanks again to Dmitri T for pointing me in the right direction with those resources.

    def numberOfNodes = 3 // set how many sub-nodes are needed
    
    def writer = new StringWriter()
    def xml = new groovy.xml.MarkupBuilder(writer)
    
    
    xml.rootNode() {
    createRootNode(xml, numberOfNodes, 'ID0000')
    }
    
    def createRootNode(builder, repeat, reqID) {
       for (int i = 0 ; i < repeat ; i++) {
           builder.pa(outOfScope:'false', inTransit:'false', reqID:reqID+(i+1).toString() ){
            builder.location (arrivalDate:'2021-09-20', code:'ASD', departureDatetime:'2021-09-20T11:00:00.000Z', scheduleNo:'LH8912')
            builder.docs( dob:'1960-09-02' , expiryDate:'2031-09-13', gen:'female', givenName:'Test3', anotherCode:'ABC', anotherCode2:'AB', surname:'John', docNr: 100000001, travelDocType:'J' )
           }
        }
    }
    
    def nodeAsText = writer.toString()
    log.info(nodeAsText) // print to jmeter log console
    
    vars.put('nodes3XmlObj', nodeAsText) //put the variable as a string into a variable accesible for jmeter
    

    Outcome in Jmeter log console:

    2021-10-13 23:05:28,222 INFO o.a.j.m.J.JSR223 PreProcessor: <rootNode>
      <pa outOfScope='false' inTransit='false' reqID='ID00001'>
        <location arrivalDate='2021-09-20' code='ASD' departureDatetime='2021-09-20T11:00:00.000Z' scheduleNo='LH8912' />
        <docs dob='1960-09-02' expiryDate='2031-09-13' gen='female' givenName='Test3' anotherCode='ABC' anotherCode2='AB' surname='John' docNr='100000001' travelDocType='J' />
      </pa>
      <pa outOfScope='false' inTransit='false' reqID='ID00002'>
        <location arrivalDate='2021-09-20' code='ASD' departureDatetime='2021-09-20T11:00:00.000Z' scheduleNo='LH8912' />
        <docs dob='1960-09-02' expiryDate='2031-09-13' gen='female' givenName='Test3' anotherCode='ABC' anotherCode2='AB' surname='John' docNr='100000001' travelDocType='J' />
      </pa>
      <pa outOfScope='false' inTransit='false' reqID='ID00003'>
        <location arrivalDate='2021-09-20' code='ASD' departureDatetime='2021-09-20T11:00:00.000Z' scheduleNo='LH8912' />
        <docs dob='1960-09-02' expiryDate='2031-09-13' gen='female' givenName='Test3' anotherCode='ABC' anotherCode2='AB' surname='John' docNr='100000001' travelDocType='J' />
      </pa>
    </rootNode>