Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamic XSLT Transformation

Tags:

xslt

I have an incoming simple xml request below and need to transform to below SOAP message with correct name space.and in the incoming XML request the name space are not coming so while forming the SOAP message we need to take care of the name space also. Is there any XSLT code snippet which will help me to achieve that. Note - We need to do this XSLT transformation dynamically like the incoming request can be any element like "GetImageRequest" so based on this element need to construct the name space. (probably we can keep all the name space in one xml file and need to construct the SOAP message)

Incoming XML request:

<request>
<payload>
<GetImageRequest>
   <participantId>1191152220010</participantId>
   <participantCode>131029</participantCode>
   <groupCode>027198</groupCode>
   <userType>EE</userType>
   <clientName>Test</clientName>
   <shoeboxID>123444</shoeboxID>
   <imageID>45235</imageID>
</GetImageRequest>
</payload>
</request>

================== Need to Construct below SOAP message with proper namespace.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header>

   </soapenv:Header>
   <soapenv:Body>
      <get:GetShoeboxItemRequest xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/GetShoeboxItem">
         <get:participantId>1060687620010</get:participantId>
         <get:participantCode>1060687620010</get:participantCode>
         <get:groupCode>027198</get:groupCode>
         <get:userType>EE</get:userType>
         <get:clientName>Test</get:clientName>
         <get:shoeboxID>123444</get:shoeboxID>
      </get:GetShoeboxItemRequest>
   </soapenv:Body>
</soapenv:Envelope>

Need a quick help on this . XSLT code snippet would be helpful.

like image 205
user5458829 Avatar asked Sep 27 '22 10:09

user5458829


1 Answers

This transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pRequestedItemName" select="'Shoebox'"/>

 <xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
 <xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vLcItemName" select=
                "translate($pRequestedItemName, $vUpper, $vLower)"/>

 <xsl:variable name="vDynNamespace" select=
   "concat('urn:webservice/server/mobile/', $vLcItemName, '/types/v1/Get', 'Item')"/>

  <xsl:template match="/">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Header>
            </soapenv:Header>
            <soapenv:Body>
              <xsl:element name="get:Get{$pRequestedItemName}ItemRequest" 
                   namespace="{$vDynNamespace}">
                <xsl:apply-templates select="/*/*/GetImageRequest/node()"/>
              </xsl:element>
            </soapenv:Body>
        </soapenv:Envelope>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="get:{name()}" namespace="{$vDynNamespace}">
      <xsl:copy-of select="namespace::*|@*"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

When applied on the provided source XML document:

<request>
    <payload>
        <GetImageRequest>
            <participantId>1191152220010</participantId>
            <participantCode>131029</participantCode>
            <groupCode>027198</groupCode>
            <userType>EE</userType>
            <clientName>Test</clientName>
            <shoeboxID>123444</shoeboxID>
            <imageID>45235</imageID>
        </GetImageRequest>
    </payload>
</request>

produces the wanted, correct result:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <get:GetShoeboxItemRequest
         xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/GetItem">
         <get:participantId>1191152220010</get:participantId>
         <get:participantCode>131029</get:participantCode>
         <get:groupCode>027198</get:groupCode>
         <get:userType>EE</get:userType>
         <get:clientName>Test</get:clientName>
         <get:shoeboxID>123444</get:shoeboxID>
         <get:imageID>45235</get:imageID>
      </get:GetShoeboxItemRequest>
   </soapenv:Body>
</soapenv:Envelope>

Explanation:

  1. The full power of the <xsl:element> instruction is used.
  2. Use of AVT (Attribute Value Templates)
  3. The only variable part of the dynamic namespace should be provided as a global parameter by the invoker of the transformation.

If you need to construct a completely dynamic namespace (such as passed in a global parameter by the invoker of the transformation), see this answer.


UPDATE:

The OP clarified in a comment that he can have all request-specific namespaces collected in a separate XML document or in a global parameter.

Here is the solution to this clarified problem:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pRequestData">
   <r name="GetImageRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/GetShoeboxItem"/>
   <r name="SaveShoeBoxitemRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/SaveShoeboxItem"/>
   <r name="SaveClaimWithReceiptRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/SaveClaimAndReceipt"/>
   <r name="GetThumbNailImageRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/GetThumbnail"/>
   <r name="AttachReceiptwithExistingClaimRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/AttachClaimAndReceipt"/>
 </xsl:param>

 <xsl:variable name="vParams" select="document('')/*/xsl:param[@name='pRequestData']"/>

  <xsl:template match="/">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Header>
            </soapenv:Header>
            <soapenv:Body>
                <xsl:apply-templates select="/*/*/*"/>
            </soapenv:Body>
        </soapenv:Envelope>
  </xsl:template>

  <xsl:template match="*">
    <xsl:param name="pKey" select="local-name()"/>
    <xsl:element name="get:{local-name()}" namespace="{$vParams/*[@name = $pKey]/@ns}">
      <xsl:copy-of select="namespace::*|@*"/>
      <xsl:apply-templates>
        <xsl:with-param name="pKey" select="$pKey"/>
      </xsl:apply-templates>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the following XML document (the provided one with a second, differently named child of payload):

<request>
    <payload>
        <GetImageRequest>
            <participantId>1191152220010</participantId>
            <participantCode>131029</participantCode>
            <groupCode>027198</groupCode>
            <userType>EE</userType>
            <clientName>Test</clientName>
            <shoeboxID>123444</shoeboxID>
            <imageID>45235</imageID>
        </GetImageRequest>
        <SaveShoeBoxitemRequest>
            <participantId>1191152220010</participantId>
            <participantCode>131029</participantCode>
            <groupCode>027198</groupCode>
            <userType>EE</userType>
            <clientName>Test</clientName>
            <shoeboxID>123444</shoeboxID>
            <imageID>45235</imageID>
        </SaveShoeBoxitemRequest>
    </payload>
</request>

The wanted, correct (unlike "solutions" in other answers) result is produced:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
       <soapenv:Header/>
       <soapenv:Body>
          <get:GetImageRequest 
xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/GetShoeboxItem">
             <get:participantId>1191152220010</get:participantId>
             <get:participantCode>131029</get:participantCode>
             <get:groupCode>027198</get:groupCode>
             <get:userType>EE</get:userType>
             <get:clientName>Test</get:clientName>
             <get:shoeboxID>123444</get:shoeboxID>
             <get:imageID>45235</get:imageID>
          </get:GetImageRequest>
          <get:SaveShoeBoxitemRequest 
xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/SaveShoeboxItem">
             <get:participantId>1191152220010</get:participantId>
             <get:participantCode>131029</get:participantCode>
             <get:groupCode>027198</get:groupCode>
             <get:userType>EE</get:userType>
             <get:clientName>Test</get:clientName>
             <get:shoeboxID>123444</get:shoeboxID>
             <get:imageID>45235</get:imageID>
          </get:SaveShoeBoxitemRequest>
       </soapenv:Body>
    </soapenv:Envelope>
like image 143
Dimitre Novatchev Avatar answered Sep 30 '22 08:09

Dimitre Novatchev