0

I have the following CSV file:

iDocType,iDocId,iName,iDate
P,555551555,Braiden,2022-12-31
I,100000001,Dominique,2024-12-10
P,100000002,Joyce,2025-11-15

Using jmeter's JSR223 preprocessor element, I need to compose an XML parent node containing multiple (based on parametrization) child-nodes and each node must contain properties with values of each of these CSV rows.

I think that I need some way to loop over this CSV file and extract values from each row until all of my target objects are composed. Maybe the approach should be having a method called createMasterXml with 2 arguments like findTargetIdInCsv and targetNumberOfXmlNodes and a for loop inside which parses the csv file and composes child node inside it with the groovy.xml.MarkupBuilder. But I don't know how to approach the problem.

Target logic:

  1. find csv row based on an ID variable
  2. compose the first object with values from the first found row with this ID
  3. find next csv row downwards
  4. compose the 2nd object with values from the 2nd row .....
  5. do this until the target number of objects are created
  6. if the end of the file is reached start from the top row of the file (without the header)

For example, given the csv file described above:

I get a variable docId populated with the value 100000001 which is found on the 2nd row of data in the csv file (ignoring the header);

I define a variable numberOfNodes = 3;

Then I expect an object created by this mapping:

child node 1 - ValuesFromCsvRow2

child node 2 - ValuesFromCsvRow3 

child node 3 - ValuesFromCsvRow1

Update: JSR223 PreProcessor code: (Note, with this current approach I am not able to compose the sub-nodes objects based on my intended logic described above, because the current approach does not handle parsing the CSV file and extracting values - I am missing the knowledge to do that)

//input from csv file
docType = vars.get('iDocType').toString()
docId = vars.get('iDocId').toString()
name = vars.get('iName').toString()
date = vars.get('iExpiryDate').toString()

def numberOfNodes = 3

def writer = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(writer)

xml.nodes() {
createNode(xml, numberOfNodes, 'ID0000')
}

def createNode(builder, repeat, pReqID) {
   for (int i = 0 ; i < repeat ; i++) {
       builder.object(a:'false', b:'false', pReqID:pReqID +(i+1).toString()) {
        builder.al(ad:'2021-09-20', alc:'bla', bla:'2021-09-20T11:00:00.000Z', sn:'AB8912')
        builder.doc( docType: docType, docId: docId, name: name , date:date )
       }
    }
}

def nodeAsText = writer.toString()
//log.info(nodeAsText)

vars.put('passengers3XmlObj', nodeAsText)   

The values from the code line with builder.doc is the one which I need to change on each node creation, based on the values from each line in the source csv file.

Currently, in this situation, my master object looks like this, because in each jmeter iteration I know only how to get the values from one row from the csv file, per sampler (using CSV Data Set test plan element):

<objects>
  <object a='false' b='false' pReqID='ID00001'>
    <al ad='2021-09-20' alc='bla' bla='2021-09-20T11:00:00.000Z' sn='AB8912' />
    <doc docType='P' docId='100000001' date='2024-12-10' name='Dominique' />
  </object>
  <object a='false' b='false' pReqID='ID00002'>
    <al ad='2021-09-20' alc='bla' bla='2021-09-20T11:00:00.000Z' sn='AB8912' />
    <doc docType='P' docId='100000001' date='2024-12-10' name='Dominique' />
  </object>
  <object a='false' b='false' pReqID='ID00003'>
    <al ad='2021-09-20' alc='bla' bla='2021-09-20T11:00:00.000Z' sn='AB8912' />
    <doc docType='P' docId='100000001' date='2024-12-10' name='Dominique' />
  </object>
</objects>

But, I need it to look like this, keeping in mid the target logic:

<objects>
  <object a='false' b='false' c='ID00001'>
    <al ad='2021-09-20' alc='bla' dt='2021-09-20T11:00:00.000Z' sn='AB8912' />
    <doc docType='I' docId='100000001' date='2024-12-10' name='Dominique' />
  </object>
   <object a='false' b='false' c='ID00002'>
    <al ad='2021-09-20' alc='bla' dt='2021-09-20T11:00:00.000Z' sn='AB8912' />
    <doc docType='P' docId='100000002' date='2025-11-15' name='Joyce' />
  </object>
  <object a='false' b='false' c='ID00003'>
    <al ad='2021-09-20' alc='bla' dt='2021-09-20T11:00:00.000Z' sn='AB8912' />
    <doc docType='P' docId='555551555' date='2022-12-31' name='Braiden' />
  </object>
</objects>  

Can someone please help me achieve this ?

4
  • where is your code? seems you are building xml with just few mistakes in code... Commented Oct 19, 2021 at 21:44
  • @daggett Thanks for taking an interest in my problem. I have updated the question. Commented Oct 19, 2021 at 22:20
  • I am missing the knowledge to parse the csv file, get values from each row up to the number of intended xml nodes and then pass them to the xml builder to build my xml object Commented Oct 19, 2021 at 23:12
  • stackoverflow.com/search?q=%5Bgroovy%5D+parse+csv Commented Oct 20, 2021 at 1:32

1 Answer 1

1

CSV Data Set Config by default reads next line on each iteration of each virtual user. The behaviour is controllable up to certain extend by the Sharing Mode setting but none of the sharing modes is suitable for reading the whole content of the CSV file at once.

If you want to parse all the entries from the CSV file in a single shot - do the reading/parsing in Groovy itself

Something like:

def writer = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(writer)
def pReqID = 'ID0000'
def lines = new File('test.csv').readLines()


xml.nodes() {
    1.upto(lines.size() - 1, { lineNo ->
        xml.object(a: 'false', b: 'false', pReqID: pReqID + (lineNo).toString()) {
            xml.al(ad: '2021-09-20', alc: 'bla', bla: '2021-09-20T11:00:00.000Z', sn: 'AB8912')
            xml.doc(docType: lines.get(lineNo).split(',')[0],
                    docId: lines.get(lineNo).split(',')[1],
                    name: lines.get(lineNo).split(',')[2],
                    date: lines.get(lineNo).split(',')[3])
        }
    })
}

def nodeAsText = writer.toString()
Sign up to request clarification or add additional context in comments.

1 Comment

This is really awesome! that's the first part of what I needed. Now if I have a different "docId" value in a variable which changes for each time the sampler is executed, how can I find this value each time in the csv and start composing objects from that line instead of from the beginning of the file?

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.