Skip to Content

XML validation in graphical mapping

Hi Folks,

I need some guidance on a topic I am dealing with. The scenario is file to multiple Idocs and I need to reject the file if one or more required fields are not present. Unfortunately the XML in the file is wrapped in a soap envelope, so trying to use Schema Validation in the sender communication channel does not work as the XSD itself does not include the soap envelope, I tried and the validation failed saying it could not find the root element Envelope in the XSD.

The validation is along the lines (based on the sample XML below) and file should be rejected if:

1) If node <GetSite><Member><homeAddress><firstName/> exists (i.e. first name is nil) reject file

2) If node <GetSite><Member><homeAddress><surname/> exists (i.e. surname is nil) reject file

3) If node <GetSite><Member><deliveryAddresses><deliveryAddress><firstName/> exists (i.e. first name is nil) reject file

4) If node <GetSite><Member><deliveryAddresses><deliveryAddress><surname/> exists (i.e. surname is nil) reject file


So with the example below either condition (2) or (3) would be satisfied and the file rejected:

<GetSite>

<Member>

<emailAddress>site1@gmail.com</emailAddress>

<homeAddress>

<title>Mr<title>

<firstName>Johnny</firstName> <<<<<< throw exception if nil

<surname/> <<<<<< throw exception if nil

<homeAddress>

<deliveryAddresses/>

</Member>

<Member>

<emailAddress>site2@gmail.com</emailAddress>

<homeAddress>

<title>Mr<title>

<firstName>Bill</firstName> <<<<<< throw exception if nil

<surname>White</surname> <<<<<< throw exception if nil

<homeAddress>

<deliveryAddresses>

<deliveryAddress>

<title>Mr<title>

<firstName/> <<<<<< throw exception if nil

<surname>Brown</surname> <<<<<< throw exception if nil

</deliveryAddress>

<deliveryAddress>

<title>Mr<title>

<firstName>Tommy</firstName> <<<<<< throw exception if nil

<surname>Evans</surname> <<<<<< throw exception if nil

</deliveryAddress>

</deliveryAddresses>

</Member>

</GetSite>

Is there anyway to achieve this in a graphical mapping (perhaps a pre-step in the operation mapping)??? Perhaps using a UDF to check for the above conditions and throw an exception (RuntimeException or StreamTransformationException).

I also tried using a mapping to throw a custom exception in the Extended Receiver Determination and this worked but unfortunately the custom error text could only be seen if you drilled deep into the Administrator Log and Trace files (it was not visible in the communication channel monitor). The message in the communication channel monitor was a standard one like Error During Execution of Receiver Determination Mapping. That's a shame as it would have worked well to reject the file in the sender channel.

Your thoughts on this welcome.

Che

Add a comment
10|10000 characters needed characters exceeded

Assigned Tags

Related questions

6 Answers

  • Best Answer
    Posted on Jul 12, 2016 at 02:59 PM

    Hi Che,

    check this mapping.

    all nodes are mapped one to one. In the mapping the root node (MT_SRC) , i have used return as xml and used an UDF validateXml . The UDF tests if all conditions you stated in your query are ok or not. If the conditions are ok mapping proceeds as usual, else it throws exception and message fails in PI.

    Here is the UDF

    public String validateXml(String xml, Container container) throws StreamTransformationException
    {
      String error="";
      try
      {
       
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder;
      builder = factory.newDocumentBuilder();
      // Use String reader
         Document document = builder.parse( new InputSource(
                 new StringReader( xml ) ) );
          NodeList firstName=document.getElementsByTagName("firstName");
          int i,l=firstName.getLength();
          if(l<=0)
          {
         error="No firstName found in entire xml document";
         throw new StreamTransformationException(error);
          }
          //check for null nodes
          for(i=0;i<firstName.getLength();++i)
          {
        if(firstName.item(i).getTextContent()==null || firstName.item(i).getTextContent()=="")
        {
        error="No firstName found under parent node "+ firstName.item(i).getParentNode().getNodeName() ;
                throw new StreamTransformationException(error);
        }
          }
          NodeList surname=document.getElementsByTagName("surname");
          l=surname.getLength();
          if(l<=0)
          {
         error="No surname found in entire xml document";
         throw new StreamTransformationException(error);
          }
          //check for null nodes
          for(i=0;i<surname.getLength();++i)
          {
        if(surname.item(i).getTextContent()==null || surname.item(i).getTextContent()=="")
        {
        error="No surname found under parent node "+ surname.item(i).getParentNode().getNodeName() ;
                throw new StreamTransformationException(error);
        }
          }
          
      }
      catch(Exception e)
      {
           throw new StreamTransformationException(e.getMessage());
      }
        return "true";
    }
    

    import statements used for the UDF are

    com.sap.aii.mapping.api.*

    com.sap.aii.mapping.lookup.*

    com.sap.aii.mappingtool.tf7.rt.*

    java.io.*

    java.lang.reflect.*

    java.util.*

    javax.xml.parsers.DocumentBuilder

    javax.xml.parsers.DocumentBuilderFactory

    org.w3c.dom.Document

    org.xml.sax.InputSource

    java.io.StringReader

    org.w3c.dom.NodeList

    com.sap.aii.mapping.api.StreamTransformationException

    Now lets see the output for following inputs

    input1

    ---------

    <?xml version="1.0" encoding="UTF-8"?>

    <ns0:MT_SRC xmlns:ns0="urn:Demo/SCN">

    <GetSite><Member><emailAddress>site1@gmail.com</emailAddress><homeAddress><title>Mr</title><firstName>jhonny</firstName><surname>his</surname></homeAddress><deliveryAddresses/></Member></GetSite>

    <Header><Item1>1</Item1><Item2>2</Item2><Item3>3</Item3><Item4>1</Item4></Header>

    </ns0:MT_SRC>

    Output1

    ---------------

    <?xml version="1.0" encoding="UTF-8"?>

    <ns0:MT_TGT xmlns:ns0="urn:Demo/SCN"><Header><Item1>1</Item1><Item2>2</Item2><Item3>3</Item3><Item4>1</Item4></Header></ns0:MT_TGT>

    Input2

    ----------

    <?xml version="1.0" encoding="UTF-8"?>

    <ns0:MT_SRC xmlns:ns0="urn:Demo/SCN">

    <GetSite><Member><emailAddress>site1@gmail.com</emailAddress><homeAddress><title>Mr</title><firstName/><surname>his</surname></homeAddress><deliveryAddresses/></Member></GetSite>

    <Header><Item1>1</Item1><Item2>2</Item2><Item3>3</Item3><Item4>1</Item4></Header>

    </ns0:MT_SRC>

    output2 ------> here mapping exception is thrown as firstName node is blank

    -------------

    Compilation of MM_SCN successful Exception:[com.sap.aii.mapping.api.StreamTransformationException: No firstName found under parent node homeAddress]

    Hope this helps.

    Regards

    Anupam


    Capture.JPG (69.1 kB)
    Add a comment
    10|10000 characters needed characters exceeded

    • Hi All,

      Thanks for all your suggestions. Anupam has provided a workable solution, which I may go with that when the time comes. For now we have decided the fields are mandatory and the sender should not send blanks in any case. If blank values are passed the Idoc fails to post in ECC as expected which is acceptable for now.

      Che

  • Posted on Jul 12, 2016 at 12:54 AM

    If file itself contains soap envelope, how is it mapped/processed if schema does not contain root element? -> change xsd to contain soap envelope ... (or maybe you have soap -> IDoc scenario not File -> IDoc ?)

    Certainly you can also add "pre-mapping" either message mapping (and use "return as XML" and one UDF that make validation) or java mapping but I would try to avoid it.

    You can also write adapter module ...

    There are plenty of options.

    /k

    Add a comment
    10|10000 characters needed characters exceeded

    • Once you reviled more details, I think, the best option would be to utilise validation in inbound processing. That would require adopting xsd to current format and changing the xml->IDoc mapping. This is what I would investigate.

      if you afraid to change mapping, you can go both for adapter module (yes, it is possible to provide descriptive error) or yet another (4-th) mapping in front. It can be both java mapping or message mapping (with return as xml option ref. Anupam answer).

      All and all, 4 mappings looks bizarre to me ... try to have a proper schema and use standard validation.

      Good luck!

      /k

  • Posted on Jul 12, 2016 at 01:26 AM

    Hi Che,

    If the requirement is to throw exception only, yes raising one in the message mapping will do the trick. But that would also mean that it will raise email notifications (if you are using alerting for the interface).

    Alternately, you can use multi-mapping and there check your conditions and create the actual output if the checks fail, else create the error file in a different directory or send an email using the content as notification to business. This way, you wouldn't create extra work for technical support team to identify if the interface failed due to business validation error or if it was a technical error.

    Of course, as mentioned by Jakub, you will either way need to handle the SOAP envelope, if it is part of your file structure.

    Cheers,

    Sanjeev.

    Add a comment
    10|10000 characters needed characters exceeded

  • Posted on Jul 12, 2016 at 01:59 AM
    Add a comment
    10|10000 characters needed characters exceeded

  • Posted on Jul 12, 2016 at 11:37 AM

    Hi Che,

    You can call Java Mapping before your actual message mapping to handle this.

    You can first search the tags <firstname/> and <surname/> tags if any of the tag is not found do not create payload else create the payload.

    If payload will not be generated then mapping will fail with exception. Else mapping will be successful

    Regards,

    Rahul

    Add a comment
    10|10000 characters needed characters exceeded

  • Posted on Jul 12, 2016 at 10:32 AM

    You can evaluate these conditions in the receiver determination and proceed true to IDoc or otherwise route it to different file, say 'not processed', to complete the scenario.

    Nikhil Bose

    Add a comment
    10|10000 characters needed characters exceeded

Before answering

You should only submit an answer when you are proposing a solution to the poster's problem. If you want the poster to clarify the question or provide more information, please leave a comment instead, requesting additional details. When answering, please include specifics, such as step-by-step instructions, context for the solution, and links to useful resources. Also, please make sure that you answer complies with our Rules of Engagement.
You must be Logged in to submit an answer.

Up to 10 attachments (including images) can be used with a maximum of 1.0 MB each and 10.5 MB total.