在SoapUI中,我想使用Groovy脚本从目录中挑选xml文件,在其中查找特定的节点树并插入到测试请求中。
让我们考虑目录res/001/data.xml
中包含内容
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.org">
<soapenv:Header/>
<soapenv:Body>
<ns:list>
<ns:item attr1="yes">
<title>Apple</title>
<quant>3</quant>
</ns:item>
<ns:item attr1="no">
<title>Banana</title>
<quant>0</quant>
</ns:item>
</ns:list>
</soapenv:Body>
</soapenv:Envelope>
肥皂请求模板:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.com">
<soapenv:Header/>
<soapenv:Body>
<ns:mylist/>
</soapenv:Body>
</soapenv:Envelope>
我尝试使用脚本中的XmlHolder将列表读入我的请求中:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def xml
def req = groovyUtils.getXmlHolder( "SendData#Request" )
req.namespaces["ns1"] = "http://examle.com"
def folder = new File('res')
if (folder.exists())
{
folder.eachDir( )
{ f ->
def xmlfile = new File( f.absolutePath + "/data.xml")
if( xmlfile.exists() )
{
def source = new com.eviware.soapui.support.XmlHolder( xmlfile.text )
source.namespaces["ns2"] = "http://example.org"
use (groovy.xml.dom.DOMCategory)
{
for( item in source.getDomNodes( "//ns2:list/ns2:item" ))
{
log.info item.xml
req["//ns1:mylist[1]"].appendChild(item.xml)
}
}
}
}
}
req.updateProperty()
我的预期结果是:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.com">
<soapenv:Header/>
<soapenv:Body>
<ns:mylist>
<ns:item attr1="yes">
<title>Apple</title>
<quant>3</quant>
</ns:item>
<ns:item attr1="no">
<title>Banana</title>
<quant>0</quant>
</ns:item>
</ns:mylist>
</soapenv:Body>
</soapenv:Envelope>
问题:如何实现这一目标?
我当前的解决方案会出错,因为req["//ns1:mylist[1]"]
为空。我已经尝试了很多不同的方法,现在它们都没有用。
答案 0 :(得分:1)
我认为问题是[]
符号在req
对象中无法正常工作(我无法弄清楚原因):req["//ns1:mylist[1]"]
还有{{1 }}
而不是使用req.namespaces["ns1"] = "http://examle.com"
尝试使用[XPath]
显式调用该函数而使用通配符代替名称而不是前缀,因为getDomNode(XPath)
似乎也不像我之前所说的那样工作( namespaces["ns1"] = "http://example.com"
对象很奇怪,req
对象无法正常工作,但这很奇怪。
最后使用xmlbeans,你无法直接从另一个文档添加一个节点,首先你必须导入节点,所以最后你的代码看起来像(我试过并使用SOAPUI 5.0.0):
source
希望这有帮助,
答案 1 :(得分:0)
这里您有一个仅用于替换XML的工作解决方案(省略了文件处理)。
@Grab('xmlunit:xmlunit:1.5')
import groovy.xml.XmlUtil
import org.custommonkey.xmlunit.XMLUnit
def xml = '''
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.org">
<soapenv:Header/>
<soapenv:Body>
<ns:list>
<ns:item attr1="yes">
<title>Apple</title>
<quant>3</quant>
</ns:item>
<ns:item attr1="no">
<title>Banana</title>
<quant>0</quant>
</ns:item>
</ns:list>
</soapenv:Body>
</soapenv:Envelope>
'''
def tmpl = '''
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.com">
<soapenv:Header/>
<soapenv:Body>
<ns:mylist/>
</soapenv:Body>
</soapenv:Envelope>
'''
def result = '''
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.com">
<soapenv:Header/>
<soapenv:Body>
<ns:mylist>
<ns:item attr1="yes">
<title>Apple</title>
<quant>3</quant>
</ns:item>
<ns:item attr1="no">
<title>Banana</title>
<quant>0</quant>
</ns:item>
</ns:mylist>
</soapenv:Body>
</soapenv:Envelope>
'''
def soapNS = new groovy.xml.Namespace("http://schemas.xmlsoap.org/soap/envelope/", 'soapenv')
def orgNS = new groovy.xml.Namespace("http://example.org", 'ns')
def comNS = new groovy.xml.Namespace("http://example.com", 'ns')
def source = new XmlParser().parseText(xml)
def target = new XmlParser().parseText(tmpl)
source[soapNS.Body][orgNS.list][0].each {
def item = target[soapNS.Body][comNS.mylist][0].appendNode('ns:item', [attr1:it.@attr1])
item.appendNode('title', it.title.text())
item.appendNode('quant', it.quant.text())
}
XMLUnit.setIgnoreWhitespace(true)
XMLUnit.setIgnoreComments(true)
XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true)
XMLUnit.setNormalizeWhitespace(true)
assert XMLUnit.compareXML(XmlUtil.serialize(target), XmlUtil.serialize(result))
如有任何问题,请随时提出。
P.S。您帖子中的预期结果不是有效的XML文件。
答案 2 :(得分:0)
非常感谢@albciff!
我最终实施的解决方案是这样的:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def xml
def req = groovyUtils.getXmlHolder( "SendData#Request" )
req.namespaces["ns1"] = "http://examle.com"
def parent = holder.getDomNode( "//ns1:myList[1]" )
def doc = parent.getOwnerDocument()
def folder = new File('res')
if (folder.exists())
{
folder.eachDir( )
{ f ->
def xmlfile = new File( f.absolutePath + "/data.xml")
if( xmlfile.exists() )
{
def source = new com.eviware.soapui.support.XmlHolder( xmlfile.text )
source.namespaces["ns2"] = "http://example.org"
// I can modify things here like that:
source["//ns2:list/item[1]/quant"] = "5"
use (groovy.xml.dom.DOMCategory)
{
for( item in source.getDomNodes( "//ns2:list/ns2:item" ))
{
def importNode = doc.importNode(item , true)
parent.appendChild( importNode )
}
}
}
}
}
req.updateProperty()
请节点:此最小示例未经过测试。