Search code examples
wso2apache-synapsewso2-esb

ESB Proxy XML Request inside CDATA tag in SOAP request


I am new to Apache Synapse. I need to do content-based routing and proxying of a SOAP service. However, the actual request is an XML document inside a CDATA tag in the body of the SOAP request. After routing based on the content of this document I need to use the XQuery mediator to transform the document and call the proxied service. I cannot change the WSDL of this request. Is it possible to do routing and transformation on the document that is inside the CDATA tags? When I log the request from within Synapse, I see that the XML inside the CDATA has been escaped. I've seen some posts that describe preserving the CDATA, but I'm not sure what I could do with it under either circumstance.

The request looks something like the following. I need to route the message based on the TypeOfRequest attribute:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:svc="http://integration.myservice.com">
   <soapenv:Header/>
   <soapenv:Body>
      <svc:Execute>
         <svc:myservice>
             <![CDATA[
             <?xml version="1.0" encoding="UTF-8"?>
            <myservice xmlns="http://integration.myservice.com">
                <Request TypeOfRequest="type1" RequestID="1" Echo="false">
                    <Message>
                        <Tag1510>
                            <TypeCode>10</TypeCode>
                            <SubTypeCode>00</SubTypeCode>
                        </Tag1510>
                        <Tag2000>
                            <Amount>
                                <Amount>1.00</Amount>
                            </Amount>
                        </Tag2000>
                    </Message>
                </Request>
            </myservice>
            ]]>
        </svc:myservice>
      </svc:Execute>
   </soapenv:Body>
</soapenv:Envelope> 

Solution

  • Usually you can use xslt to remove the CDATA block. In this case the <?xml ..?>will cause trouble but I think I managed to solve that using substring, wasn't able to test this though (edit: but it works according to feedback below) https://xsltfiddle.liberty-development.net/pPqsHUz/1

    An alternative would be to use the script mediator to do some stringmagic in javascript to extract the part between myservice and /myservice

    EDIT: I've added the XSLT below, in case the xsltfiddle link ever stops working:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="2.0" xmlns:svc="http://integration.myservice.com"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    
      <!-- match all elements that are not 'svc:myservice' and ignore -->
      <xsl:template match="@* | node()">
            <xsl:apply-templates select="@* | node()"/>
      </xsl:template>
    
      <!-- match svc:myservice and copy the entire CDATA string after the ?xml line -->
      <xsl:template match="svc:myservice">
         <xsl:copy>
           <xsl:value-of select="substring-after(., '?>')" disable-output-escaping="yes"/>
         </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>