Search code examples
xsltxslt-1.0xslt-2.0transformationbpel

How to generate comma separated string in to unbound xml structure


My Input like below

<ns0:input>AZX1,P81,IKJU,RED</ns0:input>

I have created target xsd with the unbound element to store the values

    <element name="Response">
    <complexType>
   <sequence>
    <element name="parameter" minOccurs="1" maxOccurs="unbounded">
     <complexType>
      <sequence>
       <element name="value" type="string"/>
      </sequence>
     </complexType>
    </element>
   </sequence>
  </complexType>
 </element>

SO I want the output in the below format.

<?xml version = '1.0' encoding = 'UTF-8'?>
<ns0:Response  xmlns:ns0="http://xmlns.oracle.com/CDM/Append/AppendBPELProcess">
   <ns0:parameter>
      <ns0:value>AZX1</ns0:value>
   </ns0:parameter>
   <ns0:parameter>
      <ns0:value>P81</ns0:value>
   </ns0:parameter>
   <ns0:parameter>
      <ns0:value>IKJU</ns0:value>
   </ns0:parameter>
   <ns0:parameter>
      <ns0:value>RED</ns0:value>
   </ns0:parameter>
</ns0:Response>

I tried with oraext:create-nodeset-from-delimited-string function in XSLT but it's giving me an error. Is there any way to populate this output in XSLT or using any template?


Solution

  • Here's a way you could do it using a recursive template in XSLT 1.0.

        <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:ns0="http://xmlns.oracle.com/CDM/Append/AppendBPELProcess"
        version="1.0">
    
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="/">
        <ns0:Response>
          <xsl:apply-templates select="//ns0:input"/>
        </ns0:Response>
      </xsl:template>
      
      <xsl:template match="ns0:input">
        <xsl:call-template name="inputs">
          <xsl:with-param name="input" select="."/>
        </xsl:call-template>
      </xsl:template>
      
      <!-- Recursive template will call itself for all comma separated elements -->
      <xsl:template name="inputs">
        <xsl:param name="input"/>
        <xsl:choose>
          <xsl:when test="contains($input,',')">
            <ns0:parameter>
              <ns0:value><xsl:value-of select="substring-before($input,',')"/></ns0:value>
            </ns0:parameter>
            <xsl:call-template name="inputs">
              <xsl:with-param name="input" select="substring-after($input,',')"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <ns0:parameter>
              <ns0:value><xsl:value-of select="$input"/></ns0:value>
            </ns0:parameter>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
      
    </xsl:stylesheet>
    

    See it working here : https://xsltfiddle.liberty-development.net/a9HjZW/1

    Update : Exclude first element

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:ns0="http://xmlns.oracle.com/CDM/Append/AppendBPELProcess"
        version="1.0">
    
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="/">
        <ns0:Response>
          <xsl:apply-templates select="//ns0:input"/>
        </ns0:Response>
      </xsl:template>
      
      <xsl:template match="ns0:input">
        <xsl:call-template name="inputs">
          <xsl:with-param name="input" select="."/>
          <xsl:with-param name="pos" select="1"/>
        </xsl:call-template>
      </xsl:template>
      
      <!-- Recursive template will call itself for all comma separated elements -->
      <xsl:template name="inputs">
        <xsl:param name="input"/>
        <xsl:param name="pos"/>
        <xsl:choose>
          <xsl:when test="contains($input,',')">
            <xsl:if test="$pos>1">
                <ns0:parameter>
                  <ns0:value><xsl:value-of select="substring-before($input,',')"/></ns0:value>
                </ns0:parameter>
            </xsl:if>
            <xsl:call-template name="inputs">
              <xsl:with-param name="input" select="substring-after($input,',')"/>
              <xsl:with-param name="pos" select="$pos+1"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:if test="$pos>1">
                <ns0:parameter>
                  <ns0:value><xsl:value-of select="$input"/></ns0:value>
                </ns0:parameter>
            </xsl:if>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
      
    </xsl:stylesheet>
    

    See it working here: https://xsltfiddle.liberty-development.net/a9HjZW/3