Editing XML files with Node.JS - node.js

So as you can see, we have this XML
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<GetECConfigResponse xmlns="urn:ecs.wsapi.broadon.com">
<Version>2.0</Version>
<DeviceId>4498122730</DeviceId>
<MessageId>ECDK-4498122730-39653600512638909</MessageId>
<TimeStamp>1599408189821</TimeStamp>
<ErrorCode>0</ErrorCode>
<ServiceStandbyMode>false</ServiceStandbyMode>
<ContentPrefixURL>http://example.com</ContentPrefixURL>
<UncachedContentPrefixURL>http://example.com</UncachedContentPrefixURL>
<SystemContentPrefixURL>http://example.com</SystemContentPrefixURL>
<SystemUncachedContentPrefixURL>http://example.com</SystemUncachedContentPrefixURL>
<EcsURL>http://example.com</EcsURL>
<IasURL>http://example.com</IasURL>
<CasURL>http://example.com</CasURL>
<NusURL>http://example.com</NusURL>
</GetECConfigResponse>
</soapenv:Body>
</soapenv:Envelope>
I do this so I can edit stuff inside the xml depending on the user's POST body but I have to edit the stuff I want, and turn it into a XML back again and send it as a response, since it's not possible with Node.JS to edit the XML directly without converting to JS or JSON
const xmlParser = require("xml2json");
var json2xml = require("json2xml");
// Current time in epoch
function currentEpoch() {
const now = Date.now()
return now
}
// Read the XML file
fs.readFile("./ecs/ecommercesoap/getecconfigresponse.xml", function (err, data) {
// Convert the XML to JSON
const xmlObj = xmlParser.toJson(data, {
object: true
})
// Get the user's body details
var deviceId = req.body["DeviceId"]
// Change XML index depending on the user
xmlObj["soapenv:Envelope"]["soapenv:Body"]["GetECConfigResponse"]["DeviceId"] = deviceId
xmlObj["soapenv:Envelope"]["soapenv:Body"]["GetECConfigResponse"]["TimeStamp"] = currentEpoch().toString()
This is where it converts xmlObj back to xml again
// Convert the JSON to XML and finalize it
const finalXml = xmlParser.toXml(xmlObj)
// Set the response's type as application/xml
res.type('application/xml');
// Sending the completely edited XML back to the user
res.send(finalXml)
And as you can see, the output changes when the converting happens. The XML below is after it's edited and parsed back into XML from JSON. If you noticed, <?xml version="1.0" encoding="utf-8"?> is also deleted, which shouldn't be.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<GetECConfigResponse xmlns="urn:ecs.wsapi.broadon.com" Version="2.0" DeviceId="4498122730" MessageId="ECDK-4498122730-39653600512638909" TimeStamp="1599505063565" ErrorCode="0" ServiceStandbyMode="false" ContentPrefixURL="http://example.com" UncachedContentPrefixURL="http://example.com" SystemContentPrefixURL="http://example.com" SystemUncachedContentPrefixURL="http://example.com" EcsURL="http://example.com" IasURL="http://example.com" CasURL="http://example.com" NusURL="http://example.com"/>
</soapenv:Body>
</soapenv:Envelope>
So I wonder what can I do to fix this, the tags start and end with <> in the original while edited one doesn't even have it. Long story short, bunch of stuff got changed. I also tried xml2js instead of xml2json but the output is still the same. I just want my output exactly same as the original file, but with my stuff changed.

In our project we have to deal with manually modifiying soap/xml in NodeJS as well - we've recently switched to fast-xml-parser and are really happy with it. I took your sample input and using the following code:
const xmlToJsonParser = require('fast-xml-parser');
const options = {
ignoreAttributes: false,
ignoreNameSpace: false,
parseNodeValue: true,
parseAttributeValue: true,
trimValues: true,
};
// xmlData refers to the xml-string
const tObj = xmlToJsonParser.getTraversalObj(xmlData, options);
const jsonObj = xmlToJsonParser.convertToJson(tObj, options);
// modify json
jsonObj["soapenv:Envelope"]["soapenv:Body"]["GetECConfigResponse"].DeviceId = 123456;
const JsonToXmlParser = require("fast-xml-parser").j2xParser;
const parser = new JsonToXmlParser({format: true, ignoreAttributes: false});
const xml = parser.parse(jsonObj);
console.log(xml);
it produces:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<GetECConfigResponse xmlns="urn:ecs.wsapi.broadon.com">
<Version>2</Version>
<DeviceId>123456</DeviceId>
<MessageId>ECDK-4498122730-39653600512638909</MessageId>
<TimeStamp>1599408189821</TimeStamp>
<ErrorCode>0</ErrorCode>
<ServiceStandbyMode>false</ServiceStandbyMode>
<ContentPrefixURL>http://example.com</ContentPrefixURL>
<UncachedContentPrefixURL>http://example.com</UncachedContentPrefixURL>
<SystemContentPrefixURL>http://example.com</SystemContentPrefixURL>
<SystemUncachedContentPrefixURL>http://example.com</SystemUncachedContentPrefixURL>
<EcsURL>http://example.com</EcsURL>
<IasURL>http://example.com</IasURL>
<CasURL>http://example.com</CasURL>
<NusURL>http://example.com</NusURL>
</GetECConfigResponse>
</soapenv:Body>
</soapenv:Envelope>
All that's left is to prepend the xml-header, as they've decided to exclude this feature from the parser (https://github.com/NaturalIntelligence/fast-xml-parser/issues/184).

Related

Modifying Soap UI request using groovy

we have a requirement of finding the number of dealers in current country.In the below xml request key-value pair will be varied for every request. Inputs to the soap request will be given in .txt file.Based on the number of inputs in .txt file i need to generate key-value pair xml tags dynamically.
**Format of Input.txt**
1.key1=Fruit,value1=Carrot,Key2=Vegetable,value2=Carrot
2.key1=Vegetable,value1=Potato
3.key1=Fruit,value1=Apple,key2=Fruit,value2=Orange,key3=Fruit,value3=Mango
SoapUI Request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET">
<soapenv:Header/>
<soapenv:Body>
<web:GetCitiesByCountry>
<web:CountryName>Ind</web:CountryName>
<web:queryParameters>
<web:key>Fruits</web:key>
<web:value>Mango</web:value>
</web:queryParameters>
<web:queryParameters>
<web:key>Vegetables</web:key>
<web:value>Carrot</web:value>
</web:queryParameters>
</web:GetCitiesByCountry>
</soapenv:Body>
</soapenv:Envelope>
You say you have the reading of the input records sorted, so I've just put some records in a map for demonstration purposes. Then, if your request payload starts off looking like:
<soap:Envelope xmlns:soap="w3.org/2003/05/soap-envelope">
<soap:Header/>
<soap:Body>
<web:GetCitiesByCountry xmlns:web="webserviceX.NET">
<web:CountryName>hello</web:CountryName>
</web:GetCitiesByCountry>
</soap:Body>
</soap:Envelope>
You can loop through your input records and append them to the request:
import groovy.xml.XmlUtil
// Assuming the input document has been read into a HashMap
def map = ['Fruits': 'Banana',
'Vegetable': 'Potato'
]
// Get testStep by it's name
def testStep = context.testCase.getTestStepByName('soapRequest')
// Parse the request
def xml = new XmlSlurper().parseText(testStep.getPropertyValue('request'))
// Loop through the map and append the key/value pairs
xml.Body.appendNode {
map.each {k, v ->
Parameters {
Key(k)
Value(v)
}
}
}
// Check the output
log.info(XmlUtil.serialize( xml ))
// Update the request
testStep.setPropertyValue('request',groovy.xml.XmlUtil.serialize( xml ))
Afterwards, your request will look like:
<soap:Envelope xmlns:soap="w3.org/2003/05/soap-envelope">
<soap:Header/>
<soap:Body>
<web:GetCitiesByCountry xmlns:web="webserviceX.NET">
<web:CountryName>hello</web:CountryName>
</web:GetCitiesByCountry>
<Parameters>
<Key>Fruits</Key>
<Value>Banana</Value>
</Parameters>
<Parameters>
<Key>Vegetable</Key>
<Value>Potato</Value>
</Parameters>
</soap:Body>
</soap:Envelope>
As you said you need to add
<Parameters> <Key>key1</Key> <Value>Value1</Value> </Parameters>
dynamically while executing groovy script
So inside your groovy script in a variable
xmlValue="<Parameters> <Key>key1</Key> <Value>Value1</Value> </Parameters>"
testRunner.testCase.setPropertyValue(xmlNodes,xmlValue)
So now your dynamic xml is in testCase property. So inside your xml where you want to place it
you can place this code
<web:CountryName>${#TestCase#xmlValue}</web:CountryName>
This way it will get added. If you pass it null,then nothing will be added in your xml.
There's some good technical solutions here, but if you buy a SoapUI license, you'll be able to access the data driven test functionality, which does exactly what you want right out of the box. No groovy scripts required.

Groovy script in SOAPUI to insert new tags in Soap request

I am using SOAP UI pro. My requirement is that, I need to write a groovy script to add few tag and elements to the previously processed request.
Below is my initial request and its name is "Certify Request" in my SOAP project
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pay="http://www.abcdefgh.com/eai/xsd/custom/Payout.xsd">
<soapenv:Header/>
<soapenv:Body>
<pay:request>
<pay:header>
<pay:applicationID>TANDEM001</pay:applicationID>
<pay:hostname>WUNS1</pay:hostname>
<pay:timestamp>${=new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(new Date())}</pay:timestamp>
<pay:correlationID>${#TestCase#CorrelationID}</pay:correlationID>
</pay:header>
<pay:input>
<pay:payoutTransactionDetails>
<pay:transferDetails>
<pay:sendCountryCode>${#TestCase#sendCountryCode}</pay:sendCountryCode>
<pay:sendAmount>
<pay:currencyCode>${#TestCase#sendCurrencyCode}</pay:currencyCode>
<pay:value multiplier="100">${#TestCase#sendAmount}</pay:value>
<pay:fxRate multiplier="100">${#TestCase#senderfxRate}</pay:fxRate>
</pay:sendAmount>
<pay:receiveCountryCode>${#TestCase#receiveCountryCode}</pay:receiveCountryCode>
<pay:receiveAmount>
<pay:currencyCode>${#TestCase#receiveCurrencyCode}</pay:currencyCode>
<pay:value multiplier="100">${#TestCase#receiveAmount}</pay:value>
<pay:fxRate multiplier="100">${#TestCase#receiverfxRate}</pay:fxRate>
</pay:receiveAmount>
<pay:overallFX multiplier="100000000">${#TestCase#OverallFX}</pay:overallFX>
</pay:transferDetails>
</pay:payoutTransactionDetails>
</pay:input>
</pay:request>
</soapenv:Body>
</soapenv:Envelope>
I would like to add below tags in it under " " tag:
<pay:senderAgent>
<pay:agentID>1760289</pay:agentID>
<pay:accountNumber>036526952</pay:accountNumber>
</pay:senderAgent>
So that my target request will be like below: (and it's name should be Initiate Request )
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pay="http://www.abcdefgh.com/eai/xsd/custom/Payout.xsd">
<soapenv:Header/>
<soapenv:Body>
<pay:request>
<pay:header>
<pay:applicationID>TANDEM001</pay:applicationID>
<pay:hostname>WUNS1</pay:hostname>
<pay:timestamp>${=new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(new Date())}</pay:timestamp>
<pay:correlationID>${#TestCase#CorrelationID}</pay:correlationID>
</pay:header>
<pay:input>
<pay:payoutTransactionDetails>
<pay:senderAgent>
<pay:agentID>${#TestCase#senderAgentID}</pay:agentID>
<pay:accountNumber>${#TestCase#senderAgentAcountNumber}</pay:accountNumber>
</pay:senderAgent>
<pay:transferDetails>
<pay:sendCountryCode>${#TestCase#sendCountryCode}</pay:sendCountryCode>
<pay:sendAmount>
<pay:currencyCode>${#TestCase#sendCurrencyCode}</pay:currencyCode>
<pay:value multiplier="100">${#TestCase#sendAmount}</pay:value>
<pay:fxRate multiplier="100">${#TestCase#senderfxRate}</pay:fxRate>
</pay:sendAmount>
<pay:receiveCountryCode>${#TestCase#receiveCountryCode}</pay:receiveCountryCode>
<pay:receiveAmount>
<pay:currencyCode>${#TestCase#receiveCurrencyCode}</pay:currencyCode>
<pay:value multiplier="100">${#TestCase#receiveAmount}</pay:value>
<pay:fxRate multiplier="100">${#TestCase#receiverfxRate}</pay:fxRate>
</pay:receiveAmount>
<pay:overallFX multiplier="100000000">${#TestCase#OverallFX}</pay:overallFX>
</pay:transferDetails>
</pay:payoutTransactionDetails>
</pay:input>
</pay:request>
</soapenv:Body>
</soapenv:Envelope>
I referred the solution on this link https://community.smartbear.com/t5/SoapUI-Pro/Using-Groovy-to-insert-new-tag-into-request-Need-help-with/m-p/124928#M28773 , however not able to succeed.
Thanks for your help
You could use a property inside a groovy script
def senderAgent=" <pay:senderAgent> ....... </pay:senderAgent>"
testRunner.testCase.setPropertyValue("Variable",senderAgent)
and then place that variable inside the XML
<pay:payoutTransactionDetails>
${#TestCase#senderAgent}
<pay:transferDetails>
So you have stored the xml value in groovy and then expanded that inside the XML

how to pull the parameter from cdata response and use it in another request using groovy in soapUi

This is my response from soapUI
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SearchAirFaresResponse xmlns="http://www.sample.com/xchange">
<SearchAirFaresResult>
<![CDATA[
<FareSearchResponse>
<MasterDetails>
<CurrencyCode>INR</CurrencyCode>
<RecStNo>1</RecStNo>
<SessionID>5705b1a6-95ac-486c-88a1f90f85e57590</SessionID>
</MasterDetails>
</FareSearchResponse>
]]>
</SearchAirFaresResult>
</SearchAirFaresResponse>
</soap:Body>
</soap:Envelope>
How to extract SessionID element which is inside CDATA using groovy script and use it in another request like
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<xch:GetMoreFares>
<xch:sGetMoreFare>
<![CDATA[
<MoreFlights>
<MasterDetails>
<NoOfResult Index="1">40</NoOfResult>
<BranchId>1</BranchId>
<SessionId>5705b1a6-95ac-486c-88a1f90f85e57590</SessionId>
</MasterDetails>
<Journey>DOM</Journey>
<ResponseType>XML</ResponseType>
<SearchType>OW</SearchType>
</MoreFlights>
]]>
</xch:sGetMoreFare>
</soap:Body>
</soap:Envelope>
3.I have been searching lot but didnt get the right one,and also am new to groovy script using soapUi , pls guide me stepwise procedure in soapUi to implement .
To do so you can use a Groovy testStep, inside it get the SOAP testStep where you've the response with desired sessionID and use a XmlSlurper to parse the response and get the CDATA value. Note that XmlSlurper treat CDATA as String so you've to parse it again. Finally save the returned value as a TestSuite or TestCase level (in the example I use TestCase):
// get your first testStep by its name
def tr = testRunner.testCase.getTestStepByName('Test Request')
// get your response
def response = tr.getPropertyValue('response')
// parse the response and find the node with CDATA content
def xml = new XmlSlurper().parseText(response)
def cdataContent = xml.'**'.find { it.name() == 'SearchAirFaresResponse' }
// XmlSlurper treat CDATA as String so you've to parse
// its content again
def cdata = new XmlSlurper().parseText(cdataContent.toString())
// finally get the SessionID node content
def sessionId = cdata.'**'.find { it.name() == 'SessionID' }
// now save this value at some level (for example testCase) in
// order to get it later
testRunner.testCase.setPropertyValue('MySessionId',sessionId.toString())
Then change a bit your second testStep to use property expansion to get the MySessionId property in your second request as ${#TestCase#MySessionId}:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<xch:GetMoreFares>
<xch:sGetMoreFare>
<![CDATA[
<MoreFlights>
<MasterDetails>
<NoOfResult Index="1">40</NoOfResult>
<BranchId>1</BranchId>
<SessionId>${#TestCase#MySessionId}</SessionId>
</MasterDetails>
<Journey>DOM</Journey>
<ResponseType>XML</ResponseType>
<SearchType>OW</SearchType>
</MoreFlights>
]]>
</xch:sGetMoreFare>
</soap:Body>
</soap:Envelope>
This is also most similar to albciff's answer, but with little variant (using reusable closure to parse).
Here is the Script Assertion for the first request step. This will avoid additional groovy script step in the test case.
Please follow the appropriate comments inline:
Script Assertion:
/**
* This is Script Assertion for the first
* request step which extracts cdata from response,
* then sessionId from extracted cdata. And
* Assigns the value at test case level, so that
* it can be used in the rest of the test steps of
* the same test case.
* However, it is possible to store the sessionId
* at Suite level as well if you want use the sessionId
* across the test cases too.
*
* */
/**
* Closure to search for certain element data
* input parameters
* xml data, element name to search
**/
def searchData = { data, element ->
def parsedData = new XmlSlurper().parseText(data)
parsedData?.'**'.find { it.name() == element} as String
}
//Assert the response
assert context.response, "Current step response is empty or null"
//Get the cdata part which is inside element "SearchAirFaresResult"
def cData = searchData(context.response,'SearchAirFaresResult')
//Assert CDATA part is not null
assert cData, "Extracted CDATA of the response is empty or null"
//Get the SessionID from cdata
def sessionId = searchData(cData, 'SessionID')
//Assert sessionId is not null or empty
assert sessionId, "Session Id is empty or null"
log.info "Session id of response $sessionId1"
//Set the session to test case level custom property
//So, that it can be used for the rest of the steps
//in the same test case
context.testCase.setPropertyValue('SESSION_ID', sessionId)
In the following test steps, you can use the saved SESSION_ID in the following ways:
If the following step is request step (REST, SOAP, HTTP, JDBC etc), then use property expansion ${#TestCase#SESSION_ID} like <SessionId>${#TestCase#SESSION_ID}</SessionId>
If the following step is groovy script, then use one of the below:
context.expand('${#TestCase#SESSION_ID}') or
context.testCase.getPropertyValue('SESSION_ID') or
testRunner.testCase.getPropertyValue('SESSION_ID')

accesing xml content from node.js

I have a bunch of XML documents in MarkLogic database.
I am working on a node.js middletier, it needs to pass on certain properties of all xml documents in a certain collection into a JSON array.
So far I have this:
var marklogic = require('marklogic');
var my = require('./my-connection.js');
var db = marklogic.createDatabaseClient(my.connInfo);
var qb = marklogic.queryBuilder;
db.documents.query(
qb.where(qb.collection("alert"))
).result( function(documents) {
console.log('The alerts collection:')
documents.forEach( function(document) {
//console.log('\nURI: ' + document.uri);
var aObj = document.content
//var alert = aObj.getElementsByTagNameNS("http://example.com/sccs/alert","alert");
console.log('Alert: ' + document.content);
});
}, function(error) {
console.log(JSON.stringify(error, null, 2));
});
Which gives me the content back.
Example result:
Alert: <?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0"?>
<obj:object xmlns:obj="http://marklogic.com/solutions/obi/object">
<obi:metadata xmlns:obi="http://marklogic.com/solutions/obi" createdBy="admin" createdDateTime="2015-09-23T20:42:48.562829Z" lastUpdatedBy="admin" lastUpdatedDateTime="2015-09-23T20:42:48.562829Z"/>
<obj:label>Active</obj:label>
<obj:type>alert</obj:type>
<obj:id>41e718eb-a2e2-49e0-939a-68bb87c1e301</obj:id>
<obj:content>
<alert xmlns="http://example.com/sccs/alert">
<obj:property sourceCount="1">
<status>Active</status>
</obj:property>
<obj:property sourceCount="1">
<position>{"type":"Point", "coordinates":[52.2, 4.3]}</position>
</obj:property>
<obj:property sourceCount="1">
<scc:id xmlns:scc="http://example.com/sccs">2a65b4cc-acee-4675-a8ba-d8c5dfaac9dd</scc:id>
</obj:property>
</alert>
</obj:content>
<obj:workspaces>
<obj:workspace id="Public"/>
</obj:workspaces>
<obj:sourceIds count="1">
<source:id xmlns:source="http://marklogic.com/solutions/obi/source">42aebdc7-41aa-4695-b514-2bb63f85d47c</source:id>
</obj:sourceIds>
</obj:object>
Question:
I want to access for example the 'obj:content' element in this content.
In the Query Console I can do this by :
var alerts = fn.collection("alert").toArray();
var aXML = alerts[2].getElementsByTagNameNS("http://example.com/sccs/alert","alert");
How can I do this from node.js?
(I do not understand the object type returned from the query in node.js)
The MarkLogic node.js API returns XML documents as strings; you'll need to use an XML parser in order to query, project, or process that XML. There are lots of modules for interacting with XML on npm, see
The best node module for XML parsing
https://www.npmjs.com/search?q=xml
You may find it easier to use a server-side transformation with MarkLogic, and convert your XML documents to JSON first: http://docs.marklogic.com/guide/node-dev/extensions#id_78179

SoapUI Mock Service Transfer Multiple Nodes

I am in a pickle.
I feel there is a simple solution to what I want to achieve, but I am at a loss to how to go about it.
Basically, I am standing up some mock Soap services.
I want to echo back an update call with that which is passed in.
My request looks like this:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
<soap:Body>
<ns2:setEvents xmlns:ns2="http://example.com/eventingservices" xmlns:ns3="http://example.com/eventing/sdo">
<setEventsRequest>
<SystemCode>ABC</SystemCode>
<Event>
<EventTypeCode>01</EventTypeCode>
</Event>
<Event>
<EventTypeCode>04</EventTypeCode>
</Event>
</setEventsRequest>
</ns2:SetEvents>
</soap:Body>
</soap:Envelope>
I then want to simply transfer the list of Events to the response. They have the same attributes as the request.
A typical response, would look like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
<soapenv:Body>
<qu:setEventsResponse xmlns:qu="http:/example.com/eventingServices">
<setEventsResponse>
<Event>
<EventTypeCode>01</EventTypeCode>
</Event>
<Event>
<EventTypeCode>04</EventTypeCode>
</Event>
</setEventsResponse>
</qu:setEventsResponse>
</soapenv:Body>
</soapenv:Envelope>
I tried using the following Groovy script, replacing the Events in the response with ${events}:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def holder = groovyUtils.getXmlHolder(mockRequest.requestContent)
def events = String.valueOf(holder.getNodeValues("//Event"))
context.setProperty("events", events);
I also tried the above without doing the string of. To no avail.
Please please help me.
I'll buy you a beer if I can get this damned thing to work!
I suppose that you have a mock service in SOAPUI configured as follows.
Operation with a response similar to:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
<soapenv:Body>
<setEventsResponse xmlns="http:/example.com/eventingServices">
<setEventsResponse>
${events}
</setEventsResponse>
</setEventsResponse>
</soapenv:Body>
</soapenv:Envelope>
And on the onRequestScript tab of your mockService you want to have the necessary script to get the <Event> nodes from the request and put it in the response using ${events} property. To do so, I recommend that you can use XmlSlurper as follows:
import groovy.xml.StreamingMarkupBuilder
// parse the request
def reqSlurper = new XmlSlurper().parseText(mockRequest.requestContent)
// find all 'Event' nodes from request
def events = reqSlurper.depthFirst().findAll { it.name() == 'Event' }
// builder to convert the nodes to string
def smb = new StreamingMarkupBuilder()
// concatenate in the string all "<Event>" nodes from request
def eventAsString = ''
events.each{
eventAsString += smb.bindNode(it)
}
// set the property to use in the response
context.setProperty("events", eventAsString);
That's all to make it work :).
Additionally note that there are some mistakes in you xmls. The request in your question is not well formed: </ns2:SetEvents> not close <ns2:setEvents> (note uppercase), and if you want that xmlns:ns2="http://example.com/eventingservices" namespace applies to all childs of <SetEvents> you have to add ns2 to all the child nodes or remove the ns2 to make it default for this subtree:<SetEvents xmlns="http://example.com/eventingservices">` (this applies also for your response)
Hope it helps,

Resources