Search code examples
xmlxslt-2.0

Adding comma(,) or "or" in depending on position in between conditional text using XSLT


I am having 5 products Product P, Q R, S, T input XML will differ some time one or two or three or four or five products may present but here 5 products XML posted some times products may repeat like product Q two times and product R three times and some products may miss

<products>
<product>Product_P</product>
<product>Product_Q</product>
<product>Product_R</product>
<product>Product_S</product>
<product>Product_T</product>
</products>

if input xml 2 products repeated:

<products>
    <product>Product_P</product>
    <product>Product_Q</product>
    <product>Product_R</product>
<product>Product_Q</product>
    <product>Product_R</product>
    <product>Product_S</product>
<product>Product_Q</product>
    <product>Product_R</product>
    <product>Product_T</product>
    </products>

if input xml 3 missing some products:

<products>
    <product>Product_P</product>
    <product>Product_Q</product>
    <product>Product_T</product>
    </products>

if input xml 4 other type products:

<products>
    <product>Product_P</product>
    <product>Product_U</product>
    <product>Product_R</product>
<product>Product_V</product>
    <product>Product_R</product>
    <product>Product_W</product>
<product>Product_Q</product>
    <product>Product_W</product>
    <product>Product_T</product>
    </products>

I need the output products related to P, Q, R, S,T no other products As mentioned below:

if input has one product that value equal to product="Product_Q", i want to Simply print

Product_Q

if input has two products value equal to product="Product_Q" and product="Product_S", i want to print

Product_Q or Product_S

if input has three products value equal to product="Product_P", product="Product_Q" and product="Product_R", i want to print

Product_P, Product_Q or Product_R

if input has four products values equal to product="Product_P", product="Product_Q", product="Product_R" and product="Product_T", i want to print

Product_P, Product_Q, Product_R, Product_S or Product_T

if input has five products values equal to product="Product_P", product="Product_Q", product="Product_R", product="Product_S" and product="Product_T", i want to print

Product_P, Product_Q, Product_R, Product_S  or Product_T

I have tried the below XSLT template

<xsl:template match="products">
           <xsl:variable name="product" select="products/product"/>
                    <xsl:if test="$product='Product_P'">
                        <xsl:text>Product_P</xsl:text>
                    </xsl:if>
<xsl:if test="$product='Product_P' and Product_Q">
                        <xsl:text>or</xsl:text>
                    </xsl:if>
<xsl:if test="$product='Product_Q'">
                        <xsl:text>Product_Q</xsl:text>
                    </xsl:if>
<xsl:if test="$product='Product_P' and Product_Q and Product_R">
                        <xsl:text>or</xsl:text>
                    </xsl:if>
<xsl:if test="$product='Product_R'">
                        <xsl:text>Product_R</xsl:text>
                    </xsl:if>
<xsl:if test="$product='Product_S'">
                        <xsl:text>Product_S</xsl:text>
                    </xsl:if>
<xsl:if test="$product='Product_T'">
                        <xsl:text>Product_T</xsl:text>
                    </xsl:if>
    </xsl:template>

Please assist thanks in Advance.


Solution

  • First step is to identify the distinct products:

    distinct-values(products/product)
    

    then filter the result with a predicate that selects the products you want to retain:

    [matches(., '^Product_[PQRST]$')]
    

    then add the formatting:

    <xsl:for-each select="distinct-values(products/product)[matches(., '^Product_[PQRST]$')]">
      <xsl:value-of select="if (position()=1) then ''
                            else if (position()=last()) then ' or '
                            else ', '"/>
      <xsl:value-of select="."/>
    </xsl:for-each>
    

    Note: your requirements still say nothing about the required order of the output.