Introduction
In this blog post I will present a simple solution, but with limitations, for validation of XML Schema (XSD) in ABAP using a service consumer (Enterprise Service) and reusing some basis objects.
Use Cases
This can be useful in the following cases:
- You generate an XML in your system and you want to perform schema validation.
- You are consuming a web service, you are not using ABAP Proxies not PI and you want to validate the request and/or response.
How does it work
This technique consists in using the XSD file to generate a WSDL (a fake service description), then use the WSDL to create DDIC structures and Simple Transformations with the Enterprise Service tools. We then reuse ABAP basis classes to parse the XML into the DDIC structures. During this step a limited Schema Validation will take place.
This is mostly based on the blog post Power of the Core : Using XSD for XML Transformation in ABAP (from Ram Manohar Tiwari with the difference that we are not using it to generate an XML file, but to parse it in order to check it.
How To
Generating the Service Consumer
Follow the instructions from steps 1 and 2 of the blog post Power of the Core : Using XSD for XML Transformation in ABAP.
The Code
Now use the following code in order to parse your XML into a DDIC structure, and thus perform the validation:
DATA:
" This is a structure generated by the framework for the
" Root element of your XML
ls_abap_data TYPE ztestramaccess_request_message,
lv_xstring TYPExstring,
lx_root TYPEREF TOcx_root,
lx_st_error TYPEREF TO cx_st_error,
lv_output_text TYPEstring.
" If you already have your XML in an xstring, you may skip this
cl_secxml_helper=>string_2_utf8(
EXPORTING
if_input = iv_xml " This is your XML in a string (I assume it as importing parameter)
RECEIVING
ef_output = lv_xstring
EXCEPTIONS
others=0
).
TRY.
cl_proxy_xml_transform=>xml_xstring_to_abap(
EXPORTING
" Here you pass the name of the DDIC
ddic_type ='ZTESTRAMACCESS_REQUEST_MESSAGE'
" And here your XML in xstring format
xml = lv_xstring
IMPORTING
" Alhtough this is technically optional (in the method signature),
" you need to pass a structure with the right type, or you will
" get a short dump.
abap_data = ls_abap_data
).
" Now, in case of errors during the parsing, handle the
" exceptions.
CATCH cx_st_error INTO lx_st_error.
" This is the most common exception in case of error here
" you may want to use use the attribute XML_PATH
" easily locate the error.
WRITE lx_st_error->xml_path.
NEW-LINE.
lv_output_text = lx_st_error->get_text().
WRITE lv_output_text.
" You may also want to inspect the lx_st_error->previous
" attribute for additional information, it is filled
" in case of conversion errors.
CATCH cx_transformation_error cx_proxy_fault INTO lx_root.
" This is just to be sure...
lv_output_text = lx_st_error->get_text().
WRITE lv_output_text.
ENDTRY.
The error handling is very basic in the example, you should adapt it to your own needs.
Tweaks
You may notice some false positive conversion errors for elements with xs:dateTime type. In this case it is because the DDIC structure is created assuming a specific variation (UTC, Local, Offset). You can change it in your proxy to a less specific value and (reactivate the proxy after changing):
Limitations and other Technical Considerations
Inherited Limitations
This technique inherit all limitations that occur when you use a Service Consumer. For instance, when testing, I observed that if you have two elements of a certain XML Tag where only one is expected, this is ignored by the parser.
Another important limitation is the fact that the validation will stop at the first error, as the exceptions in this case are not resumable, so it is not possible to have a list with all errors in the XML.
Memory Consumption
In case of big XML files you may observe high memory consumption, as you could have many copies of the date (the XML, the XML in xstring format, the data in the DDIC structure).
In this case, try to explore the usage of the method XML_TO_ABAP instead of XML_XSTRING_TO_ABAP. In this case you can use one of the classes (or their sub-classes) realizing the interface IF_SXML_READER, which provide you more options for reading the content of the XML.
Final Words
This method has its limitations, but it is an easy to implement method to provide minimal XML Schema validation in ABAP reusing SAP Standard tools.
I hope this will be helpful to the community.
Special Thanks to Ram Manohar Tiwari, as this post is mostly an adaptation of his original post mentioned above.
Best Regards,
Guilherme.