从源CSV文件创建具有动态内容的XML对象



我有以下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预处理器元素,我需要组成一个包含多个(基于参数化)子节点的XML父节点,并且每个节点必须包含带有这些CSV行的每个值的属性。

我认为我需要一些方法来循环这个CSV文件,并从每行提取值,直到我的所有目标对象组成。也许这种方法应该有一个叫做createMasterXml的方法,有两个参数,比如findTargetIdInCsvtargetNumberOfXmlNodes,里面有一个for循环,它解析csv文件,并用groovy.xml.MarkupBuilder在里面合成子节点。但是我不知道如何处理这个问题。

目标逻辑:

  1. 查找基于ID变量的csv行
  2. 用第一个找到的具有此ID的行中的值组成第一个对象
  3. 查找下一行csv
  4. 用第二行中的值组成第二个对象…
  5. 执行此操作,直到创建了目标数量的对象
  6. 如果到达文件的末尾,从文件的第一行开始(不带标题)

例如,给定上面描述的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;

那么我期望通过这个映射创建一个对象:

child node 1 - ValuesFromCsvRow2
child node 2 - ValuesFromCsvRow3 
child node 3 - ValuesFromCsvRow1

:JSR223预处理器代码:(注意,使用当前的方法,我无法根据上面描述的预期逻辑组合子节点对象,因为当前的方法不处理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文件中每行的值在每个节点创建时更改的值。

目前,在这种情况下,我的主对象看起来像这样,因为在每次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默认在每个虚拟用户的每次迭代中读取下一行。通过共享模式设置,这种行为在一定程度上是可控的,但是没有一种共享模式适合一次读取CSV文件的全部内容。

如果您想一次性解析CSV文件中的所有条目—在Groovy本身中执行读取/解析

类似:

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

最新更新