Search code examples
xmlxsltxslt-1.0xslt-2.0xslt-3.0

Is there any way to dynamically assign header to con-cat the XML ELEMENTS in XSLT


I'm trying to build a common interface that converts 24 different XML Structures to Flate Files by concating XML elements. In Dell Boomi, we have an option to dynamically pass variable names to XSLT. As shown below:

<xsl:variable name="headers" select="boomi:get-ddp('DDP_Headers')"/>

We have stored all the 24 XML node names in the table rows. Ex:

CLIENTID,',',CLIENTNAME,',',CLIENTADDRESS,',',....,',',CLIENTCONTACT

PERSONID,',',PERSONNAME,',',PERSONADDRESS,',',....,',',PERSONCONTACT

......,',',.......,',',... etc

When we are passing the variable name and using that in Concat function it is taking as a string and printing only the String instead of XML Element values. Here is the code which we tried.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:boomi="http://boomi.com/custom-function">
  <xsl:output method="text" encoding="utf-8" />
  <xsl:variable name="headers" select="boomi:get-ddp('DDP_Headers')"/>
  <xsl:template match="/">
        <xsl:for-each select="//externalKPIClientProductivity">
    <xsl:value-of select="concat($headers,'&#xA;')" />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

The code is working fine with the below example:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:boomi="http://boomi.com/custom-function">
  <xsl:output method="text" encoding="utf-8" />

  <xsl:variable name="headers" select="boomi:get-ddp('DDP_Headers')"/>
  <xsl:template match="/">
        <xsl:for-each select="//externalKPIClientProductivity">
            <!-- <xsl:value-of select="@id" />  -->
    <!--<xsl:value-of
                select="concat($headers,'&#xA;')" />-->
                <xsl:value-of
                select="concat(CLIENTID,',',CLIENTNAME,',',CLIENTADDRESS,',',PAY,',',CLIENTLOCATION,',',XRFCODE,',',CLIENTCONTACT,'&#xA;')" /> 
        </xsl:for-each>
    </xsl:template>


</xsl:stylesheet>

Can someone please help me out how to pass these dynamic XML Elements to Concat function so that it will work as XML Elements and retrieve the data instead of printing the same String file as example:

CLIENTID,',',CLIENTNAME,',',CLIENTADDRESS,',',PAY,',',CLIENTLOCATION,',',XRFCODE,',',CLIENTCONTACT
CLIENTID,',',CLIENTNAME,',',CLIENTADDRESS,',',PAY,',',CLIENTLOCATION,',',XRFCODE,',',CLIENTCONTACT
CLIENTID,',',CLIENTNAME,',',CLIENTADDRESS,',',PAY,',',CLIENTLOCATION,',',XRFCODE,',',CLIENTCONTACT
..................

Thanks in advance!! DC


Solution

  • If your environment supports XSLT 3 with Saxon PE or EE (https://help.boomi.com/bundle/integration/page/int-XSLT_Stylesheet_Components_13300ba8-5e94-4b14-b6bd-5b90d7002233.html seems to suggest that) or uses Saxon 10 where xsl:evaluate is supported in all editions then one way would be to use e.g.

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all" version="3.0">
    
        <xsl:param name="fields" as="xs:string">foo,bar,baz</xsl:param>
    
        <xsl:output method="text"/>
    
        <xsl:template match="/">
            <xsl:for-each select="//item">
                <xsl:value-of separator=",">
                    <xsl:evaluate xpath="$fields" context-item="."/>
                </xsl:value-of>
                <xsl:text>&#10;</xsl:text>
            </xsl:for-each>
        </xsl:template>
    
    </xsl:stylesheet>
    

    Note that I have solely passed in the field names in the param and have chosen to delegate the separator introduction to xsl:value-of. You could however also use a string with any separator string inserted like in your question and pass it to xsl:evaluate:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all" version="3.0">
    
        <xsl:param name="fields" as="xs:string">foo,',',bar,',',baz</xsl:param>
    
        <xsl:output method="text"/>
    
        <xsl:template match="/">
            <xsl:for-each select="//item">
                <xsl:evaluate xpath="$fields" context-item="."/>
                <xsl:text>&#10;</xsl:text>
            </xsl:for-each>
        </xsl:template>
    
    </xsl:stylesheet>
    

    As a third option in XSLT 3 you could try a static parameter with a shadow attribute:

    <xsl:variable name="headers" static="yes" select="boomi:get-ddp('DDP_Headers')"/>
    
    <xsl:value-of _select="concat({$headers},'&#xA;')" />
    

    I can't tell, however, whether your extension function in your environment is set up to be used with static parameters.