Empty Elements in XML with Data from Excel
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Empty Elements in XML with Data from Excel
Hello community
I would like to fill my rigid XML schema with data from an Excel file. Now there are test cases, where I don't need any data from the excel (Data Driven Testing | SoapUI). How can I send the schema correctly although the field is "empty"?
Do I need to set some settings right?
For instance:
<v13:FamilyName>
<v13:PrimaryValue>XXAD</v13:PrimaryValue>
<!--0 to 5 repetitions:-->
<v13:AlternativeSpelling>
<v13:Value></v13:Value>
<v13:Source>
<v13:Code></v13:Code>
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That just proves you should make sure you read everyones posts before responding to the last. I also suggested groovy using an event handler. Unfortunately i didnt notice everyone else suggested this too!
Cheers
Rich
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@DavidSEM_Admin Sorry, I'm not back in work for another week, so I cannot dig out some examples. At work, I have pro, but at home, I don't so I don't currently have access to the pro features to help.
Groovy Script steps allow you to script some action or task. They return a value. It could be true, false, 1, 0, "hello world' or even a whole payload.
You could have one or several such steps in your test prior to the REST/SOAP request step. In the REST/SOAP step you can 'pull' in the results of the Groovy step(s).
It's a really, really neat feature and one I use a lot.
Great big caveat here, this is an untested example. There will be bugs...
In terms of reading your datasource values in a Groovy Step, here is an example...
// What the below does is read your DataSource and gets the value of CountryCode
// for the current row and assigns it into a variable called countryCode.
def countryCode = context.expand( '${DataSource#CountryCode}' );
// Initialise a var to use to return whatever we need from this script.
def returnValue = '';
// Check if countryCode contains something....
if(countryCode.length > 0){
// It does! Let's put country code inside a tag.
returnValue = "<someElement>" + countryCode + "</countryCode>"
else {
// Do nothing, there is no contry code to consider for this row.
// But, you could do something. E.g shove in a default value.
}
// Let's return our custom part of the request.
return returnValue;
Then, in your REST/SOAP Request, you can pull this into the body of the request. E.g.
<soapEnv:envelope>
<soapEnv:header/>
<soapEnv:body>
<someElementInDataSource>${DataSource#CountryCode}</someElementInDataSource>
${GroovyStepName#result}
</soapEnv:body>
</soapEnv:envelope>
In the above, it tries to show how you pull in the result of your groovy into your request. The syntax might be wrong, but what you can do is in the request window, right-click and select 'Get Data' from the context menu, that gives you access to the other steps in your test. Just select the Groovy Step and then 'result' from the pop-out menus and SoapUI will insert the command for you.
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry @richie
I saw the solution with a Groovy script and I tried it and it somehow did not work. If it helps i can provde the XML and the ExcelFile with the Data and the Script i found on the web. Maybe it is a simple mistake from my side. However, i am not very familiar with scripts and the groovy language (or any programming language). I also use SoapUI pro wîth ReadyAPI 3.3.1
This would be the XML Request:
<v1:Request>
<Document>
<v13:FamilyName>
<v13:PrimaryValue>${TestData_DataEntry#FamilyName}</v13:PrimaryValue>
</v13:FamilyName>
<v13:FirstName>
<v13:PrimaryValue>${TestData_DataEntry#FirstName}</v13:PrimaryValue>
</v13:FirstName>
<v13:DateOfBirth>${TestData_DataEntry#DateofBirth}</v13:DateOfBirth>
<v13:Nationality>
<v13:Code>${TestData_DataEntry#Nationality}</v13:Code>
</v13:Nationality>
<v13:Gender>
<v13:Code>${TestData_DataEntry#Gender}</v13:Code>
</v13:Gender>
<v13:DocumentNumber>${TestData_DataEntry#DocumentNumber}</v13:DocumentNumber>
<v13:DocumentType>
<v13:Code>${TestData_DataEntry#DocumentType}</v13:Code>
</v13:DocumentType>
<v13:ValidUntil>${TestData_DataEntry#ValidUntil}</v13:ValidUntil>
</Document>
</v1:Request>
------------------------------------
This would be the ExcelSheet where the Data is taken:
FamilyName | FirstName | DateOfBirth | Gender | DocumentNumber | ValidUntil | DoumentType |
PETER | 19760101 | 0109 | E15687 | 2023-05-12 | 6001 |
------------------------------------
This is the groovy Script i found:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def stepName = context.getCurrentStep().getLabel()
def holder = groovyUtils.getXmlHolder( stepName + "#Request")
// Find nodes that only consist of whitespaces.
for( item in holder.getDomNodes( "//*[normalize-space(.) = '' and count(*) = 0]" )){
item.parent().removeXobj()
}
// Update the request and write the updated request back to the test step.
holder.updateProperty()
context.requestContent = holder.xml
I have implemented it under "projects>events>"projectRunListener.beforeRun" and "RequestFilter.filterRequest.
Sorry again for my little knowledge..
Thank you guys
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Based on the few nodes you have in your request, I wouldn't use the script you have below, I'd create it on the fly.
I'm assuming your test looks something like....
- Datasource Step
- SOAP Request Step
- Datasource Loop
My two cents, clone the test you have so far to create a new one. That way, if my suggestion doesn't help, you've not lost anything.
In the cloned copy of the test, insert a new Groovy step so test looks like...
- Datasource Step
- Groovy Script
- SOAP Request Step
- Datasource Loop
Don't forget to update the Datasource Loop to go to the Groovy script instead of the SOAP Request.
The idea here is that for each row in the datasource, we're going to build the body of the request in the Groovy Script. Then when SoapUI reaches the SOAP Request Step, it will 'pull' the body for this request from the groovy step.
Also, clear out that code to strip empty nodes from the SOAP Request step.
In the SOAP Request Step, you'll have the whole body in the request pane, which as posted above contains...
<v1:Request>
<Document>
<v13:FamilyName>
<v13:PrimaryValue>${TestData_DataEntry#FamilyName}</v13:PrimaryValue>
</v13:FamilyName>
<v13:FirstName>
<v13:PrimaryValue>${TestData_DataEntry#FirstName}</v13:PrimaryValue>
</v13:FirstName>
<v13:DateOfBirth>${TestData_DataEntry#DateofBirth}</v13:DateOfBirth>
<v13:Nationality>
<v13:Code>${TestData_DataEntry#Nationality}</v13:Code>
</v13:Nationality>
<v13:Gender>
<v13:Code>${TestData_DataEntry#Gender}</v13:Code>
</v13:Gender>
<v13:DocumentNumber>${TestData_DataEntry#DocumentNumber}</v13:DocumentNumber>
<v13:DocumentType>
<v13:Code>${TestData_DataEntry#DocumentType}</v13:Code>
</v13:DocumentType>
<v13:ValidUntil>${TestData_DataEntry#ValidUntil}</v13:ValidUntil>
</Document>
</v1:Request>
Delete the nodes from this so it looks something like....
<v1:Request>
<Document>
${Groovy Step#result}
</Document>
</v1:Request>
The bit ${Groovy Step#result} calls the Groovy script and replaces ${Groovy Step#result} with the result from script. Bit like a placeholder.
Here's the grind.... Edit the Groovy Step and start adding checks for each node...
// Initialise the variable we're going to add our nodes into.
def returnString = '';
// Start with the first element FamilyName...
// Get family name from the datasource...
def familyName = ${TestData_DataEntry#FamilyName};
if (familyName.length() > 0) {
// There is a family name in this datasource row. Let's use it.
returnString = returnString + "<v13:FamilyName><v13:PrimaryValue>" +
familyName + "</v13:PrimaryValue></v13:FamilyName>";
}
// FirstName Element check...
def firstName = ${TestData_DataEntry#FirstName};
if (firstName.length() > 0) {
returnString = returnString + "<v13:FirstName>" +
"<v13:PrimaryValue>" + firstName + "</v13:PrimaryValue></v13:FirstName>";
}
// And so on and so on until you checked each element...
// Finally, return what we have put together...
return returnString;
Hopefully, that should then provide you with a request that is dynamic and doesn't contain any empty nodes.
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear @ChrisAdams
Thank you very much for your reply and your help. Actually this was only e part of the nodes of my request. A full request is actually much longer but i thought by showing only partly of the nodes would help to show my current "test setting" and issue.
So in this case if I build the whole body with groovy script, this would take too much time, because I have 200 different requests..
Another idea i had was to have something that deletes all empty nodes when the data are loaded from the excel, before the request will be send. But i don't know if this is possible..
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Sorry, I thought that was pretty much the request. If you have so many nodes (200?), then building a script to check each node in the way I described would be too much work.
I don't know how easy it would be to make a working script to remove the empty/redundant nodes. Maybe someone else can help with that.
Chris
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If youre running ReadyAPI!, you could create an event handler to strip out the empty elements after the data has been extracted from your source but before its injected via your REST request, so you wouldnt have to build the xml using groovy.
For the event handler groovy youd just need to identify the xpath of the attributes you want stripped.
Ta
Rich
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
HI @richie
Thank you for your answer. Could you explain a little more about your idea with the event handler? I am using ReadyAPI 3.3.1.
I did an event handler with the mentioned script in my previous messages in this topic. I did an event "RequestFilter.filterRequest" and it didn't work. What went wrong?
This was the script:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def stepName = context.getCurrentStep().getLabel()
def holder = groovyUtils.getXmlHolder(stepName + "#Request")
for( item in holder.getDomNodes( "//*[. = '']" )){
holder.removeDomNodes("//"+item.nodeName)
}

- « Previous
-
- 1
- 2
- Next »
- « Previous
-
- 1
- 2
- Next »