SOAP TO REST PUT Method

I have created an API PROXY in Apigee which converts REST to SOAP to REST.  There is one operation which accepts method PUT and APigee build the SOAP XML request based on the XSLT defined. This XSLT is auto generated when i imported my WSDL.  Now I see issue , when I send the request then all the data including HEADERs goes inside the BODY. 

Here is sample XSLT ( Auto Generated by Apigee using my WSDL)
```

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cmpnspc="mynamespace" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sysInfo="http://mynamespace.com/schemas/SOASolutions/SystemInfo_4" xmlns:xlmime="http://www.w3.org/2004/11/xmlmime" xmlns:xop="http://www.w3.org/2004/08/xop/include" version="1.0">

    <xsl:output encoding="utf-8" indent="yes" method="xml" omit-xml-declaration="yes"/>

    <!-- Stylesheet to inject namespaces into a document in specific places -->
    <xsl:template match="/">
        <soapenv:Envelope>
            <soapenv:Header/>
            <soapenv:Body>
                <xsl:choose>
                    <!-- Handle 'Root' wrapper added by JSON to XML policy -->
                    <xsl:when test="normalize-space(/Root)">
                        <cmpnspc:company>
                            <xsl:apply-templates select="node()|@*"/>
                        </cmpnspc:company>
                    </xsl:when>
                    <!-- Handle 'Array' wrapper added by JSON to XML policy -->
                    <xsl:when test="normalize-space(/Array)">
                        <cmpnspc:company>
                            <xsl:apply-templates select="node()|@*"/>
                        </cmpnspc:company>
                    </xsl:when>
                    <!-- If the root element is not what was in the schema, add it -->
                    <xsl:when test="not(normalize-space(/company))">
                        <cmpnspc:company>
                            <xsl:apply-templates select="node()|@*"/>
                        </cmpnspc:company>
                    </xsl:when>
                    <!-- everything checks out,  just copy the xml-->
                    <xsl:otherwise>
                        <xsl:apply-templates select="node()|@*"/>
                    </xsl:otherwise>
                </xsl:choose>
            </soapenv:Body>
        </soapenv:Envelope>
    </xsl:template>

    <xsl:template match="/Root/*" name="copy-root">
        <xsl:element name="cmpnspc:{local-name()}">
            <xsl:copy-of select="namespace::*"/>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="/Array/*" name="copy-array">
        <xsl:element name="cmpnspc:{local-name()}">
            <xsl:copy-of select="namespace::*"/>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="*[not(local-name()='Root') and not(local-name()='Array')]" name="copy-all">
        <xsl:element name="cmpnspc:{local-name()}">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
        </xsl:element>
    </xsl:template>

    <!-- template to copy the rest of the nodes -->
    <xsl:template match="comment() | processing-instruction()">
        <xsl:copy/>
    </xsl:template>
</xsl:stylesheet>


```
I am not expert on XSLT but is there anyway i can format my JSON request so that HEADER data go in HEADER tag and BODY data go in only BODY tag?
here is the request which i am sending

{
    "Header": {
        "HEADER_DATA": {
            "token": {
                "PWD": "test"
            }
        },
        "HEADER_DATA": {
            "Assertion": {
                "Version": 1,
                "schemaLocation": "dsdsd",
                "xsi": "sdsdsd",
                "AttributeStatement": {
                    "Attribute": {
                        "AttributeValue": "test",
                        "Name": "test"
                    }
                }
            },
            "saml": "sdsdd",
            "wsse": "sdsdsd"
        }
    },
    "BODY_DATA": {
        "ServiceContext": {
            "slId": "sdds",
            "TID": "2323"
        }
    }
}

 

Solved Solved
0 4 335
1 ACCEPTED SOLUTION

I put together a demonstration proxy that shows this. Just tweaked the the XSL a bit.

Here's the sample input JSON payload:

 

{
  "HEADER_DATA": {
    "token": {
      "PWD": "test"
    },
    "Assertion": {
      "Version": 1,
      "schemaLocation": "dsdsd",
      "xsi": "sdsdsd",
      "AttributeStatement": {
        "Attribute": {
          "AttributeValue": "test",
          "Name": "test"
        }
      }
    },
    "saml": "sdsdd",
    "wsse": "sdsdsd"
  },
  "BODY_DATA": {
    "ServiceContext": {
      "slId": "sdds",
      "TID": "2323"
    }
  }
}

 

and then here is the result. 

 

$ curl -i $endpoint/json-to-soap/t1
HTTP/2 200 
x-cloud-trace-context: 31d7a7fe0e3a8ed7bcc119c454477a00/3890996368923888422
content-length: 1224
apiproxy: json-to-soap r4
content-type: application/xml
date: Fri, 16 Jul 2021 16:32:46 GMT
server: apigee
via: 1.1 google, 1.1 google
alt-svc: clear

<s:Envelope xmlns:cmpnspc="mynamespace"
            xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:sysInfo="http://mynamespace.com/schemas/SOASolutions/SystemInfo_4"
            xmlns:xlmime="http://www.w3.org/2004/11/xmlmime"
            xmlns:xop="http://www.w3.org/2004/08/xop/include">
   <s:Header>
      <cmpnspc:token>
         <cmpnspc:PWD>test</cmpnspc:PWD>
      </cmpnspc:token>
      <cmpnspc:Assertion>
         <cmpnspc:Version>1</cmpnspc:Version>
         <cmpnspc:schemaLocation>dsdsd</cmpnspc:schemaLocation>
         <cmpnspc:xsi>sdsdsd</cmpnspc:xsi>
         <cmpnspc:AttributeStatement>
            <cmpnspc:Attribute>
               <cmpnspc:AttributeValue>test</cmpnspc:AttributeValue>
               <cmpnspc:Name>test</cmpnspc:Name>
            </cmpnspc:Attribute>
         </cmpnspc:AttributeStatement>
      </cmpnspc:Assertion>
      <cmpnspc:saml>sdsdd</cmpnspc:saml>
      <cmpnspc:wsse>sdsdsd</cmpnspc:wsse>
   </s:Header>
   <s:Body>
      <cmpnspc:company>
         <cmpnspc:ServiceContext>
            <cmpnspc:slId>sdds</cmpnspc:slId>
            <cmpnspc:TID>2323</cmpnspc:TID>
         </cmpnspc:ServiceContext>
      </cmpnspc:company>
   </s:Body>
</s:Envelope>

 

The proxy just uses JSONToXML and then uses this XSL:

 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:cmpnspc="mynamespace"
                xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:sysInfo="http://mynamespace.com/schemas/SOASolutions/SystemInfo_4"
                xmlns:xlmime="http://www.w3.org/2004/11/xmlmime"
                xmlns:xop="http://www.w3.org/2004/08/xop/include"
                version="1.0">

  <xsl:output encoding="utf-8"
              indent="yes"
              method="xml"
              omit-xml-declaration="yes"/>

  <xsl:template match="/Root">
    <s:Envelope>
      <s:Header>
        <xsl:apply-templates select="HEADER_DATA"/>
      </s:Header>
      <s:Body>
        <xsl:apply-templates select="BODY_DATA"/>
      </s:Body>
    </s:Envelope>
  </xsl:template>

  <xsl:template match="//HEADER_DATA" name="copy-hdr">
      <xsl:apply-templates select="node()"/>
  </xsl:template>

  <xsl:template match="//BODY_DATA" name="copy-body">
    <xsl:element name="cmpnspc:company">
      <xsl:apply-templates select="node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="/Root//*[not(self::HEADER_DATA) and not(self::BODY_DATA) ]" name="copy-all">
    <xsl:element name="cmpnspc:{local-name()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:element>
  </xsl:template>

  <!-- template to copy the rest of the nodes -->
  <xsl:template match="comment() | processing-instruction()">
    <xsl:copy/>
  </xsl:template>
</xsl:stylesheet>

 

Please find attached the example proxy.

If you are having trouble downloading the attachment from the pretty link, maybe try this link:https://www.googlecloudcommunity.com/qsqph94282/attachments/qsqph94282/cloud-apigee/66529/1/apiproxy...

View solution in original post

4 REPLIES 4

I can try to help but I am not clear on the problem we are solving. 

You showed me the inbound JSON. 

and... 

What do you want the output to look like? 

What does the output look like now? 

 

Also, why did you use the inbound JSON , shaped that way?  Did you just decide that is how you want it? 

@dchiesa1 Since this is post request I have to build the Inbound JSON request ( please let me know if there is any other way to  build inbound JSON).
Since my final SOAP XML request expect  header and Body data so in my inbound JSON  i have to send HEADER and BODY so that XSLT can put HEADER data in HEADER section and BODY data in BODY section.
So in my above Inbound JSON i am expecting following final SOAP XML request
 

<soapenv:Envelope xmlns:cmpnspc="mynamespace"
                  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:sysInfo="http://mynamespace.com/schemas/SOASolutions/SystemInfo_4"
                  xmlns:xlmime="http://www.w3.org/2004/11/xmlmime"
                  xmlns:xop="http://www.w3.org/2004/08/xop/include">
  <soapenv:Header>
    <cmpnspc:Assertion>
      <cmpnspc:Version>1</cmpnspc:Version>
      <cmpnspc:schemaLocation>dsdsd</cmpnspc:schemaLocation>
      <cmpnspc:xsi>sdsdsd</cmpnspc:xsi>
      <cmpnspc:AttributeStatement>
        <cmpnspc:Attribute>
          <cmpnspc:AttributeValue>test</cmpnspc:AttributeValue>
          <cmpnspc:Name>test</cmpnspc:Name>
        </cmpnspc:Attribute>
      </cmpnspc:AttributeStatement>
    </cmpnspc:Assertion>
    <cmpnspc:saml>sdsdd</cmpnspc:saml>
    <cmpnspc:wsse>sdsdsd</cmpnspc:wsse>

  </soapenv:Header>
  <soapenv:Body>
    <cmpnspc:company>
      <cmpnspc:BODY_DATA>
        <cmpnspc:ServiceContext>
          <cmpnspc:sourceLogicalId>sdds</cmpnspc:sourceLogicalId>
          <cmpnspc:transactionId>2323</cmpnspc:transactionId>
        </cmpnspc:ServiceContext>
      </cmpnspc:BODY_DATA>
    </cmpnspc:company>
  </soapenv:Body>
</soapenv:Envelope>



I put together a demonstration proxy that shows this. Just tweaked the the XSL a bit.

Here's the sample input JSON payload:

 

{
  "HEADER_DATA": {
    "token": {
      "PWD": "test"
    },
    "Assertion": {
      "Version": 1,
      "schemaLocation": "dsdsd",
      "xsi": "sdsdsd",
      "AttributeStatement": {
        "Attribute": {
          "AttributeValue": "test",
          "Name": "test"
        }
      }
    },
    "saml": "sdsdd",
    "wsse": "sdsdsd"
  },
  "BODY_DATA": {
    "ServiceContext": {
      "slId": "sdds",
      "TID": "2323"
    }
  }
}

 

and then here is the result. 

 

$ curl -i $endpoint/json-to-soap/t1
HTTP/2 200 
x-cloud-trace-context: 31d7a7fe0e3a8ed7bcc119c454477a00/3890996368923888422
content-length: 1224
apiproxy: json-to-soap r4
content-type: application/xml
date: Fri, 16 Jul 2021 16:32:46 GMT
server: apigee
via: 1.1 google, 1.1 google
alt-svc: clear

<s:Envelope xmlns:cmpnspc="mynamespace"
            xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:sysInfo="http://mynamespace.com/schemas/SOASolutions/SystemInfo_4"
            xmlns:xlmime="http://www.w3.org/2004/11/xmlmime"
            xmlns:xop="http://www.w3.org/2004/08/xop/include">
   <s:Header>
      <cmpnspc:token>
         <cmpnspc:PWD>test</cmpnspc:PWD>
      </cmpnspc:token>
      <cmpnspc:Assertion>
         <cmpnspc:Version>1</cmpnspc:Version>
         <cmpnspc:schemaLocation>dsdsd</cmpnspc:schemaLocation>
         <cmpnspc:xsi>sdsdsd</cmpnspc:xsi>
         <cmpnspc:AttributeStatement>
            <cmpnspc:Attribute>
               <cmpnspc:AttributeValue>test</cmpnspc:AttributeValue>
               <cmpnspc:Name>test</cmpnspc:Name>
            </cmpnspc:Attribute>
         </cmpnspc:AttributeStatement>
      </cmpnspc:Assertion>
      <cmpnspc:saml>sdsdd</cmpnspc:saml>
      <cmpnspc:wsse>sdsdsd</cmpnspc:wsse>
   </s:Header>
   <s:Body>
      <cmpnspc:company>
         <cmpnspc:ServiceContext>
            <cmpnspc:slId>sdds</cmpnspc:slId>
            <cmpnspc:TID>2323</cmpnspc:TID>
         </cmpnspc:ServiceContext>
      </cmpnspc:company>
   </s:Body>
</s:Envelope>

 

The proxy just uses JSONToXML and then uses this XSL:

 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:cmpnspc="mynamespace"
                xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:sysInfo="http://mynamespace.com/schemas/SOASolutions/SystemInfo_4"
                xmlns:xlmime="http://www.w3.org/2004/11/xmlmime"
                xmlns:xop="http://www.w3.org/2004/08/xop/include"
                version="1.0">

  <xsl:output encoding="utf-8"
              indent="yes"
              method="xml"
              omit-xml-declaration="yes"/>

  <xsl:template match="/Root">
    <s:Envelope>
      <s:Header>
        <xsl:apply-templates select="HEADER_DATA"/>
      </s:Header>
      <s:Body>
        <xsl:apply-templates select="BODY_DATA"/>
      </s:Body>
    </s:Envelope>
  </xsl:template>

  <xsl:template match="//HEADER_DATA" name="copy-hdr">
      <xsl:apply-templates select="node()"/>
  </xsl:template>

  <xsl:template match="//BODY_DATA" name="copy-body">
    <xsl:element name="cmpnspc:company">
      <xsl:apply-templates select="node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="/Root//*[not(self::HEADER_DATA) and not(self::BODY_DATA) ]" name="copy-all">
    <xsl:element name="cmpnspc:{local-name()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:element>
  </xsl:template>

  <!-- template to copy the rest of the nodes -->
  <xsl:template match="comment() | processing-instruction()">
    <xsl:copy/>
  </xsl:template>
</xsl:stylesheet>

 

Please find attached the example proxy.

If you are having trouble downloading the attachment from the pretty link, maybe try this link:https://www.googlecloudcommunity.com/qsqph94282/attachments/qsqph94282/cloud-apigee/66529/1/apiproxy...

@dchiesa1  Awesome .. It worked as expected. Your are champ.