Как получить значение дочернего узла из парена, предпочтительнее другого дочернего значения в Groovy readyAPI
Я пытаюсь получить значения из ответа веб-службы в readyAPI, чтобы я мог передать его другому запросу веб-службы, чтобы я мог создать автоматизированный поток тестирования.
Я пробовал разные фрагменты кода, большинство из которых представляли собой одну строку кода, которую я предпочитаю, если это возможно. Я могу взять значение из узла, набрав родительский узел по значению его атрибута. Я также могу получить родительский узел по значению атрибута дочерних узлов и использовать его для получения другого дочернего значения.
Вот несколько примеров:
Первый формат, который я могу использовать для получения значения childs:
<webserviceResponse>
<documentslist>
<document @id="1">
<payment @currency="USD" >
<amount>1250.00</amount>
</payment>
</document>
<document @id="2">
<payment @currency="JPY" >
<amount>150.00</amount>
</payment>
</document>
<document @id="3">
<payment @currency="EUR" >
<amount>1170.00</amount>
</payment>
</document>
<!-- etc. -->
</documentslist>
-----> Чтобы получить валюту для конкретного документа
def webServiceResponse = "webservice#Response"
int index=2
def currency = context.expand('${'+webServiceResponse+'//*:document[@id="['+index+']"]//*:payment/@currency}')
-----> Результатом этого является "JPY"
<webserviceResponse>
<documentslist>
<document @id="1">
<payment @currency="USD" >
<amount>1250.00</amount>
</payment>
<refund>true</refund>
</document>
<document @id="2">
<payment @currency="JPY" >
<amount>150.00</amount>
</payment>
</document>
<document @id="3">
<payment @currency="EUR" >
<amount>1170.00</amount>
</payment>
<refund>false</refund>
</document>
<!-- etc. -->
</documentslist>
-------> Чтобы получить валюту, зависящую от существования определенного узла В этом примере мы просматриваем файл сверху вниз и находим все узлы возврата, а также принимаем значение валюты, которое находится в одном блоке с второй раз мы видим возвратный узел.
def webServiceResponse = "webservice#Response"
int index=2
def currrency= context.expand('${'+webServiceResponse+'(//*:refund)['+index+']//parent::*//*:payment/@currency}')
--------> Результат для этого "EUR"
Это то, что я не могу принять значение ребенка таким же образом.
<webserviceResponse>
<documentslist>
<document>
<key>D_Computer</key>
<currency>USD</currency>
<amount>1250.00</amount>
<refund>true</refund>
</document>
<document>
<key>D_Keyboard</key>
<currency>JPY</currency>
<amount>150.00</amount>
</document>
<document>
<key>D_Monitor</key>
<currency>EUR</currency>
<amount>1170.00</amount>
<refund>false</refund>
</document>
<!-- etc. -->
</documentslist>
Моя проблема с этим, он не имеет никаких атрибутов, имеет только значения узлов. Я знаю, что у него, кстати, нет целого числа, но, возможно, я делаю неправильно, чего не понимаю.
Я хочу получить значение суммы только в зависимости от значения "ключевых" узлов, которое я собираюсь указать в сценарии.
результат должен показать:150.00
2 ответа
Спасибо за очень подробный и хорошо написанный вопрос.
Вы можете использовать ниже. Ваша проблема проста, так как в ней нет пространства имен.
Техника та же, что вы показывали, просто вам не нужно использовать @ в качестве атрибутов
def groovyUtils=new com.eviware.soapui.support.GroovyUtils(context)
def xml=groovyUtils.getXmlHolder("NameOfRequest#Response");
def currency=xml.getNodeValue("//*:documentslist/*:document[key='${key}']/*:amount");
log.info "Value of $key is " + currency
key="D_Monitor"
currency=xml.getNodeValue("//*:documentslist/*:document[key='${key}']/*:amount");
log.info "Value of $key is " + currency
Замените NameOfRequest на имя вашего запроса
Есть и альтернативный способ. Я опубликую это как отдельный ответ, чтобы не вызвать путаницу. Этот еще лучше, чем другой
Есть альтернативный способ сделать что-то, используя Hashmap, если другой ответ не работает из-за пространств имен в вашем XML
Попробуйте этот метод
Сначала мы получаем все значения с помощью getNodeValues, а затем, поскольку у нас есть пара, мы помещаем в hashmap.
Теперь вы можете получить что угодно.
def groovyUtils=new com.eviware.soapui.support.GroovyUtils(context)
def xml=groovyUtils.getXmlHolder("Request1#Response");
def keys=xml.getNodeValues("//*:documentslist/*:document/*:key")
def amounts=xml.getNodeValues("//*:documentslist/*:document/*:amount")
log.info keys.toString()
log.info amounts.toString()
HashMap h1=[:]
// Add the pair into hashmap and then retrieve
for(int i=0;i<keys.size();i++)
{
h1.put(keys[i],amounts[i])
}
def whichone="D_Computer"
log.info "Value for $whichone is " + h1.get(whichone)
Допустим, вы хотите получить более одного значения, тогда вы можете использовать массивы. т.е. взять массивы в качестве ключа, валюты, суммы, возврата
поэтому, если вы хотите получить возврат для ключа ='Z'. Используя цикл for, вы можете узнать, что Z присутствует в 3-х местах в массиве
тогда ваш возврат должен быть возвращен [3]. Аналогично валюта [3] и сумма [3]
Оба ответа имеют свою актуальность