Skip to Content

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 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
  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):
proxy_dateTime.png

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.
To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

Leave a Reply