This page contains information on standalone ReadyAPI that has been replaced with ReadyAPI.
To try the new functionality, feel free to download a ReadyAPI trial from our website.
Let's dig into the processing and validation of CDATA sections in your XML documents that are often used to embed blocks of XML data as strings inside an existing XML structure. Specifically, we are going to look at:
- Property Transfers: How to transfer values to or from an embedded XML block.
- Assertions: How to use the standard XPath assertion to assert embedded XML content.
- Validations: How to create scripts to validate the XML data of these strings given that you have a schema available.
In the end, you are going to learn how the ReadyAPI event handler can help you do all this with ease.
1. CDATA Sections
CDATA sections are used in XML documents to avoid longer blocks of text that could otherwise be interpreted as markup, for example:
<message><![CDATA[<data>some embedded xml</data>]]></message>
In this example, the text
<data>some embedded xml</data> is a string, not XML data. Another way of writing this could be:
<message><data>some embedded xml</data></message>
This is an equivalent of the previous example that uses a CDATA section. Parsing either of these examples will return the content as a string, not as parsed XML data.
If an embedded XML document contains a CDATA section, the embedded closing tag (
]]>) terminates the outer CDATA section. Therefore, you cannot embed a CDATA section straight off. You will have to temporarily terminate the outer CDATA section before inserting the terminator of the inner CDATA section. Suppose, you have the following string:
<data>some embedded xml <![CDATA[<text>with xml</text>]]></data>
To add it to an XML document, you can use standard XML entities:
<message><data>some embedded xml <![CDATA[<text>with xml</text>]]></data></message>
or split it into three strings:
<message><![CDATA[<data>some embedded xml <![CDATA[<text>with xml</text>]]]]>><![CDATA[</data>]]></message>
- The first CDATA section wraps the following text:
<data>some embedded xml <![CDATA[<text>with xml</text>]]. Note that this CDATA section does not contain the
> character that would turn the last three characters into the CDATA terminator.
- Then comes a single character
>. This character is not treated as a markup, so there is no need to convert it to the
- Another CDATA section contains the string
Either of these methods allows you to get the original string with any XML processor.
2. CDATA Sections in SoapUI
It is (unfortunately) quite common that SOAP messages contain some part of the payload in a request or response as a string, not as XML data, which has both advantages and disadvantages. In SoapUI, these XML strings are not easily validated against a schema unless you use scripting. They are not easily asserted with XPath, and using them as targets/sources for property transfers is difficult, since they are strings, not XML data. Also, the extended message viewers in ReadyAPI (Outline, Overview) show them as strings, not as markup, which can be confusing.
Suppose, you have the following response message for an item search:
Here you see the description of the item being embedded as an XML string. On the ReadyAPI Outline and Overview tabs, it is displayed as a string:
Fortunately, there are some workarounds.
3. Property Transfers and CDATA Sections
You use the Property Transfers test steps to transfer property values between requests, responses, properties, and so on (to learn more, see Transferring Property Values). A common scenario is transferring a value from a response message to the following request (for example a session ID). In the standard case, this is straightforward:
- Set the response message as a source and specify an XPath statement to obtain the desired value.
- Set the request message as a target and specify an XPath statement to insert the transferred value.
Tip: In ReadyAPI, all this is done via point-and-click wizards.
In our scenario, the XPath statement can point only to the element containing the XML message string, not "inside" it.
There are several possible solutions:
- You can use several temporary property transfers that extract CDATA XML and that use it as a source or a target property. In this case, the CDATA content will be treated as XML content and you can point to the desired node in it.
- Another approach is to use the
saxon:parse function that parses a string to an XML object.
Let's combine both approaches into an example. Suppose, you want to transfer the embedded "isle" value from the sample message above to the following search query, which also contains embedded XML data:
To transfer the value from the CDATA section of the response message to the CDATA section of the request:
Add a temporary custom property to the test case
Insert the Property Transfer test step between the requests and configure it as follows:
Create a transfer that transfers the CDATA section of the request (in the searchstring element) to the Temporary Target property:
Create another transfer that obtains the source value from the CDATA section of the response by using the
saxon:parse function and put it to the Temporary Target property:
Now you have the desired value of the searchstring element in the Temporary Target property, so transfer it back to the request with the needed value inserted:
Running these three transfers extracts the desired value from the embedded XML data in the response and writes it to the embedded XML data in the request.
4. XPath Assertions and CDATA
By using the
saxon:parse function you can also assert an XML string embedded into a CDATA element with the standard XPath processor. In ReadyAPI, you can create it easily: right-click the desired node on the Outline tab and select Add Assertion > for Content:
If you do not have ReadyAPI, add the XPath match assertion manually.
Then specify the desired XPath expression with the
5. Validation of CDATA Content
Finally we'll look at validation. The schema of the message defines only the XML string as a string, not its complex content. You can create a script that loads an XSD schema from the file system and validates the XML data in the description:
def holder = new XmlHolder( messageExchange.responseContentAsXml )
holder.namespaces["sam"] = "http://www.example.org/sample/"
def node = holder["//sam:searchResponse/sam:searchResponse/item/description"]
def factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
def schema = factory.newSchema(new StreamSource(new FileReader("..")))
def validator = schema.newValidator()
validator.validate(new StreamSource(new StringReader(node)))
Use the following XSD file for this example:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="" elementFormDefault="unqualified">
<element name="width" type="long"></element>
<element name="height" type="long"></element>
<element name="length" type="long"></element>
<element name="isle" type="string"></element>
This can come in handy if you want to validate REST/HTTP requests that do not have a formalized schema, and since Groovy can validate by using DTD and RelaxNG as well, this can be performed equally.
6. An Event Handler to the Rescue
Wouldn't it be nice if we could just remove those CDATA tags before ReadyAPIcesses the response so that it is seen as standard XML data? Sure, it wouldn't be compliant with the original schema, but it would make transfers and assertions much easier. Well, once again, event handlers in ReadyAPI can do this for us:
- Open the Project window.
- Select the Events tab and add a RequestFilter.afterRequest handler. Set its content to
def content = context.httpResponse.responseContent
content = content.replaceAll( "<!\\[CDATA\\[", "" )
content = content.replaceAll( "]]>", "" )
//log.info( content )
context.httpResponse.responseContent = content
This effectively removes any
]]> strings from the response XML, which enables SoapUI to process the entire content as XML data, allowing you to view/handle responses as standard XML data. For example, you can now see nicer formatting in the Overview view:
Also, it allows you to create property transfers and assertions right in the Outline view as usual:
Of course, this approach has some severe limitations: it depends on the response formatting, and Schema Compliance assertions will probably fail, but it might be what you need to get the job done.
No one knows APIs better than SmartBear. Find out what our Pro version of SoapUI can do to improve your testing.