如何从响应中获取 cdata 中的属性值并在其他请求中使用它
how to get the attribute value inside cdata from the response and use it in other request
这是我的回复,如何获取HIndex
属性值?
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<HResponse xmlns="http://demo.org/">
<HResult>
<![CDATA[
<HRS>
<Header>
<Currency>INR</Currency>
<SessionId>1313123123123123123</SessionId>
</Header>
<HotelDetails>
<Stay></Stay>
<Hotel HIndex="1701" PrefContract="" HDIndex="28">
<HNm> Demo</HNm>
<HImg>demo</HImg>
</Hotel>
<Hotel HIndex="1702" PrefContract="" HDIndex="29">
<HNm> Demo</HNm>
<HImg>demo</HImg>
</Hotel>
<Hotel HIndex="1703" PrefContract="" HDIndex="30">
<HNm> Demo</HNm>
<HImg>demo</HImg>
</Hotel>
</HotelDetails>
</HRS>
]]>
</HResult>
</HResponse>
</soap:Body>
</soap:Envelope>
我想在另一个 request.Am 中使用 HIndex
值能够 select 另一个节点值。但是,当我 selecting 属性时,我得到 null
值
您可以使用 Groovy 脚本 testStep 来解析您的 SOAP testStep 响应。更确切地说,使用 XmlSlurper
来解析您的响应,通过标签名称在 slurper 中找到 CDATA
,并再次解析 CDATA
,因为 XmlSlurper
returns CDATA
作为 String
。最后通过名称找到所需的节点,然后使用 node.@attributeName
表示法访问其属性值。像这样的东西必须适合你的情况:
def xml = '''<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<HResponse xmlns="http://demo.org/">
<HResult>
<![CDATA[
<HRS>
<Header>
<Currency>INR</Currency>
<SessionId>1313123123123123123</SessionId>
</Header>
<HotelDetails>
<Stay></Stay>
<Hotel HIndex="1701" PrefContract="" HDIndex="28">
<HNm> Demo</HNm>
<HImg>demo</HImg>
</Hotel>
<Hotel HIndex="1702" PrefContract="" HDIndex="29">
<HNm> Demo</HNm>
<HImg>demo</HImg>
</Hotel>
<Hotel HIndex="1703" PrefContract="" HDIndex="30">
<HNm> Demo</HNm>
<HImg>demo</HImg>
</Hotel>
</HotelDetails>
</HRS>
]]>
</HResult>
</HResponse>
</soap:Body>
</soap:Envelope>'''
def slurper = new XmlSlurper().parseText(xml)
def cdataAsStr = slurper.'**'.find { it.name() == 'HResult' }.toString()
def cdataSlurper = new XmlSlurper().parseText(cdataAsStr)
// get all HIndex attribute values from `<Hotel>`
def hIndexValues = cdataSlurper.'**'.findAll { it.name() == 'Hotel' }*.@HIndex as List
备注:
- 在您的问题中,
CDATA
中的 Xml 格式不正确,请使用 <Stay></Stay>
而不是 <Stay></stay>
(注意小写)。
- 如果您只对第一个
<Hotel>
中的属性值感兴趣,则访问列表中的第一个元素:hIndexValues[0]
.
- 如果您想从 SOAP testStep 中获取 Xml 内容,而不是示例中的
String
,请使用:
testRunner.testCase.getTestStepByName('TestStepName').getPropertyValue('response')
定义 def xml
对象。
- 要在其他 testSteps 中使用属性值,请将其保存在某个级别(例如 testCase
testRunner.testCase.setPropertyValue('myAttrValue',hIndexValues[0].toString())
),然后在其他 testStep 请求中使用 property expansion 符号 ${#TestCase#myAttrValue}
.
如果您想在 Script Assertion 而不是 Groovy testStep 中使用上述脚本,您可以使用与上面相同的脚本只是改变了你从 testStep:
获得响应 Xml 的方式
// in the script assertion you can access the
// response from the current testStep simply with
// messageExchange.getResponseContent()
def xml = messageExchange.getResponseContent()
def slurper = new XmlSlurper().parseText(xml)
def cdataAsStr = slurper.'**'.find { it.name() == 'HResult' }.toString()
def cdataSlurper = new XmlSlurper().parseText(cdataAsStr)
// get all HIndex attribute values from `<Hotel>`
def hIndexValues = cdataSlurper.'**'.findAll { it.name() == 'Hotel' }*.@HIndex as List
这是第一个请求步骤的 Script Assertion
。这将避免测试用例中的额外 groovy 脚本步骤。
请在线关注相应的评论:
/**
* This is Script Assertion for the first
* request step which extracts cdata from response,
* then HIndex'es from extracted cdata. And
* Assigns first value at test case level, so that
* it can be used in the rest of the test steps of
* the same test case.
* */
/**
* Closure to parse and retrieve the data
* retrieves element or attribute
*/
def searchData = { data, item, itemType ->
def parsedData = new XmlSlurper().parseText(data)
if ('attribute' == itemType) {
return parsedData?.'**'.findAll{it.@"$item".text()}*.@"$item"
}
parsedData?.'**'.find { it.name() == item} as String
}
//Assert response xml
assert context.response, "Response data is empty or null"
//Get the CDATA from response which is inside of HResult
def cData = searchData(context.response, 'HResult', 'element')
//Assert retrieved CDATA is not empty
assert cData, "Data inside of HResult is empty or null"
//Get the HIndex list
def hIndexes = searchData(cData, 'HIndex', 'attribute')
//Print list of hIndexes
log.info hIndexes
//Print the first in the list
log.info "First HIndex is : ${hIndexes?.first()}"
//Print the last in the list
log.info "Last HIndex is : ${hIndexes?.last()}"
//Use the required HIndex from the list
context.testCase.setPropertyValue('HINDEX', hIndexes?.first().toString())
//or the below one using index
//context.testCase.setPropertyValue('HINDEX', hIndexes[0]?.toString())
在接下来的测试步骤中,您可以通过以下方式使用保存的HINDEX
:
- 如果接下来的步骤是请求步骤(REST、SOAP、HTTP、JDBC 等),则使用 property expansion
${#TestCase#HINDEX}
如 <Index>${#TestCase#HINDEX}</Index>
- 如果以下步骤是 groovy 脚本,则使用以下之一:
context.expand('${#TestCase#HINDEX}')
或
context.testCase.getPropertyValue('HINDEX')
或
testRunner.testCase.getPropertyValue('HINDEX')
您可以快速尝试并执行来自 here 的脚本。
这是我的回复,如何获取
HIndex
属性值?<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <HResponse xmlns="http://demo.org/"> <HResult> <![CDATA[ <HRS> <Header> <Currency>INR</Currency> <SessionId>1313123123123123123</SessionId> </Header> <HotelDetails> <Stay></Stay> <Hotel HIndex="1701" PrefContract="" HDIndex="28"> <HNm> Demo</HNm> <HImg>demo</HImg> </Hotel> <Hotel HIndex="1702" PrefContract="" HDIndex="29"> <HNm> Demo</HNm> <HImg>demo</HImg> </Hotel> <Hotel HIndex="1703" PrefContract="" HDIndex="30"> <HNm> Demo</HNm> <HImg>demo</HImg> </Hotel> </HotelDetails> </HRS> ]]> </HResult> </HResponse> </soap:Body> </soap:Envelope>
我想在另一个 request.Am 中使用
HIndex
值能够 select 另一个节点值。但是,当我 selecting 属性时,我得到null
值
您可以使用 Groovy 脚本 testStep 来解析您的 SOAP testStep 响应。更确切地说,使用 XmlSlurper
来解析您的响应,通过标签名称在 slurper 中找到 CDATA
,并再次解析 CDATA
,因为 XmlSlurper
returns CDATA
作为 String
。最后通过名称找到所需的节点,然后使用 node.@attributeName
表示法访问其属性值。像这样的东西必须适合你的情况:
def xml = '''<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<HResponse xmlns="http://demo.org/">
<HResult>
<![CDATA[
<HRS>
<Header>
<Currency>INR</Currency>
<SessionId>1313123123123123123</SessionId>
</Header>
<HotelDetails>
<Stay></Stay>
<Hotel HIndex="1701" PrefContract="" HDIndex="28">
<HNm> Demo</HNm>
<HImg>demo</HImg>
</Hotel>
<Hotel HIndex="1702" PrefContract="" HDIndex="29">
<HNm> Demo</HNm>
<HImg>demo</HImg>
</Hotel>
<Hotel HIndex="1703" PrefContract="" HDIndex="30">
<HNm> Demo</HNm>
<HImg>demo</HImg>
</Hotel>
</HotelDetails>
</HRS>
]]>
</HResult>
</HResponse>
</soap:Body>
</soap:Envelope>'''
def slurper = new XmlSlurper().parseText(xml)
def cdataAsStr = slurper.'**'.find { it.name() == 'HResult' }.toString()
def cdataSlurper = new XmlSlurper().parseText(cdataAsStr)
// get all HIndex attribute values from `<Hotel>`
def hIndexValues = cdataSlurper.'**'.findAll { it.name() == 'Hotel' }*.@HIndex as List
备注:
- 在您的问题中,
CDATA
中的 Xml 格式不正确,请使用<Stay></Stay>
而不是<Stay></stay>
(注意小写)。 - 如果您只对第一个
<Hotel>
中的属性值感兴趣,则访问列表中的第一个元素:hIndexValues[0]
. - 如果您想从 SOAP testStep 中获取 Xml 内容,而不是示例中的
String
,请使用:testRunner.testCase.getTestStepByName('TestStepName').getPropertyValue('response')
定义def xml
对象。 - 要在其他 testSteps 中使用属性值,请将其保存在某个级别(例如 testCase
testRunner.testCase.setPropertyValue('myAttrValue',hIndexValues[0].toString())
),然后在其他 testStep 请求中使用 property expansion 符号${#TestCase#myAttrValue}
.
如果您想在 Script Assertion 而不是 Groovy testStep 中使用上述脚本,您可以使用与上面相同的脚本只是改变了你从 testStep:
获得响应 Xml 的方式// in the script assertion you can access the
// response from the current testStep simply with
// messageExchange.getResponseContent()
def xml = messageExchange.getResponseContent()
def slurper = new XmlSlurper().parseText(xml)
def cdataAsStr = slurper.'**'.find { it.name() == 'HResult' }.toString()
def cdataSlurper = new XmlSlurper().parseText(cdataAsStr)
// get all HIndex attribute values from `<Hotel>`
def hIndexValues = cdataSlurper.'**'.findAll { it.name() == 'Hotel' }*.@HIndex as List
这是第一个请求步骤的 Script Assertion
。这将避免测试用例中的额外 groovy 脚本步骤。
请在线关注相应的评论:
/**
* This is Script Assertion for the first
* request step which extracts cdata from response,
* then HIndex'es from extracted cdata. And
* Assigns first value at test case level, so that
* it can be used in the rest of the test steps of
* the same test case.
* */
/**
* Closure to parse and retrieve the data
* retrieves element or attribute
*/
def searchData = { data, item, itemType ->
def parsedData = new XmlSlurper().parseText(data)
if ('attribute' == itemType) {
return parsedData?.'**'.findAll{it.@"$item".text()}*.@"$item"
}
parsedData?.'**'.find { it.name() == item} as String
}
//Assert response xml
assert context.response, "Response data is empty or null"
//Get the CDATA from response which is inside of HResult
def cData = searchData(context.response, 'HResult', 'element')
//Assert retrieved CDATA is not empty
assert cData, "Data inside of HResult is empty or null"
//Get the HIndex list
def hIndexes = searchData(cData, 'HIndex', 'attribute')
//Print list of hIndexes
log.info hIndexes
//Print the first in the list
log.info "First HIndex is : ${hIndexes?.first()}"
//Print the last in the list
log.info "Last HIndex is : ${hIndexes?.last()}"
//Use the required HIndex from the list
context.testCase.setPropertyValue('HINDEX', hIndexes?.first().toString())
//or the below one using index
//context.testCase.setPropertyValue('HINDEX', hIndexes[0]?.toString())
在接下来的测试步骤中,您可以通过以下方式使用保存的HINDEX
:
- 如果接下来的步骤是请求步骤(REST、SOAP、HTTP、JDBC 等),则使用 property expansion
${#TestCase#HINDEX}
如<Index>${#TestCase#HINDEX}</Index>
- 如果以下步骤是 groovy 脚本,则使用以下之一:
context.expand('${#TestCase#HINDEX}')
或
context.testCase.getPropertyValue('HINDEX')
或
testRunner.testCase.getPropertyValue('HINDEX')
您可以快速尝试并执行来自 here 的脚本。