6

I have a request which accepts 1..n items to add to basket. default request has one "item" element with some child elements, i want to add N no of items with child element i'm able to add Item parent element using creaeElementNS now i want to add child elements to "item" like following, can someone shed some light on this

<basket:item>
<basket:itemId>222</basket:itemId>
<basket:itemCode>DEF</basket:itemCode>
<basket:item>

Groovy script

def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( "createBasket#Request" )
def parentnode = holder.getDomNode( "//basket:createBasketRequest" )
def basketTotal=   holder.getDomNode( "//basket:itemsTotal" ) 
def itemsTag = requestDoc.createElementNS(parentnode.getNamespaceURI(), "item")
parentnode.insertBefore(itemsTag  , basketTotal)
holder.updateProperty()

Current Output

<basket:createBasketRequest>
<basket:item>
    <basket:itemId>111</basket:itemId>
    <basket:itemCode>ABC</basket:itemCode>
</basket:item>
<basket:item>
</basket:item>
    <basket:itemsTotal>500.00</basket:itemsTotal>
</basket:createBasketRequest>

Desired Output

<basket:createBasketRequest>
    <basket:item>
        <basket:itemId>111</basket:itemId>
        <basket:itemCode>ABC</basket:itemCode>
    </basket:item>
    <basket:item>
        <basket:itemId>222</basket:itemId>
        <basket:itemCode>DEF</basket:itemCode>
    <basket:item>
    <basket:itemsTotal>500.00</basket:itemsTotal>
</basket:createBasketRequest>

EDIT: I'm using soapUI and TestCase option, there is a GroovyScript step before add basket request step, groovy script prepares add basket request before actually sending request, for example if my testcase mentions 1 item it should request with default one item so i have no worries to add another Item elements but when my testcase says 2 items i have to create second Items elements(along with child elements) and prepare the add basket request using groovy script step before actually sending add basket request

2 Answers2

4

Not sure if it will work (I don't use SoapUI), but does this help?

def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder      = groovyUtils.getXmlHolder( "createBasket#Request" )
def parentnode  = holder.getDomNode( "//basket:createBasketRequest" )
def basketTotal = holder.getDomNode( "//basket:itemsTotal" ) 

def nodeText    = '''<basket:item>
                    |    <basket:itemId>222</basket:itemId>
                    |    <basket:itemCode>DEF</basket:itemCode>
                    |</basket:item>'''.stripMargin()

def nodeHolder  = new com.eviware.soapui.support.XmlHolder( nodeText )
def nodeItem    = nodeHolder.getDomNode( "//basket:item" )
def importNode  = requestDoc.importNode( nodeItem, true )

parentnode.insertBefore( importNode, basketTotal )

holder.updateProperty()
tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • Thanks for reply, had a quick look got (anyway i will try some more options) groovy.lang.MissingMethodException: No signature of method: org.apache.xmlbeans.impl.store.Xobj$ElementXobj.insertBefore() is applicable for argument types: (groovy.util.Node, org.apache.xmlbeans.impl.store.Xobj$ElementXobj) – StaleElementException Aug 22 '13 at 14:13
  • @StaleElementException Right, found [another page showing a possible solution](http://techdiary.bitourea.com/2013/06/soapui-inserting-external-xml-node.html), and updated my answer... Fingers crossed ;-) – tim_yates Aug 22 '13 at 14:32
  • almost working just facing problem with namespaces, i'm trying to resolve them, thanks for the help – StaleElementException Aug 23 '13 at 09:52
  • I ended up like this as i have different namespaces in requestdef itemsTag = requestDoc.createElementNS(parentnode.getNamespaceURI(), "item") def itemIdNode = requestDoc.createElementNS(parentnode2.getNamespaceURI(),"itemId") itemIdNode.store_text("222") itemsTag.appendChild(itemIdNode) def itemCodeNode = requestDoc.createElementNS(parentnode2.getNamespaceURI(),"itemCode") itemCodeNode.store_text("DEF") itemsTag.appendChild(itemCodeNode) parentnode.insertBefore(itemsTag,basketTotal) holder.updateProperty() – StaleElementException Aug 23 '13 at 15:15
  • WHat is the type of requestDoc here? – Simon Aug 19 '14 at 13:05
  • This didn't work for me, I kept getting "Use of undefined namespace prefix: basket". – Samir Aguiar Apr 12 '16 at 21:40
0

Check out Scott Davis's post on creating XML with groovy

I used MarkupBuilder to create an XML that looks exactly like what you want.

def sw = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(sw)
xml."basket:createBasketRequest"(){
    "basket:item"(){
        "basket.itemId"("111")
        "basket:itemCode"("ABC")
        }
    "basket:item"(){
        "basket.itemId"("222")
        "basket:itemCode"("DEF")
        }
    "basket:itemsTotal"("500.00")
}

log.info sw

Output i got:

<basket:createBasketRequest>
  <basket:item>
    <basket.itemId>111</basket.itemId>
    <basket:itemCode>ABC</basket:itemCode>
  </basket:item>
  <basket:item>
    <basket.itemId>222</basket.itemId>
    <basket:itemCode>DEF</basket:itemCode>
  </basket:item>
  <basket:itemsTotal>500.00</basket:itemsTotal>
</basket:createBasketRequest>

Updating response as some part of the XML already exists and nodes just have to be appended to the root.

Try this code...

import org.custommonkey.xmlunit.Diff
import org.custommonkey.xmlunit.XMLUnit
import groovy.xml.StreamingMarkupBuilder

def root = new XmlSlurper().parseText(orgXML)
root.appendNode {
    "basket:item"{
        "basket:itemID"("222")
        "basket:itemCode"("DEF")
    }

}

log.info groovy.xml.XmlUtil.serialize( root )
Abhishek Asthana
  • 1,857
  • 1
  • 31
  • 51