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.
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.
Now use the following code in order to parse your XML into a DDIC structure, and thus perform the validation:
" This is a structure generated by the framework for the
" Root element of your XML
ls_abap_data TYPE ztestramaccess_request_message,
lv_xstring TYPE xstring,
lx_root TYPE REF TO cx_root,
lx_st_error TYPE REF TO cx_st_error,
lv_output_text TYPE string.
" If you already have your XML in an xstring, you may skip this
if_input = iv_xml " This is your XML in a string (I assume it as importing parameter)
ef_output = lv_xstring
others = 0
" Here you pass the name of the DDIC
ddic_type = 'ZTESTRAMACCESS_REQUEST_MESSAGE'
" And here your XML in xstring format
xml = lv_xstring
" 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
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.
" 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( ).
The error handling is very basic in the example, you should adapt it to your own needs.
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
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.
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.
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 rammanohar.tiwari, as this post is mostly an adaptation of his original post mentioned above.