2

I have a business requirement to:

  1. Put the "Request" tag and child nodes into CDATA or xml string. put in arg0 element
  2. Concat <Request> node and value from <Checkword>, then do an MD5 to it. put in arg1

I was able to do the 1st. But I don't have a clue how to do the 2nd.

here's the sample XML

<?xml version="1.0" encoding="UTF-8"?>
<ns0:MT_AddressValidation_Req><Request service="OrderFilterService" lang="zh-CN">
<Head>BSPdevelop</Head>
<Body>
<OrderFilter d_address="address"></OrderFilter>
</Body>
</Request>
<Checkword>f2209jdlwne1Q=</Checkword>
</ns0:MT_AddressValidation_Req>

So far with the XSLT I did, here is the output. my problem is the md5 encryption for arg1. I am still thinking of what to do with it.

XSLT output

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.expressservice.integration.sf.com/"><soapenv:Header/>
<soapenv:Body>
<ser:sfexpressService>
<arg0><![CDATA[<Request lang="zh-CN" service="OrderFilterService"><Head>BSPdevelop</Head><Body><OrderFilter d_address="address"/></Body></Request>]]></arg0>
<arg1></arg1>
</ser:sfexpressService>
</soapenv:Body>
</soapenv:Envelope>

Code

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no" omit-xml-declaration="yes"/>
   <xsl:template match="/">
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.expressservice.integration.sf.com/">
     <soapenv:Header/>
     <soapenv:Body>
       <ser:sfexpressService>
         <arg0>
          <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
           <xsl:copy>
            <xsl:apply-templates/>
           </xsl:copy>
          <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
         </arg0>
         <arg1></arg1>
        </ser:sfexpressService>
      </soapenv:Body>
     </soapenv:Envelope>
   </xsl:template>
   <xsl:template match="/*">
    <xsl:copy-of select="Request"/>
   </xsl:template>
</xsl:transform>

expect is that in arg1, I will be able to get the MD5 hash

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.expressservice.integration.sf.com/"><soapenv:Header/>
<soapenv:Body>
<ser:sfexpressService>
<arg0><![CDATA[<Request lang="zh-CN" service="OrderFilterService"><Head>BSPdevelop</Head><Body><OrderFilter d_address="address"/></Body></Request>]]></arg0>
<arg1>1309740fa1e193</arg1>
</ser:sfexpressService>
</soapenv:Body>
</soapenv:Envelope>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
Bryan Lo
  • 23
  • 2

1 Answers1

1

An example of an XSLT 3.0 stylesheet that uses the serialize() method to serialize the Request element as a string, and then uses a publicly available REST service to obtain an MD5 hash of a value of a value passed in a querystring parameter.

Since this REST service doesn't return well-formed XML, it needs to use the unparsed-text() method. You could host a similar service that returned a well-formed XML response and then use document() instead.

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.expressservice.integration.sf.com/">
            <soapenv:Header/>
            <soapenv:Body>
                <ser:sfexpressService>
                    <arg0>
                        <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
                        <xsl:copy>
                            <xsl:apply-templates/>
                        </xsl:copy>
                        <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
                    </arg0>
                    <arg1>
                        <xsl:apply-templates mode="hash"/>
                    </arg1>
                </ser:sfexpressService>
            </soapenv:Body>
        </soapenv:Envelope>
    </xsl:template>

    <xsl:template match="/*">
        <xsl:copy-of select="Request"/>
    </xsl:template>

    <xsl:template match="/*" mode="hash">
        <xsl:variable name="val" select="concat(Request, heckword)"/>
        <!-- delegate to an external REST service to calculate the MD5 hash of the value -->
        <xsl:variable name="hash-val" 
           select="unparsed-text(concat('https://helloacm.com/api/md5/?s=', encode-for-uri($val)))"/>
        <!-- the response from this service is wrapped in quotes, so need to trim those off -->
        <xsl:value-of select="substring($hash-val, 2, string-length($hash-val) - 2)"/>
    </xsl:template>

</xsl:transform>

With some other XSLT 2.0 processor, you would need an extension function to serialize, or you could run the content through templates in a "serialize" mode:

<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="no" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.expressservice.integration.sf.com/">
            <soapenv:Header/>
            <soapenv:Body>
                <ser:sfexpressService>
                    <arg0>
                        <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
                        <xsl:copy>
                            <xsl:apply-templates/>
                        </xsl:copy>
                        <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
                    </arg0>
                    <arg1>
                        <xsl:apply-templates mode="hash"/>
                    </arg1>
                </ser:sfexpressService>
            </soapenv:Body>
        </soapenv:Envelope>
    </xsl:template>

    <xsl:template match="/*">
        <xsl:copy-of select="Request"/>
    </xsl:template>

    <xsl:template match="/*" mode="hash">
        <!-- generate the serialized form of the Request -->
        <xsl:variable name="serialized-request">
            <xsl:apply-templates select="Request" mode="serialize"/>
        </xsl:variable>
        <xsl:variable name="val" select="concat($serialized-request, heckword)"/>
        <!-- delegate to an external REST service to calculate the MD5 hash of the value -->
        <xsl:variable name="hash-val" select="unparsed-text(concat('https://helloacm.com/api/md5/?s=', encode-for-uri($val)))"/>
        <!-- the response from this service is wrapped in quotes, so need to trim those off -->
        <xsl:value-of select="substring($hash-val, 2, string-length($hash-val) - 2)"/>
    </xsl:template>

    <xsl:template match="*" mode="serialize">
        <xsl:text>&lt;</xsl:text>
        <xsl:value-of select="name()"/>
        <xsl:apply-templates select="@*" mode="serialize" />
        <xsl:choose>
            <xsl:when test="node()">
                <xsl:text>&gt;</xsl:text>
                <xsl:apply-templates mode="serialize" />
                <xsl:text>&lt;/</xsl:text>
                <xsl:value-of select="name()"/>
                <xsl:text>&gt;</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text> /&gt;</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="@*" mode="serialize">
        <xsl:text> </xsl:text>
        <xsl:value-of select="name()"/>
        <xsl:text>="</xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>"</xsl:text>
    </xsl:template>

    <xsl:template match="text()" mode="serialize">
        <xsl:value-of select="."/>
    </xsl:template>

</xsl:transform>
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147