1

This first time I am dealing with xslt creations, finding it really tricky.

I have request XML and using xslt it is supposed to generate XML with below mentioned o/p.

Utility performing this operation is already built in C#. I need to write XSLT that will correctly read values from XML and create new XML with expected format.

I am trying to write XSLT to transform XML(i/p) :

    <s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" 
    xmlns:s="http://www.w3.org/2003/05/soap-envelope">
    <s:Body>
        <ExecuteESI xmlns="http://TTTT.com/Enterprise/ServiceGateways/">
            <context xmlns:b="http://TTTT.com/Enterprise/ServiceGateways/Core/Contracts/" 
                xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                <request xmlns:b="http://TTTT.com/Enterprise/ServiceGateways/ExternalService/Request/" 
                    xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                    <b:Message>
                        <ns2:ReqProv xmlns:ns2="http://TTTT.com/TTTT/TTTTestJSONESIRequest/">
                            <ns2:CID>TTTT</ns2:CID> 
                            <ns2:TIME>18732081720160855</ns2:TIME> 
                            <ns2:HASH>40dad29c4ae9303c975639f7700bf517e6e72fbf5723c7905a74fde0d5452da0</ns2:HASH> 
                        </ns2:ReqProv>
                    </b:Message>
                </request>
            </context>
        </ExecuteESI>
    </s:Body>
</s:Envelope>

to Below mentioned format (o/p):

<?xml version="1.0" encoding="UTF-8"?>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">CID=TTTT&amp;TIME=18732081720160855&amp;HASH=40dad29c4ae9303c975639f7700bf517e6e72fbf5723c7905a74fde0d545</string>

I have written following XSLT, which doesn't work

    <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:ns="http://asurion.com/TTTT/TTTTTestJSONESIRequest/"
                xmlns="http://schemas.microsoft.com/2003/10/Serialization/"
                exclude-result-prefixes="msxsl xsl ns">
  <xsl:output method="xml" />
  <xsl:template match="/">

    <xsl:variable name="CID">
      <xsl:value-of select="./ns:ReqProv/ns:CID"/>
    </xsl:variable>
    <xsl:variable name="TIME">
      <xsl:value-of select="./ns:ReqProv/ns:TIME"/>
    </xsl:variable>
    <xsl:variable name="HASH">
      <xsl:value-of select="./ns:ReqProv/ns:HASH"/>
    </xsl:variable>

    CID=<xsl:value-of select="$CID" />&amp;TIME=<xsl:value-of select="$TIME" />&amp;HASH=<xsl:value-of select="$HASH" />

  </xsl:template>

</xsl:stylesheet>

I have tried different combinations of <xsl:value-of... and <xsl:template match... and <xsl:template name.... but nothings seems to work.

Filburt
  • 17,626
  • 12
  • 64
  • 115
VishalP
  • 13
  • 3
  • Post the required output. – Rudramuni TP Aug 18 '16 at 13:04
  • Using the [concat() function](http://stackoverflow.com/q/10395488/205233) in combination with `` should give you the desired result. BTW: Since it lloks like a SOAP service response, do you really need the transformed Xml or couldn't you simply de-serialize the whole response and access the properties to get the desired string? – Filburt Aug 18 '16 at 13:05
  • 1
    @RudramuniTP OP already specified it as *below mentioned format* – Filburt Aug 18 '16 at 13:06
  • 1
    However it would be helpful to post the *actual output*, i.e. when the code "doesn't work", what does it do instead? – LarsH Aug 18 '16 at 13:10

3 Answers3

2

There are numerous problems with your attempt - the most serious one is using the wrong namespace. Try instead:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://TTTT.com/TTTT/TTTTestJSONESIRequest/"
xmlns="http://schemas.microsoft.com/2003/10/Serialization/"
exclude-result-prefixes="ns">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
    <string>
        <xsl:text>CID=</xsl:text>
        <xsl:value-of select="//ns:ReqProv/ns:CID"/>

        <xsl:text>@amp;TIME=</xsl:text>
        <xsl:value-of select="//ns:ReqProv/ns:TIME"/>

        <xsl:text>@amp;HASH=</xsl:text>
        <xsl:value-of select="//ns:ReqProv/ns:HASH"/>
    </string>
</xsl:template>

</xsl:stylesheet>

Note:

  • there is very little point in defining a variable for something you only need once;

  • it is much more convenient to use the xsl:text instruction when outputting literal text; it also makes the code easier to read and maintain.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • To clarify the second bullet point for the reader ... the `xsl:text` instruction allows you to format your XSLT template on multiple lines, without the end-of-line characters becoming part of the template output (result). So you can string together a bunch of XSLT code without having to put it all on one line, even when you want your result to consist of just one line. – LarsH Aug 19 '16 at 13:25
  • Point taken that defining a variable for a value needed only once doesn't save processing time or length of code. But in some cases it documents what a particular value (named by a variable) is intended to consist of, which makes the code more readable and maintainable. It can also help separate the concerns of output format (where the variable is used) from input format. Then if one of those changes, it's easier to update the code because the two are not mixed. I'm not saying it's better to use a variable in this case, just that it is often a valid choice. – LarsH Aug 19 '16 at 13:32
1

Try this:

<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:msxsl="urn:schemas-microsoft-com:xslt"
            xmlns:ns="http://asurion.com/TTTT/TTTTTestJSONESIRequest/"
            xmlns="http://schemas.microsoft.com/2003/10/Serialization/"
            xmlns:s="http://www.w3.org/2003/05/soap-envelope"
            xmlns:ns2="http://TTTT.com/TTTT/TTTTestJSONESIRequest/"
            exclude-result-prefixes="msxsl xsl ns">
<xsl:output method="xml" />
<xsl:template match="/">

<xsl:variable name="CID">
  <xsl:value-of select="//ns2:ReqProv/ns2:CID"/>
</xsl:variable>
<xsl:variable name="TIME">
  <xsl:value-of select="//ns2:ReqProv/ns2:TIME"/>
</xsl:variable>
<xsl:variable name="HASH">
  <xsl:value-of select="//ns2:ReqProv/ns2:HASH"/>
</xsl:variable>

<xsl:element name="string">CID=<xsl:value-of select="$CID" />&amp;TIME=<xsl:value-of select="$TIME" />&amp;HASH=<xsl:value-of select="$HASH" /></xsl:element>

</xsl:template>

</xsl:stylesheet>

Needs to change

<xsl:value-of select="./ns:ReqProv/ns:CID"/>

to

<xsl:value-of select="//ns2:ReqProv/ns2:CID"/>

Because, in put xml ns2 is the namespace for the element CID.

OutPut:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">CID=TTTT&amp;TIME=18732081720160855&amp;HASH=40dad29c4ae9303c975639f7700bf517e6e72fbf5723c7905a74fde0d5452da0</string>
Rudramuni TP
  • 1,268
  • 2
  • 16
  • 26
1

You're almost there. You need to supply the <string> result element in the stylesheet template, fix your XPath expressions, and fix a mismatched namespace URI.

You'll want to change your template that matches "/" to something like the following:

  <xsl:template match="/">
    <!-- No need to use value-of here.
     Also use .// instead of ./, because ns:ReqProv is not a child of /. -->
    <xsl:variable name="CID" select=".//ns:ReqProv/ns:CID"/>
    <xsl:variable name="TIME" select=".//ns:ReqProv/ns:TIME"/>
    <xsl:variable name="HASH" select=".//ns:ReqProv/ns:HASH"/>

    <string>CID=<xsl:value-of select="$CID" />&amp;TIME=<xsl:value-of select="$TIME" />&amp;HASH=<xsl:value-of select="$HASH" /></string>

  </xsl:template>

You also need to change one of these two namespace URIs so that they match, in the input XML and the XSLT:

"http://TTTT.com/TTTT/TTTTestJSONESIRequest/"

and

"http://asurion.com/TTTT/TTTTTestJSONESIRequest/"

I'm guessing these are really the same in your actual input XML and XSLT, but you changed one of them in posting the question here. So you'll want to make sure that they match.

LarsH
  • 27,481
  • 8
  • 94
  • 152