Sunday, June 16, 2013

SoapUI: Inserting an external XML node dynamically into an existing XML Response using XmlHolder

The Problem: I have a Soap Response, and I have to modify that xml such that I insert a new XML node into response. The new XML is a string that I can declare in a groovy script or I can retrieve from a property.

Few exceptions I encountered while trying to solve the problem: CData missing, can not add external document, Can not add groovy Node class to java Node class, viceversa and etc etc etc

Hints to solve the problem on internet: There are many websites that provides sample which helps to solve a particular case, but could not exactly find the one I present here. The most useful one was here "" where in the coments he gives sample related to owner doc and importing into it.


Lets say you have a soap request and response in a test step of a test case. The body of the response is like below.
<Traveler xmlns="">
<Customer BirthDate="2001-01-01">
<Person Language="EN-US">
<Email Type="HOM" Address=""/>

And I want add a new XML node Payment to Customer. Lets say his payment information like credit card number which is an XML fragment like below. Later I will add the card number to it.

def pay="""<Payment>
<Card Type="INTERNATIONAL" Vendor="VISA" Number="">
Huntsville Townhall
<Issuer Name="Bank of Nowhere"/>

Create a new property transfer from Traveler xml in the Soap Response to copy the Customer node to a TestCase property "customer". You can do that by using the below configuration in a new Propperty transfer step after the Soap RQ/RS step.

Source: SoapRequestStepName Property: Response
declare namespace ns1='';
Target: TestCaseName Property: nodeCustomer

Add a new test step with groovy script called updatePaymentInXML. First step is to create a XmlHolder for the source XML Traveler and extract Customer node out of it.
def getXmlHolder(){
def groovyUtils = new context )
def nodeCustStr=testRunner.testCase.getProperty("nodeCustomer").getValue() "Pre Update: " + nodeCustStr
def holder = groovyUtils.getXmlHolder(nodeCustStr)
holder.namespaces["ex"] =""
return holder

Next lets get the Customer node from it as a Node.

def holder = getXmlHolder()
def nodeCustomer = holder.getDomNode("//ex:Customer")

Next lets insert payment in the customer node.

def insertPaymentInCustomer(holder, nodeCustomer, pay){
def ownerDoc=nodeCustomer.getOwnerDocument()
def payHolder=new
payHolder.namespaces["ex"] =""
def nodePay = payHolder.getDomNode("//ex:Payment")

def importedNodePay=ownerDoc.importNode(nodePay, true)
holder.updateProperty() "Post Update: " + holder.getXml()
insertPaymentInCustomer(holder, nodeCustomer, pay)

Things to note in the above snippet is that we get the owner document and import the newly extracted Payment xml node from the xml string using a new XmlHolder instance. Lets add the card number to it.

def updateCCNumberInHolder(holderIn, ccNumberIn){
testRunner.testCase.setPropertyValue("nodeCustomerUpdated",holderIn.getXml()) "Post Update: " + holderIn.getXml()
updateCCNumberInHolder(holder, testRunner.testCase.getPropertyValue("ccNumber"))

Now, the holder.getXml() gives you the latest XML with updated Payment and cc number in it. Test case property nodeCustomerUpdated has the all updated XML that you can use.