如何在空手道框架中获取Child元素

时间:2018-05-16 06:08:40

标签: karate

我需要从一个api的响应中提取子元素,然后将其动态传递给下一个api请求。

假设我有以下xml:

* def foo =
"""
<records>
  <record index="1">a</record>
  <record index="2">b</record>
  <record index="3" foo="bar">c</record>
</records>
"""

我想只提取这个:

  <record index="1">a</record>
  <record index="2">b</record>
  <record index="3" foo="bar">c</record>

我尝试了下面的选项,但没有一个工作:

* def chk = foo//records/*
* def chk = foo//records/child::*
* def chk = foo//records/descendant::*
* print chk

打印完成后,我会收到以下内容,如果我遗漏了任何内容或其他任何方式,请提出建议。谢谢!

13:51:07.046 INFO  - [print] {
  "records": {
    "record": [
      {
        "_": "a",
        "@": {
          "index": "1"
        }
      },
      {
        "_": "b",
        "@": {
          "index": "2"
        }
      },
      {
        "_": "c",
        "@": {
          "foo": "bar",
          "index": "3"
        }
      }
    ]
  }
}

1 个答案:

答案 0 :(得分:0)

编辑:看起来像一个简单的字符串替换就可以解决这个问题,如果您需要做的就是获取一组元素并将它们填充到另一个XML模板中: (我将在本答案的最后留下原来较长的答案供参考)

* def foo =
"""
<records>
  <record index="1">a</record>
  <record index="2">b</record>
  <record index="3" foo="bar">c</record>
</records>
"""
* replace foo.<records> = ''
* replace foo.</records> = ''
# you can do def bar = read('template.txt') in your case
* text bar = 
"""
<after new="namespace">
  @@foo@@
</after>
"""
* replace bar.@@foo@@ = foo
* xml bar = bar
* match bar ==
"""
<after new="namespace">
  <record index="1">a</record>
  <record index="2">b</record>
  <record index="3" foo="bar">c</record>
</after>
"""

是的,Karate本身不支持XML节点列表,通常您不需要它。而且XML具有这种特性,你总是需要一个“父”或“包装”元素。

如上所述,您确实拥有所需的所有信息。我还不清楚你需要将哪种XML传递给下一个API - 但无论如何,空手道都有一种方法。这里有2个选项。首先,迭代数据并手动发出XML:

* def foo =
"""
<records>
  <record index="1">a</record>
  <record index="2">b</record>
  <record index="3" foo="bar">c</record>
</records>
"""

* json records = foo.records.record
* def temp = <bar></bar>
* def fun = 
"""
function(r, i){ 
  karate.set('temp', '/bar/record[' + (i+1) + ']', r._); 
  karate.set('temp', '/bar/record[' + (i+1) + ']/@index', r['@'].index); 
}
"""
* eval karate.forEach(records, fun)
* match temp == 
"""
<bar>
  <record index="1">a</record>
  <record index="2">b</record>
  <record index="3">c</record>
</bar>
"""

请注意,karate.forEach仅在即将推出的0.8.0中可用,但您可以尝试0.8.0.RC3

这是另一个有趣的选项,如果您只需更改XML父级,则字符串替换将起到作用:

* replace foo.<records> = '<bar>'
* replace foo.</records> = '</bar>'
* xml bar = foo
* match bar ==
"""
<bar>
  <record index="1">a</record>
  <record index="2">b</record>
  <record index="3" foo="bar">c</record>
</bar>
"""