使用源 CSV 文件中的动态内容创建 XML object

Create XML object with dynamical content from a source CSV file

我有以下 CSV 文件:

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

使用 jmeter 的 JSR223 预处理器元素,我需要组成一个包含多个(基于参数化)child-nodes 的 XML parent 节点并且每个节点必须包含具有每个值的属性这些 CSV 行。

我认为我需要一些方法来遍历此 CSV 文件并从每一行中提取值,直到我的所有目标 object 都已组成。 也许该方法应该有一个名为 createMasterXml 的方法,带有 2 个参数,如 findTargetIdInCsvtargetNumberOfXmlNodes 以及一个 for 循环,其中解析 csv 文件并在其中组成 child 节点groovy.xml.MarkupBuilder。但我不知道如何解决这个问题。

目标逻辑:

  1. 根据 ID 变量查找 csv 行
  2. 将第一个 object 与第一个找到的具有此 ID 的行中的值组成
  3. 向下查找下一个 csv 行
  4. 用第二行的值组成第二个 object .....
  5. 执行此操作直到创建 object 的目标数量
  6. 如果到达文件末尾,则从文件的第一行开始(没有 header)

例如,给定上述 csv 文件:

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;

然后我希望通过此映射创建 object:

child node 1 - ValuesFromCsvRow2

child node 2 - ValuesFromCsvRow3 

child node 3 - ValuesFromCsvRow1

更新: JSR223 预处理器代码: (请注意,使用当前的方法,我无法根据上述预期逻辑编写 sub-nodes object,因为当前的方法不处理解析 CSV 文件和提取值 - 我缺少这样做的知识)

//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)   

带有 builder.doc 的代码行中的值是我需要根据源 csv 文件中每一行的值在每个节点创建时更改的值。

目前,在这种情况下,我的主人 object 看起来像这样,因为在每次 jmeter 迭代中,我只知道如何从每个采样器的 csv 文件的一行中获取值(使用 CSV 数据集测试计划元素):

<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>

但是,我需要它看起来像这样,保持在目标逻辑中间:

<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>  

有人可以帮我实现这个吗?

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设置但none的共享模式适合一次读取CSV文件的全部内容。

如果您想一次性解析 CSV 文件中的所有条目 - 在 Groovy 本身

中执行 reading/parsing

类似于:

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()