XSLT mapping to concatenate similar node values

71 Views Asked by At

I want productType nodes to be combined and values to be concatenated.

I have sample input XML as below.

<Orders>
    <fromDate>Date</fromDate>
    <toDate>Date</toDate>
    <soldTo>String</soldTo>
    <shipTo>String</shipTo>
    <endUser>String</endUser>
    <customerPO>String</customerPO>
    <orderId>String</orderId>
    <consigneePO>String</consigneePO>
    <productType>
        <productTypeValue>String1</productTypeValue>
    </productType>
    <productType>
        <productTypeValue>String2</productTypeValue>
    </productType>
    <orderStatus>
        <orderStatusValue>String3</orderStatusValue>
    </orderStatus>
    <orderStatus>
        <orderStatusValue>String4</orderStatusValue>
    </orderStatus>
    <orderLineItemStatus>
        <orderLineItemStatusValue>String5</orderLineItemStatusValue>
    </orderLineItemStatus>
    <orderLineItemStatus>
        <orderLineItemStatusValue>String6</orderLineItemStatusValue>
    </orderLineItemStatus>
</Orders>

Expected output:

<Orders>
    <fromDate>Date</fromDate>
    <toDate>Date</toDate>
    <soldTo>String</soldTo>
    <shipTo>String</shipTo>
    <endUser>String</endUser>
    <customerPO>String</customerPO>
    <orderId>String</orderId>
    <consigneePO>String</consigneePO>
    <productType>
        <productTypeValue>String1,String2</productTypeValue>
    </productType>
    <orderStatus>
        <orderStatusValue>String3,String4</orderStatusValue>
    </orderStatus>
    <orderLineItemStatus>
        <orderLineItemStatusValue>String5,String6</orderLineItemStatusValue>
    </orderLineItemStatus>
</Orders>
1

There are 1 best solutions below

3
On

I get your desired result given your input set with the XSLT3 implementation.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all">
  
  <xsl:output indent="yes" />
  
  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template match="/Orders/*[ (name(.) || 'Value') eq name(*[1]) ]" >
    <xsl:if test="current() is /Orders/*[name(current()) eq name(.)][1]" >
      <xsl:copy>
        <xsl:apply-templates />
      </xsl:copy>
    </xsl:if>
  </xsl:template>
  
  <xsl:template match="/Orders/*/*">
    <xsl:copy>
      <xsl:value-of select="/Orders/*/*[name(current()) eq name(.)]" 
                    separator="," />
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>